Vue.js中的动态html元素

use*_*653 10 vue.js

如何动态地向内容添加元素?示例如下:

<template>
    {{{ message | hashTags }}}
</template>

<script>
    export default {
        ...

        filters: {
            hashTags: function(value) {
                // Replace hash tags with links
                return value.replace(/#(\S*)/g, '<a v-on:click="someAction()">#$1</a>')
            }
        }
    }
</script>
Run Code Online (Sandbox Code Playgroud)

问题是,如果我按下链接,则不会触发任何操作.Vue看不到新元素.

Roy*_*y J 9

我刚学会了$compile,它似乎非常适合你的需要.一个非常简单的指令使用$compile避免了所有注册.

Vue.directive('dynamic', function(newValue) {
    this.el.innerHTML = newValue;
    this.vm.$compile(this.el);
});

var v = new Vue({
  el: 'body',
  data: {
    message: 'hi #linky'
  },
  computed: {
    messageAsHtml: function() {
      return this.message.replace(/#(\S*)/g, '<a v-on:click="someAction()">#$1</a>');
    }
  },
  methods: {
    someAction: function() {
      console.log('Action!');
    }
  }
});

setTimeout(() => {
  v.$set('message', 'another #thing');
}, 2000);
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div v-dynamic="messageAsHtml"></div>
Run Code Online (Sandbox Code Playgroud)


Roy*_*y J 7

更新: 基于此答案,您可以在Vue 2中执行类似的动态模板组件.您可以在部分中实际设置组件规范computed并使用:is

var v = new Vue({
  el: '#vue',
  data: {
    message: 'hi #linky'
  },
  computed: {
    dynamicComponent: function() {
      return {
        template: `<div>${this.hashTags(this.message)}</div>`,
        methods: {
          someAction() {
            console.log("Action!");
          }
        }
      }
    }
  },
  methods: {
    hashTags: function(value) {
      // Replace hash tags with links
      return value.replace(/#(\S*)/g, '<a v-on:click="someAction">#$1</a>')
    }
  }
});

setTimeout(() => {
  v.message = 'another #thing';
}, 2000);
Run Code Online (Sandbox Code Playgroud)
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="vue">
  <component :is="dynamicComponent" />
</div>
Run Code Online (Sandbox Code Playgroud)

内插HTML不会发生Vue绑定.你需要一些Vue看作模板的东西,就像部分一样.但是,Vue仅将绑定应用于部分一次; 您无法返回并更改模板文本并重新绑定.因此,每次模板文本更改时,您都必须创建一个新的部分.

有一个<partial>标签/元素,你可以把你的HTML,它接受一个变量名,所以程序是:

  • 模板HTML更改
  • 为新模板HTML注册新的部分名称
  • 更新名称变量,以便呈现新的部分

每次有变化时注册新内容都有点可怕,所以如果可能的话,最好使用具有更结构化模板的组件,但如果你真的需要带有绑定的完全动态HTML,它就可以工作.

下面的示例以一条消息开始,根据您的过滤器进行链接,并在两秒后进行更改message.

您可以使用messagepartial作为注册的名称,但是您需要一个在执行注册后返回该名称的computed,否则它将尝试在注册名称之前呈现.

var v = new Vue({
  el: 'body',
  data: {
    message: 'hi #linky'
  },
  computed: {
    partialName: function() {
      Vue.partial(this.message, this.hashTags(this.message));
      return this.message;
    }
  },
  methods: {
    someAction: function() {
      console.log('Action!');
    },
    hashTags: function(value) {
      // Replace hash tags with links
      return value.replace(/#(\S*)/g, '<a v-on:click="someAction()">#$1</a>')
    }
  }
});

setTimeout(() => {
  v.$set('message', 'another #thing');
}, 2000);
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<partial :name="partialName"></partial>
Run Code Online (Sandbox Code Playgroud)


Pav*_*vel 5

在 Vue.js 2 中更容易:

new Vue({
    ...,
    computed: {
        inner_html() {
            return ...; // any raw html
        },
    },
    template: `<div v-html='inner_html'></div>`,
});
Run Code Online (Sandbox Code Playgroud)

  • 渲染 html 的概念很棒,但是嵌入的 v-model 或 v-bind:is 或 @click 处理程序都不起作用。 (2认同)
  • 这更接近......它实际上确实动态渲染 html,但如果它有任何 v-model 或其他 vue 指令,它们将不会被连接为反应性的。 (2认同)