Vue.js 中的动态 html 元素 [英] Dynamic html elements in Vue.js
问题描述
如何将元素动态添加到内容中?下面的例子:
{{{ 消息 |标签}}}</模板><脚本>导出默认{...过滤器:{哈希标签:函数(值){//用链接替换哈希标签return value.replace(/#(\S*)/g, '<a v-on:click="someAction()">#$1</a>')}}}
问题是,如果我按下链接,则不会触发任何操作.Vue 看不到新元素.
更新:基于 这个答案,您可以在 Vue 2 中做一个类似的动态模板组件.您实际上可以设置组件规范在 computed
部分并使用 绑定它:是
var v = new Vue({el: '#vue',数据: {消息:'嗨#linky'},计算:{动态组件:函数(){返回 {模板:`<div>${this.hashTags(this.message)}</div>`,方法: {someAction() {console.log("动作!");}}}}},方法: {哈希标签:函数(值){//用链接替换哈希标签return value.replace(/#(\S*)/g, '<a v-on:click="someAction">#$1</a>')}}});setTimeout(() => {v.message = '另一个#thing';}, 2000);
<script src="//unpkg.com/vue@latest/dist/vue.js"></script><div id="vue"><component :is="dynamicComponent"/>
Vue 绑定不会发生在插入的 HTML 上.你需要一些 Vue 视为模板的东西,比如 a partial.然而,Vue 只对部分应用绑定一次;您无法返回并更改模板文本并重新绑定.所以每次模板文本改变时,你必须创建一个新的部分.
有一个 <partial>
标签/元素可以放在你的 HTML 中,它接受一个变量名,所以过程是:
- 模板 HTML 更改
- 为新模板 HTML 注册新的部分名称
- 更新名称变量以便呈现新的部分
每次发生变化时都注册新的东西有点可怕,所以如果可能的话,最好使用带有更结构化模板的组件,但如果你真的需要完全动态的带有绑定的 HTML,它可以工作.
下面的示例从一条消息开始,根据您的过滤器进行链接,两秒钟后,更改message
.
您可以只使用 message
作为注册部分的名称,但是您需要一个在注册后返回该名称的计算,否则它会在名称注册之前尝试渲染.
var v = new Vue({el: '身体',数据: {消息:'嗨#linky'},计算:{部分名称:函数(){Vue.partial(this.message, this.hashTags(this.message));返回 this.message;}},方法: {someAction:函数(){console.log('动作!');},哈希标签:函数(值){//用链接替换哈希标签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>
How is it possible to add elements dynamically to the content? Example below:
<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>
Problem is that if I press the link no action will fire. Vue do not see new elements.
Update:
Based on this answer, you can do a similar dynamic-template component in Vue 2. You can actually set up the component spec in the computed
section and bind it using :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 bindings don't happen on interpolated HTML. You need something Vue sees as a template, like a partial. However, Vue only applies bindings to a partial once; you can't go back and change the template text and have it re-bind. So each time the template text changes, you have to create a new partial.
There is a <partial>
tag/element you can put in your HTML, and it accepts a variable name, so the procedure is:
- the template HTML changes
- register new partial name for the new template HTML
- update name variable so the new partial is rendered
It's a little bit horrible to register something new every time there's a change, so it would be preferable to use a component with a more structured template if possible, but if you really need completely dynamic HTML with bindings, it works.
The example below starts out with one message, link-ified as per your filter, and after two seconds, changes message
.
You can just use message
as the name of the partial for registering, but you need a computed that returns that name after doing the registering, otherwise it would try to render before the name was registered.
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>
这篇关于Vue.js 中的动态 html 元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!