【发布时间】:2018-07-27 23:11:58
【问题描述】:
我有一个用例(如下),我需要 mount(如果这是正确的术语)一个通过 jQuery 插入 DOM 的 Vue.js 组件模板,我可以设置一个 Mutation Observer 或对某些响应突变发生时触发的事件。
我正在使用 Vue.js v2
下面是我整理的一个简单例子来说明这一点:
直播 jsFiddle https://jsfiddle.net/w7q7b1bh/2/
下面的 HTML 包含两个组件的 inlined-templates
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="app">
<!-- The use of inline-template is required for my solution to work -->
<simple-counter inline-template>
<button v-bind:style="style" v-on:click="add">clicks: {{ counter }}</button>
</simple-counter>
<simple-counter inline-template>
<button v-on:click="counter += 1">{{ counter }}</button>
</simple-counter>
</div>
<button id="mutate">Mutate</button>
js:
// simple counter component
Vue.component('simple-counter', {
data: function() {
return {
counter: 0,
style: {
color: 'red',
width: '200px'
}
}
},
methods: {
add: function() {
this.counter = this.counter + 1;
this.style.color = this.style.color == 'red' ? 'green' : 'red';
}
}
})
// create the Vue instance
var initV = () => new Vue({
el: '#app'
});
// expose the instance for later use
window.v = initV();
// click handler that will add a new `simple-counter` template to the Vue.el scope
$('#mutate').click(function(){
$('#app').append(` <div is="simple-counter" inline-template>
<button v-bind:style="style" v-on:click="add">click to add: <span class="inactive" v-bind:class="{ active: true }">{{ counter }}</span></button></div>`)
// do something after the template is incerted
window.v.$destroy()
window.v = initV(); // does not work
})
如代码中所述,销毁重新实例化 Vue 实例不起作用,我理解为什么,组件的模板在第一次 Vue 实例化时更改为最终的 HTML,当您尝试第二次实例化时,模板不存在,组件不存在mounted
我希望能够在突变后找到新添加的组件并仅安装那些,这可能吗?以及如何?
更新:
我能够通过将 el 设置为 DOM 的特定变异部分而不是整个 #app 树实例化一个新的 Vue 实例来找到一种方法:
$('#mutate').click(function(){
var appended =
$(`
<div is="simple-counter" inline-template>
<button v-bind:style="style" v-on:click="add">
click to add: {{ counter }}
</button>
</div>`
).appendTo($('#app'));
var newV = new Vue({el: appended[0]});
});
似乎有效,但看起来也很丑陋,我不确定这可能会产生什么其他影响..
用例:
我正在研究一种为名为 Adobe Experience Manager (AEM) 的 CMS 编写 Vue.js 组件的方法。
我使用 inlined-template 编写我的组件,这让我利用了 SEO 以及使用另一种称为 HTL 的模板语言进行服务器端渲染的优势。
AEM 创作的工作方式是,当(通过对话框)编辑组件时,该特定组件会在服务器端重新渲染,然后注入回 DOM 以替换旧组件,所有这些都通过 Ajax 完成和 jQuery(无浏览器刷新)。
这是一个例子
AEM 组件模板:
<button>${properties.buttonTitle}</button>
作者可能会这样做:
- 作者访问创作页面
- 打开按钮组件对话框进行编辑
- 将 buttonTitle 更改为“新按钮标题”
- 保存
保存后,发送一个 ajax,组件 HTML 在服务器上重新渲染,返回的是新的 HTML。该 HTML 现在通过 jQuery 替换旧的 HTML(改变 DOM)
这对于静态组件来说很好,但是如果这是一个 Vue.js 组件,我如何在保持其他组件挂载的同时动态挂载它。
一个简单的解决方案是刷新页面......但这只是糟糕的体验......必须有更好的方法。
【问题讨论】:
-
将新部分实例化为新的 Vue 似乎是正确的方法,但似乎绑定不起作用,因为它们在另一个 Vue 中。但是,他们可能会在作用域插槽中。
-
有没有办法手动挂载组件,然后将它们添加到 Vue 实例中?
-
我真的不知道。让其他东西修改 DOM 然后告诉 Vue 接管这些更改是非常不符合 Vue 的。如果您的服务器只提供不同的数据并且前端可以进行 DOM 更新,那就更好了。
-
我完全同意,这只会发生在创作界面上。对于最终用户来说,这永远不会发生。我认为现在只用更新的 DOM 创建一个新的 Vue 实例就足够了。
-
可能会有帮助:css-tricks.com/…
标签: javascript vue.js vuejs2 aem