vue 树形控件-封装思路

问题:自己想封装一个树形控件,看了看element-ui的源码有点麻烦(mei,kan,ming,bai)直接放弃了,目前组件递归没有问题,点击有子集的复选框后所有子集的checked可以跟着改变,但是状态不变,加上checkbox后就感觉懵逼了
目标:1.实现全选 2.查询 3.删除
有大神可以提供具体点的思路吗

<template>

<li class="tree-item">

<span @click="handlerToggle">

<em v-if="hasChild" class="icon">{{open ? '-' : '+'}}</em>

<em v-if="!hasChild" class="icon file-text"></em>

</span>

<input type="checkbox" v-model="data.checked" :value="data.id" @click="checkedChange(data,level)">

<span>{{ data.name }}</span>

<ul v-show="open" v-if="hasChild">

<tree-item v-for="(item, index) in data.list" :data="item" :key="index" :level="level+1"></tree-item>

</ul>

</li>

</template>

<script>

export default {

name: 'TreeItem',

props: {

data: {

type: [Object, Array],

required: true

},

level: {

type: Number,

default: 0

}

},

data() {

return {

open: false, // 是否展开

checkedArr: []

}

},

computed: {

// 是否有下一级

hasChild () {

if (this.data.list && this.data.list.length ) {

// console.log(1)

}

return this.data.list && this.data.list.length

}

},

methods: {

// 展开收缩

handlerToggle () {

if (this.hasChild) {

this.open = !this.open

}

},

// 本层数据添加checked

addChecked (obj) {

if (!obj.hasOwnProperty('checked')) {

obj.checked = false

}

return obj

},

// 每个多选框状态改变

checkedChange (data, level) {

if (data.list && data.list.length > 0) {

this.recurrenceCheckedChange(data);

} else {

data.checked = !data.checked;

}

},

// 递归修改多选框状态改变

recurrenceCheckedChange (data) {

data.list.forEach((item) => {

item.checked = !item.checked;

if (item.list && item.list.length > 0 ) {

this.recurrenceCheckedChange(item)

}

})

}

},

watch: {

},

created () {

},

mounted () {

this.addChecked(this.data);

}

}

</script>

<style>

.tree-item {

margin-top: 10px;

}

.tree-item ul {

margin-left: 22px;

}

em.icon {

display: inline-block;

width: 15px;

background-repeat: no-repeat;

cursor: pointer;

}

</style>

回答

我之前写过,参考链接:https://juejin.im/post/684490...

<template>

<el-select

v-model="dataArr"

:multiple="multiple"

filterable

:placeholder="placeholder"

:disabled="disabled"

:collapse-tags="collapseTags"

@remove-tag="handleTagChange"

@change="handleTagChange"

@visible-change="handleOptionHidden"

:filter-method="handleSelectFilter"

class="hi-input">

<el-option value="0"

class="hidden">

</el-option>

<el-checkbox

v-if="selectAll"

v-model="checked"

@change="handleSelectAll"

class="select-all">

Select All

</el-checkbox>

<el-tree

ref="tree"

:data="options"

node-key="key"

show-checkbox

:default-checked-keys="selectedData"

@check="handleCheckChange"

:filter-node-method="handleTreeFilter"

:props="defaultProps">

</el-tree>

</el-select>

</div>

</template>

<script>

export default {

data() {

return {

dataArr: [],

selectedData: [],

selectedItem: [],

defaultProps: {

children: 'children',

label: 'label'

},

checked: false

};

},

props: {

dataList: {

type: Array,

default: function() {

return [];

}

},

options: {

type: Array,

default: function() {

return [];

}

},

placeholder: {

type: String,

default: 'Select'

},

selectAll: {

type: Boolean,

default: false

},

disabled: {

type: Boolean,

default: false

},

multiple: {

type: Boolean,

default: true

},

title: {

type: String

},

collapseTags: {

type: Boolean,

default: true

}

},

watch: {

selectedData: function(newValue) {

this.$nextTick(() => { this.dataArr = this.handleDataTransform(newValue, 'key', 'label'); });

},

dataList: {

immediate: true,

handler(newValue) {

this.selectedData = newValue;

this.$nextTick(() => this.$refs.tree && this.$refs.tree.setCheckedKeys(this.selectedData));

this.cancelSelectAll();

}

}

},

methods: {

handleSelectFilter: function(val) {

this.$refs.tree.filter(val);

},

handleTreeFilter: function(value, data) {

if (!value) return true;

return data.label.toUpperCase().indexOf(value.toUpperCase()) !== -1;

},

// 下拉框收起时再触发

handleOptionHidden: function(item) {

// 处理选中内容没变的情况

if (item) {

this.selectedItem = [...this.selectedData];

} else {

if (!this.$util.isEqual(this.selectedItem, this.selectedData)) {

this.handleUpdate(this.selectedData);

}

// 为了处理搜素关键字输入后,移出下拉框焦点后 options 恢复数据

this.$refs.tree.filter('');

}

},

handleTagChange: function() {

this.selectedData = this.handleDataTransform(this.dataArr, 'label', 'key');

this.$refs.tree.setCheckedKeys(this.selectedData);

this.handleUpdate(this.selectedData);

},

handleUpdate: function(item) {

this.$emit('update:dataList', item);

this.$emit('change-field');

this.cancelSelectAll();

},

handleCheckChange: function() {

this.selectedData = this.$refs.tree.getCheckedKeys().filter(_ => _);

// 这里是为了通过表单验证的处理

this.$emit('update:dataList', this.selectedData);

this.cancelSelectAll();

},

handleDataTransform: function(source, key, value) {

return this.options.map(_ => {

let arr = [];

if (_.children) {

arr = source.map(item => this.$business.getNameById(

_.children,

item,

key,

value

));

} else if (source.includes(_[key])) {

arr = [_[value]];

}

return arr.filter(item => item);

}).reduce((acc, cur) => {

return acc.concat(cur);

}, []);

},

cancelSelectAll() {

// 处理全选

if (this.selectAll && (this.selectedData.length !== this.options.length)) {

this.checked = false;

}

},

handleSelectAll() {

this.selectedData = this.checked ? this.options.map(_ => _.key) : [];

this.$refs.tree && this.$refs.tree.setCheckedKeys(this.selectedData);

}

}

};

</script>

<style lang="less" scoped>

</style>

以上是 vue 树形控件-封装思路 的全部内容, 来源链接: utcz.com/a/43694.html

回到顶部