Element-ui el-select下拉內嵌Tree 樹形控件 進行二次封裝


封裝組件,支持單選,多選,搜索,根據節點id默認選中對應的節點,勾選數據事件觸發回調

效果圖(會不斷更新 和修復一些BUG 記得回來看看哦)

(認真看組件配置屬性,特別是傳值的時候defaultProps 配置的展示key)因為最后有模擬JSON數據所以文章有點長

多選效果圖:                                                                        單選效果圖:

 

一.子組件

 

<template>
  <div>
    <el-select v-model="mineStatus" ref="searchSelect" :placeholder="placeholder" :multiple="!Single" :size="size"
      :disabled="disabled" collapse-tags @change="selectChange"  :loading="loading">
      <div style="padding: 10px;">
      <el-input v-if="filterable" placeholder="請輸入搜索內容" v-model="singleSearch" :size="size" clearable></el-input>
    </div>
      <el-option :value="mineStatusValue" v-on:click="doThis($event)" style="position: relative;width: 100%;" :style="{'height':height+'px','overflow-y':overflow}">
        <div style="height: 100%;" v-on:click="doThis($event)">
          <div style="padding-right: 10px;" v-on:click="doThis($event)">
            <el-tree  v-if="treeData.length" :data="treeData" :show-checkbox="!Single" ref="tree" style="font-weight: 500;" highlight-current :props="defaultProps" :default-expand-all="defaultExpandAll" :default-checked-keys="defaultCheckedKeys" :check-strictly="Single" :filter-node-method="filterNode" node-key="id" @check-change="handleCheckChange" @node-click="clickNode">
            </el-tree>
          </div>
          <div v-if="!treeData.length" style="width: 100%;height: 100%;background-color: #FFFFFF;text-align: center;"> 暫無數據 </div>
        </div>
        <div id="load" v-show="load" style="position: absolute;left: 0;top: 0;height: 200px;width: 100%;"></div>
      </el-option>
    </el-select>
  </div>
</template>

<!-- /** * 組件說明 * 屬性: * 參數 說明 類型 默認值 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * placeholder 輸入框占位文本 String '請選擇' * defaultProps 需要使用的展示字段值 Object {children: 'children',label: 'label'} * data tree 的數據源 Array [] * filterable 是否開啟搜索功能 Boolean false * Single tree下拉是否單選 Boolean false * defaultExpandAll tree是否展開全部節點 Boolean false * defaultCheckedKeys 默認勾選節點 Array [] * disabled 是否禁止操作 Boolean Array * size el-option大小尺寸選擇 String medium * * 事件: * selectTerrEvent 獲取選中對象 返回數組 */ -->
<script> const deepFind = (arr, condition, children) => { let main = [] try { (function poll (arr, level) { if (!Array.isArray(arr)) return
      for (let i = 0; i < arr.length; i++) { const item = arr[i] main[level] = item const isFind = (condition && condition(item, i, level)) || false
        if (isFind) { throw Error } else if (children && item[children] && item[children].length) { poll(item[children], level + 1) } else if (i === arr.length - 1) { main.length = main.length - 1 } } })(arr, 0) } catch (err) {} return main } export default { props: { placeholder: { type: String, required: false, default: '請選擇' }, defaultProps: { // 需要使用的展示字段值
 type: Object, default: () => ({ children: 'children', label: 'label' }) }, filterable: { type: Boolean, // 是否開啟搜索
      default: false }, Single: { type: Boolean, // 是否單選
      default: false }, data: { type: Array, // 數據
      default: () => ([]) }, defaultExpandAll: { type: Boolean, // 是否展開節點
      default: false }, defaultCheckedKeys: { type: Array, default: () => ([]) }, size: { type: String, default: 'medium' }, disabled: { type: Boolean, default: false } }, data () { return { overflow: 'hidden', height: 40, load: false, mineStatus: '', mineStatusValue: [], loading: false, deferTimer: null, // 多選復選框高頻查找的數據使用到的延時器變量
      loadingTips: null, SearchData: [], // 搜索的數據
      treeData: [], // 渲染樹的變量
      callbackDefault: null, // 更新數據 高頻回調事件使用到的 延時器變量
      // timeID: null, // 搜索防抖
      singleSearch: '', // 單選搜索
      firstTime: false // 初次加載 狀態
 } }, watch: { singleSearch (newValue, oldValue) { this.$refs.tree.filter(newValue) }, // 更新數據/清空輸入框
 data (n) { if (this.firstTime) { if (Array.isArray(n)) { if (n.length) { this.height = 200
            this.overflow = 'auto' } else { this.height = 40
            this.overflow = 'hidden' } this.mineStatus = ''
          this.mineStatusValue = [] this.treeData = n this.defaultCheckEvent(true) } else { console.error('data 屬性必須是一個Array') } } }, // 更新勾選數據
 defaultCheckedKeys (newValue, oldValue) { if (this.firstTime) { clearTimeout(this.callbackDefault) this.callbackDefault = setTimeout(() => { this.defaultCheckEvent(true) }, 300) } } }, created () { let that = this let dataType = true
    // 等待 接口樹 數據獲取完成
    function dataTerr () { if (!that.treeData.length && dataType) { that.mineStatus = '獲取數據中...' setTimeout(() => { that.treeData = that.data dataTerr() }, 400) } else if (that.treeData.length) { dataType = false that.height = 200 that.overflow = 'auto' that.mineStatus = ''
        // 是否開啟默認勾選
        if (that.defaultCheckedKeys.length) { that.defaultCheckEvent() } // 初次加載 完成
        that.firstTime = true } } dataTerr() // 2.5s后不管有沒要獲取到數據 都停止
    setTimeout(() => { dataType = false that.firstTime = true }, 2500) }, methods: { // 過濾數據 返回搜索結果
 filterNode (value, data) { if (!value) return true
      return data[this.defaultProps.label].indexOf(value) !== -1 }, // 阻止事件冒泡 解決點擊空白區域事件獲取錯誤的數據bug
 doThis (event) { this.$refs.searchSelect.blur() event.stopPropagation() }, // select框值改變時候觸發的事件
 selectChange (e) { if (this.Single || !this.treeData.length) { return false } let arrNew = [] let dataLength = this.mineStatusValue.length let eleng = e.length for (let i = 0; i < dataLength; i++) { for (let j = 0; j < eleng; j++) { if (e[j] === this.mineStatusValue[i][this.defaultProps.label]) { arrNew.push(this.mineStatusValue[i]) break } } } this.$refs.tree.setCheckedNodes(arrNew) // 設置勾選的值
 }, // 默認勾選
 defaultCheckEvent (lock) { // 避免 多個監聽數據更新時同時並發多次
      if (lock) { this.firstTime = false } // 篩選出數據存放
      let defaultData = [] // 根據樹id 遞歸樹 篩選出對應的數據
      if (this.Single) { // 單選
        let myarr = deepFind(this.treeData, (item, index, level) => item.id === this.defaultCheckedKeys[0], this .defaultProps.children) myarr.forEach((v, l) => { if (v.id === this.defaultCheckedKeys[0]) { defaultData.push(v) }; }) } else { // 多選
        this.defaultCheckedKeys.forEach((id, k) => { let myarr = deepFind(this.treeData, (item, index, level) => item.id === id, this.defaultProps.children) myarr.forEach((v, l) => { if (v.id === id) { defaultData.push(v) }; }) }) } // 更新輸入框內的默認勾選值
      let arrLabel = [] let arr = [] defaultData.forEach(item => { arrLabel.push(item[this.defaultProps.label]) arr.push(item) }) this.mineStatusValue = arr if (this.Single) { this.mineStatus = arrLabel[0] } else { this.mineStatus = arrLabel } // 解除 狀態
      if (lock) { this.firstTime = true } this.$emit('selectTerrEvent', defaultData) if (!this.mineStatus.length) { this.$refs.tree && this.$refs.tree.setCheckedNodes([]) } }, // 搜索 監聽
 search () { this.loading = true let val = this.$refs.searchSelect.$data.query this.SearchData = [] this.treeData = this.data setTimeout(() => { this.loading = false
        this.$refs.tree.filter(val) }, 500) }, // 單選點擊 復選框事件 @check="handleCheck"
 handleCheck (data) { if (!this.Single) { return } this.$refs.tree.setCheckedKeys([]) // 刪除所有選中節點
      this.$refs.tree.setCheckedNodes([data]) // 選中已選中節點
 }, // 單選模式事件
 clickNode (data, node, obj) { if (!this.Single) { // 多選不執行
        const index = this.mineStatusValue.findIndex(d => d.id === data.id) if (index > -1) { this.$refs.tree.setChecked(data, false) } else { this.$refs.tree.setChecked(data, true) } return } let arrLabel = [] let arr = []; [data].forEach(item => { arrLabel.push(item[this.defaultProps.label]) arr.push(item) }) this.mineStatusValue = arr this.mineStatus = arrLabel[0] this.$refs.searchSelect.blur() // 失去焦點 關閉下拉框
      // 傳遞數據給父
      this.$emit('selectTerrEvent', [data]) }, // 獲取當前復選框 選中的值 賦值到輸入框里
 handleCheckChange () { if (this.deferTimer == null) { this.load = true
        this.loadingTips = this.$loading({ lock: true, text: 'Loading', spinner: 'el-icon-loading', background: 'rgba(255, 255, 255, 0.5)', target: document.getElementById('load') }) }; let res = this.$refs.tree.getCheckedNodes(true, true) // 這里兩個true,1. 是否只是葉子節點 2. 是否包含半選節點(就是使得選擇的時候不包含父節點)
 let arrLabel = [] let arr = [] res.forEach(item => { arrLabel.push(item[this.defaultProps.label]) arr.push(item) }) clearTimeout(this.deferTimer) this.deferTimer = setTimeout(() => { this.mineStatusValue = arr this.mineStatus = arrLabel this.load = false
        this.loadingTips.close() this.deferTimer = null
        this.$emit('selectTerrEvent', res) }, 200) } } } </script>
<style  scoped> .el-tooltip.item { width: max-content; display: inline-block; border: none; outline: none; } .el-select-dropdown__item.hover, .el-select-dropdown__item:hover { background-color: #ffffff; } .el-select-dropdown__item { padding: 0; } .treedownwidth { width: 13px !important; } .show { display: block; } .comtreedown { height: 100%; } .comtreedown .treedown { width: 220px; height: 100%; display: flex; flex-direction: column; color: #ffffff; position: relative; } .comtreedown .treedown .title { height: 35px; line-height: 35px; font-size: 16px; text-indent: 14px; border-bottom: 1px solid #fff; overflow: hidden; text-overflow: ellipsis !important; white-space: nowrap !important; cursor: pointer; } .comtreedown .treedown .left { position: absolute; z-index: 8; top: 50%; right: 0px; width: 13px; height: 72px; margin-top: -36px; cursor: pointer; } .comtreedown .treedown .left img { display: none; } /* 修改默認樣式 */ .el-tree-node__expand-icon { color: #ffffff; } .comtreedown .el-tree { width: 100%; height: 100%; padding: 10px; color: #ffffff; overflow: auto; border-bottom-left-radius: 10px; } .el-tree-node__content { width: max-content; min-width: 100%; color: #fff; } .el-tree-node, .el-tree-node__children { min-width: 100%; width: max-content; } .el-tree-node__label { width: auto; overflow: hidden; text-overflow: ellipsis !important; white-space: nowrap !important; } .el-tree-node__children .el-tree-node__label { width: auto; overflow: hidden; -webkit-overflow: hidden; text-overflow: ellipsis !important; white-space: nowrap !important; } span.el-icon-caret-right:before { content: ""; } span.el-icon-caret-right:after { content: "\E60E"; } </style>

 

 

二.父頁面

<template>
  <div>
    <el-form :inline="true" :model="pageParams.params" class="demo-form-inline">
      <el-form-item label="下拉樹">
        <select-tree size="mini" :data="getData" :filterable="true" @selectTerrEvent="selectTerrEvetn"
          :defaultExpandAll="true" :defaultProps="defaultProps">
        </select-tree>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
  import SelectTree from '@/components/V2'
  export default {
    components: {
      SelectTree
    },
    data() {
      let _this = this
      return {
        pageParams:{},
        defaultProps: {
          children: "children",
          label: "name"
        },
        getData: []
      }
    },
    created() {
      this.getData = [{
        "id":"-1",
        "name":"前置庫系統",
        "pid":null,
        "children":[
            {
                "id":"1",
                "name":"Mysql",
                "pid":"-1",
                "children":[
                    {
                        "id":"021d75b2eea64d579effd98fcf173c1c",
                        "name":"mysql連接19",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"dcde763b6fbf4c24af3eb8c419405c7f",
                        "name":"xp_制作映射表數據",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"c5868ea98e574c10a6396197d8ea0be8",
                        "name":"SOURCEMySql",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"c7778794bd1f4c24a87bd8384846945d",
                        "name":"fd",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"5206c716b9e34ebcb6d18135a29012c7",
                        "name":"cx",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"ec358fba11d44d15a96276da2d8c92b6",
                        "name":"local12345",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"08a1d89a54e64c98ba3dfc4c56de70d8",
                        "name":"fd2",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"85a3bace64bf49c49997c89e976c1797",
                        "name":"fd1",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"044bc4a61dc945079592ef6b119f5611",
                        "name":"xwscon",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"2b2add5ab7624561a89e023f1526df4e",
                        "name":"order",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"cb200d034acf4ea6b729b0b17820b5ee",
                        "name":"206fd",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"98ecb1222d9e4c1f9a5db30c44875b8e",
                        "name":"CJY_CS",
                        "pid":"1",
                        "children":null
                    },
                    {
                        "id":"5edfc7e8638845128e44f2a4da7de7eb",
                        "name":"測試數值類型",
                        "pid":"1",
                        "children":null
                    }
                ]
            },
            {
                "id":"2",
                "name":"Oracle",
                "pid":"-1",
                "children":[
                    {
                        "id":"a3b7f6eec7134de8b85bbd9dc57d07c5",
                        "name":"local",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"4b80404a54d54812bb3409ddf21442ac",
                        "name":"bzk",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"5610963be596416a9deb83ec32a16f19",
                        "name":"by",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"ead9bd5004b44e8ba791bcb2511d0b11",
                        "name":"gw測試",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"9d717d68fbe141baa8c8380fa52bc51d",
                        "name":"ORA123",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"739a330fdbba4d7ea9378ec169c30e91",
                        "name":"206ORA",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"fb48a2e3177e4c4a910a7a0c81c3e9ac",
                        "name":"xp_采集流程",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"197030e0295c4546ad3087da9c312da2",
                        "name":"測試大小寫",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"a9fad7c393b74103ba3beea7719c90e2",
                        "name":"xp_數據源配置",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"34ed62284e624bb0a4ae756fef82c9de",
                        "name":"oracle連接",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"65f4ea98c9de4f6daa7693d2fd0ab43c",
                        "name":"206123",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"7d72b8e291464d129c95592752f839ce",
                        "name":"MT18",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"0c6acdf12d554d6ea39d986c596bc4d2",
                        "name":"監控測試",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"9724796eb3aa45baa225c936e549bd81",
                        "name":"SOURCE2",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"174987a5a60b45b5beedd088dd42a02a",
                        "name":"SunOrcl",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"9899e04067554df69c67cf5b196e98b7",
                        "name":"by1",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"d314fbad49d14e05a4279fc4ccb4ce66",
                        "name":"MT",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"c8cbeff921e547e483596074a9e324fb",
                        "name":"gw_bzk",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"45e29dc086b544678e9125a1c2f0e89b",
                        "name":"YGH",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"5f21d117c256418a801eae9ee27d8cc3",
                        "name":"CHATESTU",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"e29a448c8c4c4e37a75f64ad87479cfd",
                        "name":"MT041201",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"79802451f0bb4a0f9918d24cbb3df478",
                        "name":"MT0415",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"4066e261f0bd4aab94880080594f2f42",
                        "name":"LOCS",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"63c531c5ec30436bb83c3f153bf4ea04",
                        "name":"bzk2",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"5269f15244b84074b60789a54d839ebe",
                        "name":"GB",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"f76d9389e35d40e7ba4b9d5604f9821e",
                        "name":"GW測試",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"87c3ccb1d9224972901e1cea2fee88a8",
                        "name":"orcl202",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"a9cb35c1e9564ac88a88b2aef38aeafb",
                        "name":"測試1",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"30b36c6022834b4c8fbba6b1400f7e85",
                        "name":"TEST_SUB",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"4f8f187bc8e046ccb9c0afaa2e30fa6b",
                        "name":"XP_DRI",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"47b79c6e096248e18a51568d763e9ac5",
                        "name":"ORCLCHA",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"27af4fdba1df477295f5978ca6f0704c",
                        "name":"XP_訂閱分發1",
                        "pid":"2",
                        "children":null
                    },
                    {
                        "id":"2224cfbd964e444d96acddc404622491",
                        "name":"XP_訂閱分發2",
                        "pid":"2",
                        "children":null
                    }
                ]
            },
            {
                "id":"10",
                "name":"DM",
                "pid":"-1",
                "children":[
                    {
                        "id":"362eede69f654260b891d1a9ac61cc68",
                        "name":"達夢連接",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"8331b61efdca4c82a183c69da90d5099",
                        "name":"達夢AAA",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"65eb1c3012584d9e865d2f0447fd5eb0",
                        "name":"zb",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"37562043808646709b003badbdeab8e5",
                        "name":"bzk1",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"b39484a1f6654c6ab5c2bac8763e652e",
                        "name":"達夢GW",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"0d905fdf73a94948a91406bc508b607d",
                        "name":"DM數值類型",
                        "pid":"10",
                        "children":null
                    },
                    {
                        "id":"10132ff9686145929a24de9b5c9c6eb4",
                        "name":"測試dm轉Oracle",
                        "pid":"10",
                        "children":null
                    }
                ]
            },
            {
                "id":"12",
                "name":"Kingbase8",
                "pid":"-1",
                "children":[
                    {
                        "id":"c933e63315ee4c64b70a5fa348c83059",
                        "name":"xp_1111_test1",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"a5b761ecb97a4930a8ecae16219c6fd9",
                        "name":"xp_add_1",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"12c96463ed464a7da6c0696cf272b6e0",
                        "name":"xp_test_kingbase8_22",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"14f306c4ccc94ddfb4b0cafcb79c3982",
                        "name":"XP_TEST_1",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"9a68cbf199534e28a6c8779036977edb",
                        "name":"金倉C",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"6097a77761d64e83a3a481fa9b4e000f",
                        "name":"金倉m",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"6941881032414bd2858a64efcf36db5e",
                        "name":"sunKing",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"91b67d1b3d9049c597544302f4e0053a",
                        "name":"qztable",
                        "pid":"12",
                        "children":null
                    },
                    {
                        "id":"645aadeb3d5542dfb71801c5600ef857",
                        "name":"king8",
                        "pid":"12",
                        "children":null
                    }
                ]
            }
        ]
        }
        ]
    },
    beforeDestroy() {

    },
    computed: {

    },
    methods: {
      selectTerrEvetn(data) {
        console.log(data, '勾選了')
      }
    },
    watch: {

    }
  }
</script>

<style  scoped>

</style>

 

我是馬丁的車夫,歡迎轉發收藏!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM