element 樹狀下拉框

<!--

? ? /**

? ? * 樹形下拉選擇組件,下拉框展示樹形結(jié)構(gòu),提供選擇某節(jié)點功能,方便其他模塊調(diào)用

? ? * @author sxy https://bysjb.cn

? ? * @date 2020-12-02

? ? */

-->

<template>

? <div>

? ? <div v-show="isShowSelect" class="mask" @click="isShowSelect = !isShowSelect" />

? ? <el-popover

? ? ? v-model="isShowSelect"

? ? ? placement="bottom-start"

? ? ? :width="width"

? ? ? trigger="manual"

? ? ? style="padding: 12px 0;"

? ? ? @hide="popoverHide"

? ? >

? ? ? <el-tree

? ? ? ? ref="tree"

? ? ? ? class="common-tree"

? ? ? ? :style="style"

? ? ? ? :data="data"

? ? ? ? :props="defaultProps"

? ? ? ? :show-checkbox="multiple"

? ? ? ? :node-key="nodeKey"

? ? ? ? :check-strictly="checkStrictly"

? ? ? ? default-expand-all

? ? ? ? :expand-on-click-node="false"

? ? ? ? :check-on-click-node="multiple"

? ? ? ? :highlight-current="true"

? ? ? ? @node-click="handleNodeClick"

? ? ? ? @check-change="handleCheckChange"

? ? ? />

? ? ? <el-select

? ? ? ? slot="reference"

? ? ? ? ref="select"

? ? ? ? v-model="selectedData"

? ? ? ? :style="selectStyle"

? ? ? ? :size="size"

? ? ? ? :multiple="multiple"

? ? ? ? :clearable="clearable"

? ? ? ? :collapse-tags="collapseTags"

? ? ? ? class="tree-select"

? ? ? ? @click.native="isShowSelect = !isShowSelect"

? ? ? ? @remove-tag="removeSelectedNodes"

? ? ? ? @clear="removeSelectedNode"

? ? ? ? @change="changeSelectedNodes"

? ? ? >

? ? ? ? <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />

? ? ? </el-select>

? ? </el-popover>

? </div>

</template>

<script>

export default {

? props: {

? ? // 樹結(jié)構(gòu)數(shù)據(jù)

? ? data: {

? ? ? type: Array,

? ? ? default() {

? ? ? ? return []

? ? ? }

? ? },

? ? defaultProps: {

? ? ? type: Object,

? ? ? default() {

? ? ? ? return {

? ? ? ? ? children: 'children',

? ? ? ? ? label: 'name'

? ? ? ? }

? ? ? }

? ? },

? ? // 配置是否可多選

? ? multiple: {

? ? ? type: Boolean,

? ? ? default() {

? ? ? ? return false

? ? ? }

? ? },

? ? // 配置是否可清空選擇

? ? clearable: {

? ? ? type: Boolean,

? ? ? default() {

? ? ? ? return false

? ? ? }

? ? },

? ? // 配置多選時是否將選中值按文字的形式展示

? ? collapseTags: {

? ? ? type: Boolean,

? ? ? default() {

? ? ? ? return false

? ? ? }

? ? },

? ? nodeKey: {

? ? ? type: String,

? ? ? default() {

? ? ? ? return 'id'

? ? ? }

? ? },

? ? // 顯示復選框情況下,是否嚴格遵循父子不互相關(guān)聯(lián)

? ? checkStrictly: {

? ? ? type: Boolean,

? ? ? default() {

? ? ? ? return false

? ? ? }

? ? },

? ? // 默認選中的節(jié)點key數(shù)組

? ? checkedKeys: {

? ? ? type: Array,

? ? ? default() {

? ? ? ? return []

? ? ? }

? ? },

? ? size: {

? ? ? type: String,

? ? ? default() {

? ? ? ? return 'medium'

? ? ? }

? ? },

? ? width: {

? ? ? type: Number,

? ? ? default() {

? ? ? ? return 250

? ? ? }

? ? },

? ? height: {

? ? ? type: Number,

? ? ? default() {

? ? ? ? return 300

? ? ? }

? ? }

? },

? data() {

? ? return {

? ? ? isShowSelect: false, // 是否顯示樹狀選擇器

? ? ? options: [],

? ? ? selectedData: [], // 選中的節(jié)點

? ? ? style: 'width:' + (this.width - 24) + 'px;' + 'height:' + this.height + 'px;',

? ? ? selectStyle: 'width:' + (this.width + 24) + 'px;',

? ? ? checkedIds: [],

? ? ? checkedData: []

? ? }

? },

? watch: {

? ? isShowSelect(val) {

? ? ? // 隱藏select自帶的下拉框

? ? ? this.$refs.select.blur()

? ? },

? ? checkedKeys(val) {

? ? ? console.log('checkedKeys', val)

? ? ? if (!val) return

? ? ? this.checkedKeys = val

? ? ? this.initCheckedData()

? ? }

? },

? mounted() {

? ? this.initCheckedData()

? },

? methods: {

? ? // 單選時點擊tree節(jié)點,設(shè)置select選項

? ? setSelectOption(node) {

? ? ? const tmpMap = {}

? ? ? tmpMap.value = node.key

? ? ? tmpMap.label = node.label

? ? ? this.options = []

? ? ? this.options.push(tmpMap)

? ? ? this.selectedData = node.key

? ? },

? ? // 單選,選中傳進來的節(jié)點

? ? checkSelectedNode(checkedKeys) {

? ? ? var item = checkedKeys[0]

? ? ? this.$refs.tree.setCurrentKey(item)

? ? ? var node = this.$refs.tree.getNode(item)

? ? ? this.setSelectOption(node)

? ? },

? ? // 多選,勾選上傳進來的節(jié)點

? ? checkSelectedNodes(checkedKeys) {

? ? ? // this.$refs.tree.setCheckedKeys(checkedKeys)

? ? ? // 優(yōu)化select回顯顯示 有個延遲的效果

? ? ? const that = this

? ? ? setTimeout(function() {

? ? ? ? that.$refs.tree.setCheckedKeys(checkedKeys)

? ? ? }, 10)

? ? ? // console.log('checkSelectedNodes', checkedKeys, this.selectedData)

? ? },

? ? // 單選,清空選中

? ? clearSelectedNode() {

? ? ? this.selectedData = []

? ? ? this.$refs.tree.setCurrentKey(null)

? ? },

? ? // 多選,清空所有勾選

? ? clearSelectedNodes() {

? ? ? var checkedKeys = this.$refs.tree.getCheckedKeys() // 所有被選中的節(jié)點的 key 所組成的數(shù)組數(shù)據(jù)

? ? ? for (let i = 0; i < checkedKeys.length; i++) {

? ? ? ? this.$refs.tree.setChecked(checkedKeys[i], false)

? ? ? }

? ? },

? ? initCheckedData() {

? ? ? if (this.multiple) {

? ? ? ? // 多選

? ? ? ? // console.log(this.checkedKeys.length)

? ? ? ? if (this.checkedKeys.length > 0) {

? ? ? ? ? this.checkSelectedNodes(this.checkedKeys)

? ? ? ? } else {

? ? ? ? ? this.clearSelectedNodes()

? ? ? ? }

? ? ? } else {

? ? ? ? // 單選

? ? ? ? if (this.checkedKeys.length > 0) {

? ? ? ? ? this.checkSelectedNode(this.checkedKeys)

? ? ? ? } else {

? ? ? ? ? this.clearSelectedNode()

? ? ? ? }

? ? ? }

? ? },

? ? popoverHide() {

? ? ? if (this.multiple) {

? ? ? ? this.checkedIds = this.$refs.tree.getCheckedKeys() // 所有被選中的節(jié)點的 key 所組成的數(shù)組數(shù)據(jù)

? ? ? ? this.checkedData = this.$refs.tree.getCheckedNodes() // 所有被選中的節(jié)點所組成的數(shù)組數(shù)據(jù)

? ? ? } else {

? ? ? ? this.checkedIds = this.$refs.tree.getCurrentKey()

? ? ? ? this.checkedData = this.$refs.tree.getCurrentNode()

? ? ? }

? ? ? this.$emit('popoverHide', this.checkedIds, this.checkedData)

? ? },

? ? // 單選,節(jié)點被點擊時的回調(diào),返回被點擊的節(jié)點數(shù)據(jù)

? ? handleNodeClick(data, node) {

? ? ? if (!this.multiple) {

? ? ? ? this.setSelectOption(node)

? ? ? ? this.isShowSelect = !this.isShowSelect

? ? ? ? this.$emit('change', this.selectedData)

? ? ? }

? ? },

? ? // 多選,節(jié)點勾選狀態(tài)發(fā)生變化時的回調(diào)

? ? handleCheckChange() {

? ? ? var checkedKeys = this.$refs.tree.getCheckedKeys() // 所有被選中的節(jié)點的 key 所組成的數(shù)組數(shù)據(jù)

? ? ? // console.log('handleCheckChange', checkedKeys)

? ? ? this.options = checkedKeys.map((item) => {

? ? ? ? var node = this.$refs.tree.getNode(item) // 所有被選中的節(jié)點對應(yīng)的node

? ? ? ? const tmpMap = {}

? ? ? ? tmpMap.value = node.key

? ? ? ? tmpMap.label = node.label

? ? ? ? return tmpMap

? ? ? })

? ? ? this.selectedData = this.options.map((item) => {

? ? ? ? return item.value

? ? ? })

? ? ? this.$emit('change', this.selectedData)

? ? },

? ? // 多選,刪除任一select選項的回調(diào)

? ? removeSelectedNodes(val) {

? ? ? this.$refs.tree.setChecked(val, false)

? ? ? var node = this.$refs.tree.getNode(val)

? ? ? if (!this.checkStrictly && node.childNodes.length > 0) {

? ? ? ? this.treeToList(node).map(item => {

? ? ? ? ? if (item.childNodes.length <= 0) {

? ? ? ? ? ? this.$refs.tree.setChecked(item, false)

? ? ? ? ? }

? ? ? ? })

? ? ? ? this.handleCheckChange()

? ? ? }

? ? ? this.$emit('change', this.selectedData)

? ? },

? ? treeToList(tree) {

? ? ? var queen = []

? ? ? var out = []

? ? ? queen = queen.concat(tree)

? ? ? while (queen.length) {

? ? ? ? var first = queen.shift()

? ? ? ? if (first.childNodes) {

? ? ? ? ? queen = queen.concat(first.childNodes)

? ? ? ? }

? ? ? ? out.push(first)

? ? ? }

? ? ? return out

? ? },

? ? // 單選,清空select輸入框的回調(diào)

? ? removeSelectedNode() {

? ? ? this.clearSelectedNode()

? ? ? this.$emit('change', this.selectedData)

? ? },

? ? // 選中的select選項改變的回調(diào)

? ? changeSelectedNodes(selectedData) {

? ? ? // 多選,清空select輸入框時,清除樹勾選

? ? ? if (this.multiple && selectedData.length <= 0) {

? ? ? ? this.clearSelectedNodes()

? ? ? }

? ? ? this.$emit('change', this.selectedData)

? ? }

? }

}

</script>

<style scoped>

? .mask {

? ? width: 100%;

? ? height: 100%;

? ? position: fixed;

? ? top: 0;

? ? left: 0;

? ? opacity: 0;

? ? z-index: 11;

? }

? .common-tree {

? ? overflow: auto;

? }

? .tree-select {

? ? z-index: 111;

? }

</style>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容