我在将绑定的项目对象移动到不同的数据数组时尝试保持组件处于活动状态。因为它被移动了,默认的keep-alive标签不起作用。
当我的应用中的动态组件使用外部库时,我需要这样做以改善加载时间。
简化示例:(https://jsfiddle.net/eywraw8t/24419/)
HTML:
<div id="app">
<div v-for="list in lists">
<h1>{{ list.title }}</h1>
<ul>
<draggable v-model="list.items" :options="{group: 'list-items'}">
<list-item
v-for="item in list.items"
:key="item.key"
:content="item.content">
</list-item>
</draggable>
</ul>
</div>
</div>
JS:
Vue.component('list-item', {
props: {
content: {
required: true
}
},
mounted () {
document.body.insertAdjacentHTML('beforeend', 'Mounted! ');
},
template: '<li>{{ content }}</li>'
})
new Vue({
el: "#app",
data: {
lists: [
{
title: 'List 1',
items: [
{ key: 'item1', content: 'Item 1' },
{ key: 'item2', content: 'Item 2' },
{ key: 'item3', content: 'Item 3' }
]
},
{
title: 'List 2',
items: [
{ key: 'item4', content: 'Item 4' },
{ key: 'item5', content: 'Item 5' },
{ key: 'item6', content: 'Item 6' }
]
}
]
}
})
答案 0 :(得分:1)
我调查了你的问题,我想我可能会找到一个解决方案,我不能用js小提琴做,但我会试着解释一下:
在你的js小提琴中,mount被挂钩在你的list-item组件中,所以每次状态改变时(拖动时)都会触发事件。
我创建一个带有主模板组件(componentX)的设置,带有挂载的功能,然后创建一个单独的列表项组件
在我的示例中,您将看到在开始时挂载两次,这是正常的,因为我们有2个列表!但是当你开始拖放时,你将无法获得额外的已安装事件
您可以通过以下方式下载解决方案:
http://www.bc3.eu/download/test-vue.zip
这是一个vue cli项目,因此您只需npm run dev
即可启动本地服务器
答案 1 :(得分:1)
如果问题只是缓存昂贵的html构建问题,您可以通过从模板中删除list-item
组件并在app.mounted()
中提前构建它们来实现。
这在现实场景中的效果取决于item.content
的性质及其生命周期。
console.clear()
const ListItem = Vue.component('list-item', {
props: {
content: {
required: true
}
},
mounted () {
document.body.insertAdjacentHTML('beforeend', 'Mounted! ');
},
template: '<li>{{ content }}</li>'
})
new Vue({
el: "#app",
methods: {
getHtml(content) {
const li = new ListItem({propsData: {content}});
li.$mount()
return li.$el.outerHTML
}
},
mounted () {
this.lists.forEach(list => {
list.items.forEach(item => {
const cacheHtml = this.getHtml(item.content)
Vue.set( item, 'cacheHtml', cacheHtml )
})
})
},
data: {
lists: [
{
title: 'List 1',
items: [
{ key: 'item1', content: 'Item 1' },
{ key: 'item2', content: 'Item 2' },
{ key: 'item3', content: 'Item 3' }
]
},
{
title: 'List 2',
items: [
{ key: 'item4', content: 'Item 4' },
{ key: 'item5', content: 'Item 5' },
{ key: 'item6', content: 'Item 6' }
]
}
]
}
})
ul {
margin-bottom: 20px;
}
li:hover {
color: blue;
cursor: move;
}
h1 {
font-size: 20px;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/15.0.0/vuedraggable.min.js"></script>
<div id="app">
<div v-for="list in lists">
<h1>{{ list.title }}</h1>
<ul>
<draggable v-model="list.items" :options="{group: 'list-items'}">
<div v-for="item in list.items" :key="item.key">
<li v-html="item.cacheHtml"></li>
</div>
</draggable>
</ul>
</div>
</div>
要在item.content
更改时保持反应,您需要更多代码。
item.content
的副本添加到缓存(您可以使用参数化计算属性更优雅地执行此操作)。
为了模拟item.content更改,我在mount()中添加了setTimeout。
console.clear()
const ListItem = Vue.component('list-item', {
props: {
content: {
required: true
}
},
mounted () {
document.body.insertAdjacentHTML('beforeend', 'Mounted! ');
},
template: '<li>{{ content }}</li>'
})
new Vue({
el: "#app",
methods: {
getHtml(content) {
const li = new ListItem({
propsData: { content }
});
li.$mount()
return li.$el.outerHTML
},
cacheHtml(item) {
if (item.cache && item.cache.content === item.content) {
return item.cache.html
} else {
const html = this.getHtml(item.content)
const cache = {content: item.content, html}
Vue.set(item, 'cache', cache)
}
}
},
mounted () {
this.lists.forEach(list => {
list.items.forEach(item => {
this.cacheHtml(item)
})
})
setTimeout(() =>
Vue.set( this.lists[0].items[0], 'content', 'changed' )
,2000)
},
data: {
lists: [
{
title: 'List 1',
items: [
{ key: 'item1', content: 'Item 1' },
{ key: 'item2', content: 'Item 2' },
{ key: 'item3', content: 'Item 3' }
]
},
{
title: 'List 2',
items: [
{ key: 'item4', content: 'Item 4' },
{ key: 'item5', content: 'Item 5' },
{ key: 'item6', content: 'Item 6' }
]
}
]
}
})
ul {
margin-bottom: 20px;
}
li:hover {
color: blue;
cursor: move;
}
h1 {
font-size: 20px;
font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.6.0/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/15.0.0/vuedraggable.min.js"></script>
<div id="app">
<div v-for="list in lists">
<h1>{{ list.title }}</h1>
<ul>
<draggable v-model="list.items" :options="{group: 'list-items'}">
<div v-for="item in list.items" :key="item.key">
<li v-html="cacheHtml(item)"></li>
</div>
</draggable>
</ul>
</div>
</div>