vue element select-tree组件 超简单实现 直接使用满足多选|单选,数据双向绑定,代码可二次开发
el-select-tree 利用el-select 及el-tree特性重新封装,属性灵活装载,满足常规的表单下拉树支持,代码改写没有优化有需要的朋友自行下载优化。代码:<template><el-select:collapseTags="collapseTags":multiple="multiple"v-model='selectId':clearable="clearab
·
导读:el-select-tree 利用el-select 及el-tree特性重新封装,直接继承el-select 及el-tree的属性,单选多选支持顺畅,满足常规的表单下拉树支持,代码需要优化的地方还有很多,水平有限如有更好的方法请留言告知谢谢,感谢支持感谢开源。
近期因为工作需要故而有把此组件重新整理和封装了下,有如下几点调整:
1:使用$attars属性暴露子组件的属性,方法(自己写)和事件(v-bind="$listeners")请自行去暴露优化
2、应各位朋友期望,添加了组件搜素功能
3、其他一些更改
旧版代码:
<template>
<el-select
:collapseTags="collapseTags"
:multiple="multiple"
v-model='selectId'
:clearable="clearable"
:props='defaultProps'
:placeholder='placeholder'
@clear='handleClear'
ref='selectUpResId'
@remove-tag="handleRemoveTag">
<!-- 设置一个空option 不然selectData为空下拉不显示 -->
<el-option hidden value="xx" label="xx" key="xxxxx"></el-option>
<el-option hidden v-for="(item, _index) in selectData" :value="item[defaultProps['id']]" :label="item[defaultProps['label']]" :key="_index"></el-option>
<!-- 设置树形组件-->
<el-tree
:data='data'
:show-checkbox="multiple"
:node-key="defaultProps['id']"
:props='defaultProps'
:expand-on-click-node='false'
:check-on-click-node='true'
@node-click='handleNodeClick'
@check="handCheck"
ref="tree">
</el-tree>
</el-select>
</template>
<script>
export default {
name: 'ElSelectTree',
componentName: 'ElSelectTree',
props: {
// ********* 属性 如有需要自行添加 ****
multiple: Boolean, // 默认:false
clearable: Boolean, // 默认:false
collapseTags: Boolean, // 默认:false
data: { // tree 数据
type: Array,
default: function () {
return []
}
},
placeholder: {
type: String,
default: '请选择'
},
// ********* 属性 ******************
defaultProps: {
type: Object,
default: {
children: 'children',
label: 'label',
id: 'id'
}
},
value: [String, Number, Object, Array]
},
data () {
return {
selectId: '',
selectData: []
}
},
mounted () {
this.$nextTick(_ => {
this.setDefaultValue(this.value)
})
},
watch: {
value: function (v) {
console.log('watch value', v)
this.setDefaultValue(v)
}
},
methods: {
// 回填值
setDefaultValue (v) {
if (this.multiple) { // 多选
this.$refs.tree.setCheckedKeys(v)
this.handCheckSetValue()
} else { // 其他
this.$refs.tree.setCurrentKey(v)
this.$nextTick(_ => {
this.handleNodeSetValue()
})
}
},
// 单选点击事件
handleNodeClick (data) {
if (this.multiple) return
// 隐藏下拉框的效果
this.$refs.selectUpResId.blur()
this.$emit('input', this.handleNodeSetValue())
console.log('handleNodeClick', this.value)
},
handleNodeSetValue () {
var cNode = this.$refs.tree.getCurrentNode()
this.selectData = cNode ? [cNode] : []
// 设置值
var _value = cNode ? cNode[this.defaultProps['id']] : null
this.selectId = _value
return _value
},
// 多选选择勾选
handCheck (currentNode, checkedNodes) {
if (!this.multiple) return
this.$emit('input', this.handCheckSetValue())
console.log('multiple handleNodeClick', this.value)
},
handCheckSetValue () {
this.selectData = this.cloneDeep(this.$refs.tree.getCheckedNodes(true, false))
// 设置值
var _value = this.selectData.map(item => item[this.defaultProps['id']])
this.selectId = _value
return _value
},
// 清空触发
handleClear () {
this.$emit('input', this.multiple ? [] : null)
},
// 多选模式移除tag
handleRemoveTag (v) {
console.log('handlRemoveTag formData.id', this.selectId)
this.$emit('input', this.selectId)
}
}
}
</script>
调用方式:
<el-select-tree :defaultProps= "{
children: 'children',
label: 'name',
id: 'id'
}" v-model="test" multiple collapse-tags clearable :data="treeList" placeholder="xxxxxxx"></el-select-tree>
新版代码
个别属性需要特殊处理,见props中的属性
<template>
<el-select
v-bind="$attrs"
:style="styles"
v-model='selectId'
:multiple="multiple"
:props='dynaDefProps'
@clear='handleClear'
ref='selectUpResId'
@remove-tag="handleRemoveTag"
:filter-method="handleFilterMethod"
@visible-change="selectVisibleChange">
<!-- 设置一个空option 不然selectData为空下拉不显示,这样处理无需用js去处理显示和隐藏了 -->
<el-option hidden value="x" label="x" key="x"></el-option>
<el-option hidden v-for="(item, _index) in selectData" :value="item[dynaDefProps['id']]" :label="getLable(item)" :key="_index"></el-option>
<!-- 设置树形组件-->
<el-tree
v-bind="$attrs"
:show-checkbox="multiple"
:node-key="dynaDefProps['id']"
:props='dynaDefProps'
@node-click='handleNodeClick'
@check="handCheck"
:filter-node-method="handleFilterNode"
ref="tree">
</el-tree>
</el-select>
</template>
<script>
export default {
inheritAttrs: false,
name: 'ElSelectTree1',
componentName: 'ElSelectTree1',
props: {
// ********* 自定义的属性 如有需要自行添加 ****
multiple: Boolean, //是否多选 默认:false
onlyLeaf: { // 是否只包含叶子节点
type: Boolean,
default: false
},
styles: {// 给一个样式属性
type: String,
default: 'width:100%'
},
defaultProps: {
type: Object,
required: false,
default: () => ({
parent: 'parentId', // 父级唯一标识
id: 'id', // 唯一标识
label: 'code', // 标签显示
children: 'children' // 子级
})
},
value: [String, Number, Object, Array]
},
data () {
return {
selectId: '',
selectData: []
}
},
computed: {
// 树节点配置选项
dynaDefProps () {
return Object.assign({}, {
parentId: 'parentId',
id: 'id',
label: 'name',
children: 'children',
filter: 'filter'
}, this.props)
}
},
mounted () {
},
watch: {
value: {
handler (v, ov) {
this.$nextTick(() => {
// 针对第一次请求,如果data延迟加载而出现赋值显示不是label的属性问题
if (this.$refs.tree.data.length) {
this.setDefaultValue(v)
} else {
this.$refs.tree.$watch('data', () => {
this.setDefaultValue(v)
})
}
})
},
immediate:true, // watch立即执行
deep: true
}
},
methods: {
getLable (item) {
return (typeof this.dynaDefProps['label'] === 'string') ? item[this.dynaDefProps['label']] : this.dynaDefProps['label'](item)
},
// 回填值
setDefaultValue (v) {
if (this.multiple) { // 多选
// this.$nextTick(() => {
this.$refs.tree.setCheckedKeys(v, this.onlyLeaf)
this.handCheckSetValue(v, null)
} else { // 其他
this.$refs.tree.setCurrentKey(v)
this.handleNodeSetValue()
}
},
// 单选点击事件
handleNodeClick (data) {
if (this.multiple) return
// 隐藏下拉框的效果
this.$refs.selectUpResId.blur()
this.$emit('input', this.handleNodeSetValue())
// console.log('handleNodeClick', this.value)
},
handleNodeSetValue () {
var cNode = this.$refs.tree.getCurrentNode()
this.selectData = cNode ? [cNode] : []
// 设置值
var _value = cNode ? cNode[this.dynaDefProps['id']] : null
this.selectId = _value
return this.selectId
},
// 多选选择勾选
handCheck (currentNode, checkedNodesState) {
// console.log('handCheck', checkedNodesState)
if (!this.multiple) return
this.$emit('input', this.handCheckSetValue())
// console.log('multiple handleNodeClick', this.value)
},
/**
* 特殊处理下多选值处理,解决父子节点强关联的时候用
* checkedKeys选中的keys
* checkedNodes 选中的nodes
*
*/
handCheckSetValue (checkedKeys, checkedNodes) {
// console.log('handCheckSetValue')
this.selectData = this.$refs.tree.getCheckedNodes(this.onlyLeaf, false)
this.selectId = checkedKeys || this.$refs.tree.getCheckedKeys(this.onlyLeaf)
return this.selectId
},
// 清空触发
handleClear () {
this.$emit('input', this.multiple ? [] : null)
},
// 多选模式移除tag
handleRemoveTag (v) {
// console.log('handlRemoveTag formData.id', this.selectId, v)
this.$emit('input', this.selectId)
},
// select搜索调用tree过滤
handleFilterMethod (query) {
this.$refs.tree.filter(query)
},
// tree 过滤
handleFilterNode (value, data) {
if (!value) return true
var _label = this.getLable(data);
return _label.toLowerCase().indexOf(value.toLowerCase()) !== -1
},
// select 失去焦点并重置过滤器
selectVisibleChange (v) {
if (v || !this.filterable ) return
this.handleFilterMethod(null)
// console.log('selectVisibleChange', v, this.filterable)
}
}
}
</script>
tips:
> selectVisibleChange方法中 this.selectVisibleChange 改为
> this.$refs.selectUpResId.selectVisibleChange
新版调用方式:
**注意:支持使用el-select 和el-tree的属性,外加自定的props属性**
<el-select-tree :defaultProps= "{
children: 'children',
label: 'name',
id: 'id'
}" v-model="test" multiple collapse-tags clearable :data="treeList" placeholder="xxxxxxx"></el-select-tree>
更多推荐
已为社区贡献1条内容
所有评论(0)