Vue2 Router Link from Server Data

I have a Vue2 SPA page that downloads content from a server. It is available for editing by the client in the CMS.

When the user adds a relative link (let say / about-us), this should be selected by Vue and treated as a menu link (which already has / a link to us).

However, the link to / about -us added to the content reloads the entire page, so it is not selected as the vue route.

How can I connect a router to such links?

What I have done so far is changing the contents in the response image.

So, I am essentially changing

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

in

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

Using:

 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); } 

Still out of luck.

How is this possible?

+5
source share
3 answers

If you correctly understood that your problem is not related to parsing links, this looks normal. You want to compile the resulting HTML so that the Vue router can come in. There is a Vue.compile function that 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 prop html , which will then be compiled into the mounted event and replace the component template. Note that the router passes new Vue() , this is a link to your Vue router, which is necessary so that all <router-link> tags in your HTML can be resolved.

Now you can use this component to compile your HTML as follows:

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

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

Here you can see a working example https://codepen.io/anon/pen/BmmjwV

+3
source

I think your regular expression is suitable, but one is missing. Indeed, after testing, I see the result of the parsing:

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

outputs:

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

instead of the correct one:

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

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

Could you please try:

 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); } 
+1
source

The simplest regex pattern for 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 do not know PHP, but I assume that the equivalent PHP can 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 am interested to know about the presence of http|https|mailto|tel in your regular expression, does this mean that you want to do some verification in the link?

If so, using preg_match() allows you to perform the second step of the regular expression on $matches[1] before exiting. It would seem easier to check as a second step, rather than using one large regular expression.


Edit next comment

The problem is not regular expression. It is in Vue that content pulled from the server does not understand

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

Mycompponent.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 retrieved from the server. I get a full <router-link> that can work with the Dynamic component , but it seems redundant since you know the element will be <router-link .

Please note that if there is a problem with the server responding with 404 , you can use hash mode routing (default) by adding # before the link, for example #/about-us .

Alternatively, set the history mode in the Vue router.

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

This requires the server to be redirected to index.html for 404. See HTML History Mode .

In addition, you need to handle 404 in Vue using the catch-all route,

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

Source: https://habr.com/ru/post/1273237/


All Articles