如何动态地向内容添加元素?示例如下:
<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看不到新的元素。
答案 0 :(得分:9)
我刚刚了解了SELECT a.family, coalesce(sum(b.tpt), 0) AS total
FROM tbl AS a
LEFT JOIN tbl AS b ON a.tool = b.tool AND a.family != b.family
GROUP BY a.family
,它似乎非常适合您的需求。使用$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);
答案 1 :(得分:6)
<强>更新强>
基于this answer,您可以在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);
&#13;
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="vue">
<component :is="dynamicComponent" />
</div>
&#13;
Vue绑定不会发生在插值HTML上。您需要Vue视为模板的内容,例如a partial。但是,Vue仅将绑定应用于部分一次;您无法返回并更改模板文本并重新绑定。因此,每次模板文本更改时,您都必须创建一个新的部分。
您可以在HTML中添加<partial>
标记/元素,并且它接受变量名称,因此过程为:
每次发生变化时注册新内容都有点可怕,所以如果可能的话,最好使用具有更结构化模板的组件,但如果你真的需要完全动态的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);
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<partial :name="partialName"></partial>
&#13;
答案 2 :(得分:0)
自partial
已从VueJS 2(https://vuejs.org/v2/guide/migration.html#Vue-partial-removed)
更好的方法可能是创建一个处理其内容并创建适当DOM元素的组件
上述组件将通过可点击链接替换主题标签
<process-text>Hi #hashtag !</process-text>
Vue.component('process-text', {
render: function (createElement) {
var hashtagRegex = /(^|\W)(#[a-z\d][\w-]*)/ig
var text = this.$slots.default[0].text
var list = text.split(hashtagRegex)
var children = []
for (var i = 0; i < list.length; i++) {
var element = list[i]
if (element.match(hashtagRegex)) {
children.push(createElement('a', {
attrs: {
href: 'https://www.google.fr/search?q=' + element,
target: "_blank"
},
domProps: {
innerHTML: element
}
}))
} else {
children.push(element)
}
}
}
return createElement('p', {}, children) // VueJS expects root element
})
答案 3 :(得分:0)
我发现使用自定义html工作正常的最佳解决方案看起来像这样,就像你每次html属性更改时创建新组件一样。实际上没有人这样做,我们只使用computed属性来创建新组件。
它的外观如下:
new Vue({
el: "#root",
data: {
value: '',
name: 'root',
htmlData: '<div><input @input="onInputProxy($event)" ' +
'v-model="value" ' +
'v-for="i in 3" ' +
':ref="`customInput${i}`"></div>'
},
computed: {
// our component is computed property which returns the dict
htmlDataComponent () {
return {
template: this.htmlData, // we use htmlData as template text
data() {
return {
name: 'component',
value: ''
}
},
created () {
// value of "this" is formComponent
console.log(this.name + ' created');
},
methods: {
// proxy components method to parent method,
// actually you done have to
onInputProxy: this.onInput
}
}
}
},
methods: {
onInput ($event) {
// while $event is proxied from dynamic formComponent
// value of "this" is parent component
console.log(this.name + ' onInput');
// use refs to refer to real components value
console.log(this.$refs.htmlDataComponent.value);
console.log(this.$refs.htmlDataComponent.$refs.customInput1);
console.log(this.$refs.htmlDataComponent.$refs.customInput2);
console.log(this.$refs.htmlDataComponent.$refs.customInput3);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js">
</script>
<div id="root">
<component ref="htmlDataComponent"
v-if="htmlData"
:is="htmlDataComponent"></component>
</div>
我没有检查它的内存效率,但看起来效果很好。
答案 4 :(得分:0)
@RoyJ答案的修改版本,可在Vue.js v2.6.10中使用
new Vue({
...,
computed: {
inner_html() {
return ...; // any raw html
},
},
directives: {
dynamic: {
bind(el, binding) {
el.innerHTML = binding.value;
},
update(el, binding) {
el.innerHTML = binding.value;
},
},
},
template: `<div v-dynamic='inner_html'></div>`,
});
答案 5 :(得分:0)
在Vue.js 2中更容易:
new Vue({
...,
computed: {
inner_html() {
return ...; // any raw html
},
},
template: `<div v-html='inner_html'></div>`,
});