vue实现列表联动插件
Vue 列表联动插件实现方案
基于 v-model 的双向绑定
通过 Vue 的 v-model 实现父子组件数据同步,适用于简单联动场景。
<template>
<div>
<parent-list v-model="selectedItems" :items="parentItems" />
<child-list :items="filteredChildItems" />
</div>
</template>
<script>
export default {
data() {
return {
selectedItems: [],
parentItems: [...],
allChildItems: [...]
}
},
computed: {
filteredChildItems() {
return this.allChildItems.filter(item =>
this.selectedItems.includes(item.parentId)
)
}
}
}
</script>
使用事件总线通信
通过 Vue 的 EventBus 实现跨组件通信,适合复杂层级结构。
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
// ParentComponent.vue
EventBus.$emit('parent-selected', selectedIds)
// ChildComponent.vue
EventBus.$on('parent-selected', ids => {
this.filteredItems = this.allItems.filter(item => ids.includes(item.parentId))
})
封装可复用插件
创建独立插件实现标准化列表联动功能。
// list-linkage.js
const ListLinkage = {
install(Vue) {
Vue.mixin({
methods: {
$updateLinkedList(sourceKey, targetKey, filterFn) {
this.$watch(sourceKey, newVal => {
this[targetKey] = this.allItems.filter(item => filterFn(item, newVal))
}, { deep: true })
}
}
})
}
}
// main.js
import ListLinkage from './list-linkage'
Vue.use(ListLinkage)
// 组件内使用
this.$updateLinkedList('selectedParents', 'filteredChildren', (child, parents) => {
return parents.some(p => p.id === child.parentId)
})
基于 Provide/Inject 的层级传递
适合深层嵌套组件结构,通过依赖注入实现数据共享。
// 祖先组件
export default {
provide() {
return {
listLinkage: {
selected: Vue.observable([]),
update: this.updateSelection
}
}
}
}
// 后代组件
export default {
inject: ['listLinkage'],
methods: {
handleSelect(item) {
this.listLinkage.update(item.id)
}
}
}
性能优化建议
对于大数据量场景应添加防抖处理和虚拟滚动。
import debounce from 'lodash/debounce'
export default {
methods: {
updateFilter: debounce(function(searchTerm) {
this.filtered = this.items.filter(i =>
i.name.includes(searchTerm)
)
}, 300)
}
}
完整插件示例
以下是封装成 npm 包的完整插件结构示例:
// index.js
export default {
install(Vue, options = {}) {
const defaultOptions = {
debounceTime: 200,
linkageKey: 'linkageId'
}
const config = { ...defaultOptions, ...options }
Vue.directive('list-linkage', {
bind(el, binding, vnode) {
const source = binding.value.source
const target = binding.value.target
const filterFn = binding.value.filter || defaultFilter
vnode.context.$watch(
source,
debounce(newVal => {
vnode.context[target] = vnode.context.allItems
.filter(item => filterFn(item, newVal))
}, config.debounceTime),
{ deep: true }
)
}
})
function defaultFilter(item, sourceVal) {
return sourceVal.includes(item[config.linkageKey])
}
}
}
使用时可全局注册或按需引入,通过指令方式实现列表联动:
<template>
<div v-list-linkage="{ source: 'selected', target: 'filtered' }">
<!-- 联动列表内容 -->
</div>
</template>






