vue2 , el-select 多選樹結構,可重名

人家antd都支持,elementplus 也支持,vue2的沒有,很煩。

網上其實可以搜到各種的,不過大部分不支持重名,在刪除的時候可能會刪錯,比如樹結構1F的1樓啊,2F的1樓啊這種同時勾選的情況。。

可以全路徑

干凈點不要全路徑也可以,

一股腦全放,可能有一點無效代碼,懶得刪了,等出bug再說

<template><!-- <t-tree-select:options="treeList"placeholder="請選擇tree結構"width="50%":defaultData="defaultValue":treeProps="treeProps"@handleNodeClick="selectDrop"
/> --><el-selectref="select"v-model="displayValues":multiple="multiple":filter-method="dataFilter"@remove-tag="removeTag"@clear="clearAll"popper-class="t-tree-select":style="{width: width||'100%'}"v-bind="attrs"v-on="$listeners" popper-append-to-bodyclass="select-tree"><el-option v-model="selectTree" class="option-style" disabled  ><div class="check-box" v-if="multiple&&checkBoxBtn"><el-button type="text" @click="handlecheckAll">{{checkAllText}}</el-button><el-button type="text" @click="handleReset">{{resetText}}</el-button><el-button type="text" @click="handleReverseCheck">{{reverseCheckText}}</el-button></div> <el-tree:data="options":props="treeProps"class="tree-style"ref="treeNode":check-strictly="true":show-checkbox="multiple":node-key="treeProps.value":filter-node-method="filterNode":default-checked-keys="defaultValue":current-node-key="currentKey"@node-click="handleTreeClick"@check-change="handleNodeChange"v-bind="treeAttrs"v-on="$listeners"></el-tree></el-option></el-select>
</template><script>
export default {name: 'TTreeSelect',props: {// 多選默認值數組defaultValue: {type: Array,default: () => []},// 單選默認展示數據必須是{id:***,label:***}格式defaultData: {type: Object},// 全選文字checkAllText: {type: String,default: '全選'},// 清空文字resetText: {type: String,default: '清空'},// 反選文字reverseCheckText: {type: String,default: '反選'},// 可用選項的數組options: {type: Array,default: () => []},// 配置選項——>屬性值為后端返回的對應的字段名treeProps: {type: Object,default: () => ({value: 'value', // ID字段名label: 'title', // 顯示名稱children: 'children' // 子級字段名})},// 是否顯示全選、反選、清空操作checkBoxBtn: {type: Boolean,default: false},// 是否多選multiple: {type: Boolean,default: true},// 選擇框寬度width: {type: String},// 是否顯示完整路徑, 如 1樓-1f-101showFullPath: {type: Boolean,default: true}},data() {return {selectTree: this.multiple ? [] : '', // 綁定el-option的值currentKey: null, // 當前選中的節點filterText: null, // 篩選值VALUE_NAME: this.treeProps.value, // value轉換后的字段VALUE_TEXT: this.treeProps.label, // label轉換后的字段selectedNodes: [] // 存儲選中的完整節點信息}},computed: {attrs() {return {'popper-append-to-body': false,clearable: true,filterable: true,...this.$attrs}},// tree屬性treeAttrs() {return {'default-expand-all': true,...this.$attrs}},// 顯示值:根據showFullPath決定顯示內容displayValues() {if (this.multiple) {return this.selectedNodes.map(node => this.showFullPath ? this.getNodePath(node) : node[this.VALUE_TEXT])}const firstNode = this.selectedNodes[0]if (!firstNode) return ''return this.showFullPath ? this.getNodePath(firstNode) : firstNode[this.VALUE_TEXT]}},watch: {defaultValue: {handler() {this.$nextTick(() => {// 多選if (this.multiple) {let datalist = this.$refs.treeNode.getCheckedNodes()this.selectTree = datalistthis.selectedNodes = [...datalist]}})},deep: true},// 對樹節點進行篩選操作filterText(val) {this.$refs.treeNode.filter(val)}},mounted() {this.$nextTick(() => {const scrollWrap = document.querySelectorAll(".el-scrollbar .el-select-dropdown__wrap")[0];const scrollBar = document.querySelectorAll(".el-scrollbar .el-scrollbar__bar");scrollWrap.style.cssText ="margin: 0px; max-height: none; overflow: hidden;";scrollBar.forEach((ele) => {ele.style.width = 0;});});if (this.multiple) {let datalist = this.$refs.treeNode.getCheckedNodes()this.selectTree = datalistthis.selectedNodes = [...datalist]}// 有defaultData值才回顯默認值if (this.defaultData?.id) {this.setDefaultValue(this.defaultData)}},methods: {// 獲取節點的完整路徑getNodePath(node) {const path = []let currentNode = node// 向上查找父節點,構建路徑while (currentNode) {path.unshift(currentNode[this.VALUE_TEXT])currentNode = this.findParentNode(currentNode, this.options)}return path.join('-')},// 查找父節點findParentNode(targetNode, nodes, parent = null) {for (let node of nodes) {if (node[this.VALUE_NAME] === targetNode[this.VALUE_NAME]) {return parent}if (node.children && node.children.length > 0) {const found = this.findParentNode(targetNode, node.children, node)if (found !== null) {return found}}}return null},// 單選設置默認值setDefaultValue(obj) {if (obj.label !== '' && obj.id !== '') {this.selectTree = obj.idthis.selectedNodes = [{ [this.VALUE_NAME]: obj.id, [this.VALUE_TEXT]: obj.label }]this.$nextTick(() => {this.currentKey = this.selectTreethis.setTreeChecked(this.selectTree)})}},// 全選handlecheckAll() {setTimeout(() => {this.$refs.treeNode.setCheckedNodes(this.options)}, 200)},// 清空handleReset() {setTimeout(() => {this.$refs.treeNode.setCheckedNodes([])}, 200)},/*** @description: 反選處理方法* @param {*} nodes 整個tree的數據* @param {*} refs  this.$refs.treeNode* @param {*} flag  選中狀態* @param {*} seleteds 當前選中的節點* @return {*}*/batchSelect(nodes, refs, flag, seleteds) {if (Array.isArray(nodes)) {nodes.forEach(element => {refs.setChecked(element, flag, true)})}if (Array.isArray(seleteds)) {seleteds.forEach(node => {refs.setChecked(node, !flag, true)})}},// 反選handleReverseCheck() {setTimeout(() => {let res = this.$refs.treeNodelet nodes = res.getCheckedNodes(true, true)this.batchSelect(this.options, res, true, nodes)}, 200)},// 輸入框關鍵字dataFilter(val) {setTimeout(() => {this.filterText = val}, 100)},/*** @description: tree搜索過濾* @param {*} value 搜索的關鍵字* @param {*} data  篩選到的節點* @return {*}*/filterNode(value, data) {if (!value) return truereturn data[this.treeProps.label].toLowerCase().indexOf(value.toLowerCase()) !== -1},/*** @description: 勾選樹形選項* @param {*} data 該節點所對應的對象* @param {*} self 節點本身是否被選中* @param {*} child 節點的子樹中是否有被選中的節點* @return {*}*/// 多選賦值組件handleNodeChange(data, self, child) {let datalist = this.$refs.treeNode.getCheckedNodes()this.$nextTick(() => {this.selectTree = datalistthis.selectedNodes = [...datalist]this.$emit('handleNodeClick', this.selectTree)})},// 單選tree點擊賦值handleTreeClick(data, node) {if (this.multiple) {} else {this.filterText = ''this.selectTree = data[this.VALUE_NAME]this.selectedNodes = [data]this.currentKey = this.selectTreethis.highlightNode = data[this.VALUE_NAME]this.$emit('handleNodeClick', { id: this.selectTree, label: data[this.VALUE_TEXT] }, node)this.setTreeChecked(this.highlightNode)this.$refs.select.blur()}},setTreeChecked(highlightNode) {if (this.treeAttrs.hasOwnProperty('show-checkbox')) {// 通過 keys 設置目前勾選的節點,使用此方法必須設置 node-key 屬性this.$refs.treeNode.setCheckedKeys([highlightNode])} else {// 通過 key 設置某個節點的當前選中狀態,使用此方法必須設置 node-key 屬性this.$refs.treeNode.setCurrentKey(highlightNode)}},// 移除單個標簽removeTag(displayText) {let nodeIndex = -1if (this.showFullPath) {// 完整路徑模式:根據完整路徑精確匹配nodeIndex = this.selectedNodes.findIndex(node => this.getNodePath(node) === displayText)} else {// 普通模式:根據文本匹配,刪除最后一個匹配項nodeIndex = this.selectedNodes.map(node => node[this.VALUE_TEXT]).lastIndexOf(displayText)}if (nodeIndex !== -1) {const nodeToRemove = this.selectedNodes[nodeIndex]// 從selectedNodes中移除this.selectedNodes.splice(nodeIndex, 1)// 從selectTree中移除對應的節點const treeNodeIndex = this.selectTree.findIndex(v => v[this.VALUE_NAME] === nodeToRemove[this.VALUE_NAME])if (treeNodeIndex !== -1) {this.selectTree.splice(treeNodeIndex, 1)}// 更新樹的選中狀態this.$nextTick(() => {this.$refs.treeNode.setCheckedNodes(this.selectTree)})this.$emit('handleNodeClick', this.selectTree)}},// 文本框清空clearAll() {this.selectTree = this.multiple ? [] : ''this.selectedNodes = []this.$refs.treeNode.setCheckedNodes([])this.$emit('handleNodeClick', this.selectTree)}}}
</script><style scoped lang="scss">
.t-tree-select {.check-box {padding: 0 20px;}.option-style {height: 100%;max-height: 300px;margin: 0;overflow-y: auto;cursor: default !important;}.tree-style {::v-deep .el-tree-node.is-current > .el-tree-node__content {color: #3370ff;}}.el-select-dropdown__item.selected {font-weight: 500;}.el-input__inner {height: 36px;line-height: 36px;}.el-input__icon {line-height: 36px;}.el-tree-node__content {height: 32px;}}
</style>
<style lang="scss" scoped>
::v-deep .el-tree{background: #262F40 !important;color: #FFFFFF;
}
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {height: auto;max-height: 300px;padding: 0;overflow: hidden;overflow-y: auto;
}.el-select-dropdown__item.selected {font-weight: normal;
}ul li >>> .el-tree .el-tree-node__content {height: auto;padding: 0 20px;
}.el-tree-node__label {font-weight: normal;
}.el-tree >>> .is-current .el-tree-node__label {// color: #409eff;font-weight: 700;
}.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {// color: #606266;font-weight: normal;
}::v-deep .el-tree-node__content:hover,
::v-deep .el-tree-node__content:active,
::v-deep .is-current > div:first-child,
::v-deep .el-tree-node__content:focus {background-color: rgba(#333F52, 0.5);color: #409eff;
}
::v-deep .el-tree-node__content:hover {background-color: rgba(#333F52, 0.5);color: #409eff;
}::v-deep .el-tree-node:focus>.el-tree-node__content{background-color: rgba(#333F52, 0.5);}
.el-popper {z-index: 9999;
}.el-select-dropdown__item::-webkit-scrollbar {display: none !important;
}.el-select {::v-deep.el-tag__close {// display: none !important; //隱藏在下拉框多選時單個刪除的按鈕}
}
</style><style lang="scss"  >
.select-tree {.el-tag.el-tag--info{color: #fff;border-color:none;background: #273142 !important;}.el-icon-close:before{color: rgba(245, 63, 63, 1); }.el-tag__close.el-icon-close{background-color: transparent !important;}
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83272.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83272.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83272.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

golang循環變量捕獲問題??

在 Go 語言中&#xff0c;當在循環中啟動協程&#xff08;goroutine&#xff09;時&#xff0c;如果在協程閉包中直接引用循環變量&#xff0c;可能會遇到一個常見的陷阱 - ??循環變量捕獲問題??。讓我詳細解釋一下&#xff1a; 問題背景 看這個代碼片段&#xff1a; fo…

【一文看懂Spring循環依賴】Spring循環依賴:從陷阱破局到架構涅槃

&#x1f32a;? Spring Boot循環依賴&#xff1a;從陷阱破局到架構涅槃 循環依賴如同莫比烏斯環上的螞蟻&#xff0c;看似前進卻永遠困在閉環中。本文將帶你拆解Spring中這一經典難題&#xff0c;從臨時救火到根治重構&#xff0c;構建無懈可擊的依賴體系。 &#x1f525; 一、…

el-table封裝自動滾動表格(適用大屏)

表格功能&#xff1a;自動滾動&#xff0c;鼠標移入停止滾動&#xff0c;移出繼續滾動。如果想加觸底加載新數據可以判斷 scrollWrap.scrollTop和maxScrollTop大小來加載數據&#xff0c;另寫邏輯。 <template><el-table ref"eltable" :data"tableDa…

Eureka REST 相關接口

可供非 Java 應用程序使用的 Eureka REST 操作。 appID 是應用程序的名稱&#xff0c;instanceID 是與實例關聯的唯一標識符。在 AWS 云中&#xff0c;instanceID 是實例的實例 ID&#xff1b;在其他數據中心&#xff0c;它是實例的主機名。 對于 XML/JSON&#xff0c;HTTP 的…

DSP——時鐘樹講解

配置任何外設的第一步都要看一下時鐘樹,下圖是DSP28377的時鐘樹: 由圖所示DSP28377由4個時鐘源,分別是INTOSC1、INTOSC2、XTAL、AUXCL INTOSC1:0M內部系統時鐘,備用時鐘,檢測到系統時鐘缺失自動連接到備用時鐘,也作為看門狗時鐘使用; INTOSC2:10M內部系統時鐘,復位…

少量數據達到更好效果

九坤團隊新作&#xff01;一條數據訓練AI超越上萬條數據 一 僅需一條無標簽數據和10步優化 九坤團隊訓練了13,440個大模型&#xff0c;發現熵最小化 (EM) 僅需一條無標簽數據和10步優化&#xff0c;就能實現與強化學習中使用成千上萬條數據和精心設計的獎勵機制所取得的性能提…

html - <mark>標簽

<mark> 標簽在HTML中用于高亮顯示文本&#xff0c;通常用于突出顯示某些重要的部分。它的默認樣式通常是背景色為黃色&#xff0c;但你可以通過CSS自定義其外觀。 1. 基本用法 <mark> 標簽用于標記文本的高亮顯示。它常用于搜索結果中&#xff0c;突出顯示匹配的…

YOLOv8+ByteTrack:高精度人車過線統計系統搭建指南

文章目錄 1. 引言2. YOLOv8簡介3. 過線統計原理4. 代碼實現4.1 環境準備4.2 基礎檢測代碼4.3 過線統計實現4.4 完整代碼示例5. 性能優化與改進5.1 多線程處理5.2 區域檢測優化5.3 使用ByteTrack改進跟蹤6. 實際應用中的挑戰與解決方案7. 總結與展望1. 引言 目標檢測是計算機視…

20、React常用API和Hook索引

這一小節中只給出一些API和Hook的索引&#xff0c;需要用到的時候可以去官網查詢&#xff0c;如無必要此處不列出詳細用法。React v1.19.1。 對Components的支持 以下是開發時通用的一些功能組件 APIdescription<Fragment>通常使用 <>…</> 代替&#xff0…

Python爬蟲實戰:研究feedparser庫相關技術

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上存在著海量的信息資源。RSS(Really Simple Syndication)作為一種標準化的信息聚合技術,被廣泛用于網站內容的發布和訂閱。通過 RSS,用戶可以方便地獲取網站更新的內容,而無需頻繁訪問各個網站。 然而,互聯網…

HTML實現的2048游戲

以下是一個純HTML實現的2048游戲代碼&#xff0c;包含CSS和JavaScript&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>2048 Game</title><style>body {font-family: Arial, sans-serif;text-a…

使用Python 構建支持主流大模型與 Ollama 的統一接口平臺

?? 背景概述 近年來,隨著大語言模型(LLM)的蓬勃發展,OpenAI 的 GPT 系列、Google 的 Gemini、Anthropic 的 Claude、以及開源的 Ollama 本地模型等,逐漸成為自然語言處理、智能問答、AI 助手等應用的基礎組件。 開發者在使用這些模型時常面臨如下問題: 各模型接口不統…

計算機系統概述(4)

計算機系統層次結構&#xff1a;硬件層、系統層、應用層。 計算機的基本硬件系統由運算器、控制器、存儲器、輸入設備和輸出設備5大部件組成。 運算器、控制器等部件被集成在一起統稱為中央處理單元CPU。 存儲器是計算機系統中的記憶設備&#xff0c;分為內部存儲器和外部存…

Linux 下的COW機制(copy-on-write)

Linux通過MMU進行虛擬地址到物理地址的轉換&#xff0c;當進程執行fork()后&#xff0c;會把頁中的權限設置為RD-ONLY&#xff08;只讀&#xff09;。 MMU&#xff08;內存管理單元&#xff09; MMU本質是一個集成在CPU核心的硬件電路模塊&#xff0c;其核心任務是實現…

客戶案例 | 短視頻點播企業海外視頻加速與成本優化:MediaPackage+Cloudfront 技術重構實踐

01技術背景與業務挑戰 某短視頻點播企業深耕國內用戶市場&#xff0c;但其后臺應用系統部署于東南亞印尼 IDC 機房。 隨著業務規模擴大&#xff0c;傳統架構已較難滿足當前企業發展的需求&#xff0c;企業面臨著三重挑戰&#xff1a; ① 業務&#xff1a;國內用戶訪問海外服…

開發Vue.js組件的二三事

Vue.js作為一款漸進式JavaScript框架&#xff0c;其組件化開發模式是其核心優勢之一。在多年的Vue開發實踐中&#xff0c;我積累了一些組件開發的經驗和思考&#xff0c;在此與大家分享。 組件設計原則 單一職責原則 每個組件應該只關注一個特定的功能或UI部分。如果一個組件…

實現多路視頻截圖預覽之后上傳到后臺系統

********************父組件********************** <div class"camera-box" v-loading"i.loading"> <div class"camera-box-inner" v-for"(x, y) in i.children" :key"y children x.featureCode" v-show"…

分布式鎖-Redisson實現

目錄 本地鎖的局限性 Redisson解決分布式鎖問題 在分布式環境下&#xff0c;分布式鎖可以保證在多個節點上的并發操作時數據的一致性和互斥性。分布式鎖有多種實現方案&#xff0c;最常用的兩種方案是&#xff1a;zookeeper和redis&#xff0c;本文介紹redis實現分布式鎖方案…

【辦公類-48-04】202506每月電子屏臺賬匯總成docx-5(問卷星下載5月范圍內容,自動獲取excel文件名,并轉移處理)

背景需求&#xff1a; 1-4月電子屏表格&#xff0c;都是用這個代碼將EXCEL數據整理成分類成3個WORD表格。 【辦公類-48-04】20250118每月電子屏臺賬匯總成docx-4&#xff08;提取EXCLE里面1月份的內容&#xff0c;自制月份文件夾&#xff09;-CSDN博客文章瀏覽閱讀1.2k次&…

【websocket】安裝與使用

websocket安裝與使用 1. 介紹2. 安裝3. websocketpp常用接口4. Websocketpp使用4.1 服務端4.2 客戶端 1. 介紹 WebSocket 是從 HTML5 開始支持的一種網頁端和服務端保持長連接的 消息推送機制。 傳統的 web 程序都是屬于 “一問一答” 的形式&#xff0c;即客戶端給服務器發送…