下面是Vue实现无限级树形选择器的完整攻略:
1. 需求分析
首先,我们需要确定本次开发的需求。本次开发要实现一个无限级别的树形选择器,包含以下要求:
- 根据给定的数据结构渲染树形结构;
- 支持无限极展开和收起;
- 支持多选和单选;
- 支持选择器搜索;
2. 技术选型
基于此,我们可以选择使用Vue.js框架进行开发,并结合Vue组件,Element-ui库来完成组件的构建。
3. 数据结构设计
树形结构的展开和收起是通过组件之间的嵌套来实现的,因此我们需要确定树形结构的数据结构设计。
例如如下的数据结构:
{
"label": "一级选择器",
"value": "0",
"children": [{
"label": "二级选择器1",
"value": "1-1",
"children": [{
"label": "三级选择器1-1",
"value": "1-1-1"
}, {
"label": "三级选择器1-2",
"value": "1-1-2"
}]
}, {
"label": "二级选择器2",
"value": "1-2",
"children": [{
"label": "三级选择器2-1",
"value": "1-2-1"
}, {
"label": "三级选择器2-2",
"value": "1-2-2"
}]
}]
}
4. 组件设计
4.1 父组件
父组件的作用是渲染整个树形结构,并且控制每个子组件的展开和收起。
<template>
<div>
<tree-node
:data="treeData"
:multiple="multiple"
:is-searchable="isSearchable"
:search-placeholder="searchPlaceholder"
v-model="selectedValues"
/>
</div>
</template>
<script>
import TreeNode from './tree-node.vue'
export default {
name: "TreeSelector",
components: {TreeNode},
props: {
treeData: {
required: true,
type: Object
},
value: {
default: [],
type: [Array, String, Number]
},
multiple: {
default: false,
type: Boolean
},
isSearchable: {
default: true,
type: Boolean
},
searchPlaceholder: {
default: '搜索',
type: String
},
},
data() {
return {
selectedValues: []
}
},
mounted() {
this.selectedValues = this.value
},
watch: {
selectedValues: function (val) {
this.$emit('input', val);
},
value: function (val) {
this.selectedValues = val
}
}
};
</script>
4.2 子组件
子组件的作用是渲染每个节点,包含展开和收起。
<template>
<div>
<el-tree
v-if="!isSearchVisible"
:data="data"
:node-key="props.nodeKey"
:props="props"
:default-expand-all="true"
:expand-on-click-node="false"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
:show-checkbox="multiple"
v-model="checkedKeys">
</el-tree>
<el-tree
v-else
:data="filteredData"
:node-key="props.nodeKey"
:props="props"
:default-expand-all="true"
:expand-on-click-node="false"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
:show-checkbox="multiple"
v-model="checkedKeys">
</el-tree>
</div>
</template>
<script>
export default {
name: "TreeNode",
props: {
data: {
required: true,
type: Object
},
multiple: {
default: false,
type: Boolean
},
isSearchable: {
default: true,
type: Boolean
},
searchPlaceholder: {
default: '搜索',
type: String
}
},
data() {
return {
checkedKeys: [],
filteredData: [],
props: {
label: 'label',
children: 'children'
}
}
},
methods: {
handleNodeClick(data) {
this.$emit('node-click', data);
},
handleCheckChange(data, checked) {
this.$emit('check-change', data, checked);
}
},
watch: {
data: {
handler(val) {
this.checkedKeys = this.$parent.selectedValues;
},
deep: true
}
},
computed: {
isSearchVisible() {
return this.isSearchable && this.filteredData.length > 0;
}
},
mounted() {
this.checkedKeys = this.$parent.selectedValues;
}
};
</script>
4.3 过滤器组件
筛选器功能是根据关键字搜索匹配的节点。
<template>
<div>
<el-input
:placeholder="searchPlaceholder"
v-model="filterText"
clearable
size="mini"
@clear="filterText = ''"
/>
<div v-if="filteredData && filteredData.length > 0">
<el-tree
:data="filteredData"
:node-key="props.nodeKey"
:props="props"
:default-expand-all="true"
:expand-on-click-node="false"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
:show-checkbox="multiple"
v-model="checkedKeys"
/>
</div>
<p v-else>没有找到匹配的节点</p>
</div>
</template>
<script>
export default {
name: 'TreeSelectorFilter',
props: {
data: {
type: Array,
required: true
},
multiple: {
default: false,
type: Boolean
},
searchPlaceholder: {
default: '搜索',
type: String
}
},
data() {
return {
filterText: '',
checkedKeys: [],
filteredData: [],
props: {
label: 'label',
children: 'children'
}
}
},
methods: {
handleNodeClick(data) {
this.$emit('node-click', data);
},
handleCheckChange(data, checked) {
this.$emit('check-change', data, checked);
}
},
watch: {
filterText: function (val) {
if (!val) {
this.filteredData = [];
} else {
this.filteredData = this.filterTreeData(this.data, val);
}
},
data: function () {
this.checkedKeys = []
}
},
mounted() {
this.filteredData = this.data;
},
computed: {
filterTreeData() {
const filter = function (data, text) {
return data.filter(function (item) {
if (item.label.indexOf(text) > -1) {
return true;
} else if (item.children && item.children.length > 0) {
return filter(item.children, text);
} else {
return false;
}
});
};
return filter;
}
}
};
</script>
5. 示例说明
5.1 示例一:基本用法
<template>
<tree-selector :tree-data="treeData" v-model="selectedValues" />
</template>
<script>
import TreeSelector from "./components/tree-selector.vue";
export default {
name: "App",
components: {
TreeSelector
},
data() {
return {
treeData: {
label: "全国",
value: "0",
children: [{
label: "浙江",
value: "1",
children: [{
label: "杭州",
value: "1-1"
}, {
label: "宁波",
value: "1-2"
}]
}, {
label: "福建",
value: "2",
children: [{
label: "福州",
value: "2-1"
}]
}]
},
selectedValues: []
};
}
};
</script>
5.2 示例二:多选
<template>
<tree-selector :tree-data="treeData" v-model="selectedValues" :multiple="true" />
</template>
<script>
import TreeSelector from "./components/tree-selector.vue";
export default {
name: "App",
components: {
TreeSelector
},
data() {
return {
treeData: {
label: "全国",
value: "0",
children: [{
label: "浙江",
value: "1",
children: [{
label: "杭州",
value: "1-1"
}, {
label: "宁波",
value: "1-2"
}]
}, {
label: "福建",
value: "2",
children: [{
label: "福州",
value: "2-1"
}]
}]
},
selectedValues: []
};
}
};
</script>
以上就是Vue实现无限级树形选择器的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue实现无限级树形选择器 - Python技术站