Vue2 Router link from server data Vue2 Router link from server data vue.js vue.js

Vue2 Router link from server data


If I understand you correctly your issue is not with the link parsing, this looks fine. You want to compile the resulting HTML so Vue router can kick in. There is a function Vue.compile which can help you:

Vue.component('my-component', {  template: '<div></div>',  props: {    html: String  },  mounted() {    let { render, staticRenderFns } = Vue.compile(this.html);    new Vue({ el: this.$el, render, staticRenderFns, router })  }});

With this component you can specify any HTML using the prop html, which will then get compiled in the mounted event and will replace the component template. Please note the router being passed to new Vue(), this is a reference to your Vue router, which is needed so all the <router-link> tags in your HTML can be resolved.

Now you can use this component to compile your HTML like this:

<my-component :html="content"></my-component>

where var content = parseVueLinks('<a href="/about-us">Text</a>').

You can see a working example over here https://codepen.io/anon/pen/BmmjwV


I think your replacement regex is good but is missing one /.Indeed, after testing it, I see the result of parsing :

<a href="/about-us">Text</a>

outputs :

<router-link :to="{ path: 'about-us'}">Text</router-link>

instead of correct:

<router-link :to="{ path: '/about-us'}">Text</router-link>

(see about-us instead of /about-us)

Could you try this,please:

function parseVueLinks($value){    $pattern = "/<a([^>]*) href=\\\"[^http|https|mailto|tel]([^\\\"]*)\"([^>]*)>(.*?)<(\\/a>)/";    $replace = "<router-link$1 :to=\"{ path: '/$2'}\">$4</router-link>";    return preg_replace($pattern, $replace, $value);}


The simplest regex pattern to do this is /<a href="([^>]*)">(.+)<\/a>/.

Test example:

console.clear() const parseVueLinks = ($value) => {  const re = /<a href="([^>]*)">(.+)<\/a>/g;  const matches = re.exec($value);  return `<router-link :to="{ path: '${matches[1]}'}">${matches[2]}</router-link>`}console.log(parseVueLinks('<a href="/about-us">Text</a>'))console.log(parseVueLinks('<a href="http://google.com">Goooooogle</a>'))


I don't know PHP, but am guessing the equivalent PHP might be (tested at https://www.functions-online.com/preg_match.html):

function parseVueLinks($value){  $pattern = "/<a href="([^>]*)">(.+)<\/a>/";  $matches = [];  preg_match($pattern, $replace, $matches);  return "<router-link :to=\"{ path: '" + $matches[1] + "'}\">" + $matches[2] + "</router-link>"; }

I'm wondering about the presence of http|https|mailto|tel in your regex, does this mean you want to do some validation on the link?

If so, using preg_match() allows a second regex step to be performed on $matches[1] before output. It would seem simpler to validate as a second step rather than using one big regex.


Edit following comment

The issue is not in regex. It is in Vue not parsing content pulled from the server

This may not apply if you're using server side rendering, but this is how I apply links from content.

MyComponent.ts

<template>  <div class="row">    ...      <router-link :to="'/' + measure.link" class="measure">        <i class="measure-icon fa fa-lg" :class="measure.icon" aria-hidden="true">          <span class="title">{{measure.title}}</span>        </i>      </router-link>

Here, measure is an object that is fetched from the server. I you are fetching the full <router-link>, that may work with a Dynamic Component but it seems like overkill, since you know the element will be a <router-link.

Note, if there's also a problem with the server responding with 404 to the click, you can use hash-mode routing (default) by adding # before the link, e.g #/about-us.

Alternatively, set history mode in the Vue router.

const router = new Router({  routes,  mode: 'history'})

This requires the server to redirect to index.html for a 404. See HTML History Mode.

Also, you then need to handle 404 in Vue with a catch-all route,

const routes = [  ...  { path: '*', component: NotFoundComponent },]