返回
Element-UI封装实现TreeSelect 支持下拉框中输入值检索
前端
2023-12-27 02:58:32
前言
前些天实现的一个树形的下拉组件,可最近又让我支持下拉检索功能,查了一圈没有合适的,只好今天自己写一下,凑合能用吧,支持检索功能了最起码,可有些参数还是要配置的,使用起来比之前那一篇麻烦了一丢丢。
实现
我们下载依赖包,再新建文件夹新建Element-UI的component:
# 安装依赖
pnpm i element-ui -S
# 新建Element-UI文件夹
pnpm i element-ui -S
# 再新建一个component文件夹
pnpm i element-ui -S
新建好文件夹后,我们再进入Element-UI的component文件夹:
# 进入Element-UI component
pnpm i element-ui -S
我一个一个创建吧:
- treeSelect组件先创建一个TreeSelect:
import { defineAsyncComponent } from 'element-ui/src/utils/async-component';
// 异步加载TreeSelect
const AsyncTreeSelect = defineAsyncComponent(
() => import('@/components/treeSelect/index.vue')
);
export default AsyncTreeSelect;
我们新建treeSelect文件夹:
# 在Element-UI component新建treeSelect文件夹
pnpm i element-ui -S
treeSelect里新建TreeSelect:
import Tree from "vue-tree";
import TreeUi from "vue-tree/src/index.js";
// 引入的样式
import './Tree.less';
export default {
name: 'AsyncTreeSelect',
components: {
TreeUi,
},
props: {
treeData: {
type: Object,
default: () => {
return {};
}
},
defaultVal: {
type: Array,
default: []
},
hideIfSingle: {
type: Boolean,
default: false
},
onlyParent: {
type: Boolean,
default: false
}
},
methods: {
// 选择
handleSelect({ target: { value } }, node) {
if (this.onlyParent) {
value = node.dataId;
}
this.propSetInput(value);
if (value) {
this.$emit('input', value);
this.$emit('node', node);
}
},
propSetInput(value) {
if (Array.isArray(this.propValue)) {
let array = [];
if (value !== null && value !== undefined) {
array = array.concat(this.propValue).concat(value);
}
this.syncInput(array);
} else if (value !== null && value !== undefined) {
this.syncInput(value);
} else {
this.syncInput(null);
}
},
// 同步input
syncInput(value) {
let changed = false;
const inputValue = value;
if (Array.isArray(inputValue)) {
changed = this.propValue !== inputValue;
} else {
changed = inputValue !== this.propValue;
}
if (!changed) return;
this.$emit('update:input', value);
},
// 单选触发
defaultActiveChange({ startValue }) {
if (this.onlyParent) {
this.propSetInput(startValue);
} else {
this.propSetInput(startValue);
}
this.$emit('update:defaultActive', startValue);
},
// 根据value设置选中值
handleVal(val) {
setTimeout(() {
if (this.onlyParent) {
this.$emit('input', val);
this.$emit('node', null);
} else {
this.$emit('input', val);
this.$emit('node', null);
}
}, 100);
}
},
render(h) {
let value = this.propValue;
value =
typeof value === 'object' ? value.map(v => String(v)) : String(value);
return (
<TreeUi
className={this._treeClass}
defaultActive={value}
showCheckbox={this.showCheckbox}
selectedVals={value}
search={this.showSearch}
custom={this.slotRender}
on-defaultActiveChange={this.defaultActiveChange}
on-toggle={this.handleSelect}
on-search={this.handleSearch}
/>
);
}
};
再写样式:
// Element-UI component/treeSelect/Tree.less
// 样式
.tree-class {
padding: 12px 16px;
}
.tree-class-sub {
padding: 12px 16px 0 32px;
background-color: #f3f3f3;
}
.tree-class-btn {
width: 130px;
}
再写TreeSelect.vue:
<template>
<AsyncTreeSelect />
</template>
<script>
import { defineAsyncComponent } from 'element-ui/src/utils/async-component';
import TreeSelect from './treeSelect';
// 异步加载TreeSelect
const AsyncTreeSelect = defineAsyncComponent(
() => import('@/components/treeSelect/index.vue')
);
export default AsyncTreeSelect;
</script>
<style lang="less">
@import '../TreeSelect.less';
</style>
- 模拟的数据
{
id: '1',
name: '我的菜单',
children: [
{
id: '11',
name: '子菜单 1'
},
{
id: '12',
name: '子菜单 2'
},
{
id: '13',
name: '子菜单 3'
}
]
}
- 普通的Select组件
import { defineAsyncComponent } from 'element-ui/src/utils/async-component';
// 异步加载TreeSelect
const AsyncTreeSelect = defineAsyncComponent(
() => import('@/components/treeSelect/index.vue')
);
export default AsyncTreeSelect;
- 测试的页面
<template>
<div class="tree-class">
<TreeSelect
treeData={data}
defaultVal={[31, 32]}
onlyParent
/>
</div>
<div class="tree-class">
<TreeSelect
treeData={data}
defaultVal={[31, 32]}
onlyParent
hideIfSingle
/>
</div>
</template>
<script>
import { defineAsyncComponent } from 'element-ui/src/utils/async-component';
import data from './data';
// 异步加载TreeSelect
const AsyncTreeSelect = defineAsyncComponent(
() => import('@/components/treeSelect/index.vue')
);
export default {
components: {
TreeSelect: AsyncTreeSelect
},
data: data
};
</script>
<style lang="less">
@import '../TreeSelect.less';
</style>
结语
这个Element-UI的treeSelect 下拉检索组件我们自己做的还是蛮复杂的,要比之前的组件要复杂很多,你可以自己创建你的,根据你自己的情况设置,各有所得。
演示
你可以看这个地址,已经出结果了,就是这个我们自己做好的Element-UI treeSelect 下拉检索组件:
https://github.com/caobeibei/treeSelect
希望你能和我提一些意见和新的发现。