Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue components / elements in v-html

I have a post.text data that contains the text of a blog post submitted by the user Much like in Twitter, users can mention other users with the sintax I am tagging @user1 in this post. When rendering the post, I want to replace all the @username instances with links to the page of the mentioned user.

With a regex match / replace I can easily transform the mentioned @username into something like (I'm using vue-router):

I am tagging <router-link :to="{name: 'user', params: {userId: post.userId}}">{{ dPost.user_name }}</router-link> in this post

But when I use it like this:

<p v-html="preparedText"></p>

vue doesn't reprocess the html to bind its own tags.

How to solve this problem? Thanks

like image 248
pistacchio Avatar asked Oct 05 '17 11:10

pistacchio


People also ask

How do I use Vue components in HTML?

The simplest way to get started with Vue is to grab the development version script for it and add it to the head tag of your HTML file. Then you can start Vue code inside the HTML file inside of script tags. And have the Vue code connect up with an existing element on your HTML page.

What is V-HTML in VueJS?

The v-html directive is a Vue. js directive used to update a element's inner HTML with our data. This is what separates it from v-text which means while v-text accepts string and treats it as a string it will accept string and render it into HTML.

What can I use instead of V in HTML?

Reintroduce Triple Curly Braces {{{ }}} as a v-html alternative #7431.

Should I use V-HTML?

If you think you need v-html , re-think three more times before implementing it. If you still think you need it, make sure there is no way any user generated content is displayed there. If it must be displayed, then use sanitizer to make sure it does not make your application vulnerable to XSS attacks.


1 Answers

What you want to do sortof breaks the normal Vue paradigm, but it can be done using Vue.compile. You'll need to use Vue.compile to generate the render functions and then manually create a new Vue instance once your component has been mounted.

Here's an example:

Vue.component('post', {
  template: `<div></div>`,
  props: { text: String },
  mounted() {
    let regex = /\B\@([\w\-]+)/gim;
    let username = this.text.match(regex)[0];
    let linkText = this.text.replace(regex, `<a href="#">${username}</a>`);
    let res = Vue.compile(`<p>${linkText}</p>`);
    
    let { render, staticRenderFns } = res;
    new Vue({ el: this.$el, render, staticRenderFns })
  }
})

new Vue({
  el: '#app',
  data() {
    return { text: `Hi @user1, how are you?` }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<div id="app">
  <post :text="text"></post>
</div>
like image 122
thanksd Avatar answered Sep 23 '22 17:09

thanksd