Vue.js 中的动态 html 元素

新手上路,请多包涵

如何将元素动态添加到内容中?下面的例子:

 <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>

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

原文由 user2058653 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 951
2 个回答

更新: 基于 此答案,您可以在 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);
 <script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="vue">
  <component :is="dynamicComponent" />
</div>

Vue 绑定不会发生在插入的 HTML 上。你需要一些 Vue 视为模板的东西,比如 部分.然而,Vue 只对部分应用绑定一次;您无法返回并更改模板文本并重新绑定。因此,每次模板文本更改时,您都必须创建一个新的部分。

有一个 <partial> 标记/元素可以放入您的 HTML 中,它接受一个变量名,所以过程是:

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

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

下面的示例以一条消息开始,根据您的过滤器链接化,两秒钟后,更改 message

您可以只使用 message 作为注册部分的名称,但您需要在注册后返回该名称的计算,否则它将尝试在注册名称之前呈现。

 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);
 <script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<partial :name="partialName"></partial>

原文由 Roy J 发布,翻译遵循 CC BY-SA 4.0 许可协议

我刚刚了解了 $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);
 <script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div v-dynamic="messageAsHtml"></div>

原文由 Roy J 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题