vue项目中,如h5端,第三方的树形选择器无法满足项目开发时,原生封装tree控件,通过判断是否存在子节点,循环递归组件完成树形封装,通过vue指令实现跨级传递数据或方法
封装树形组件如下:
1 <template> 2 <div class="tree-select-page"> 3 <div class="tree-item" v-for="item in treeData" :key="item.key"> 4 <div class="tree-item-options"> 5 <div class="tree-item-left"> 6 <!-- 有子级,出现箭头 --> 7 <div class="tree-item-icon" @click="hanlderOpen(item)" v-if="item.children"> 8 <img 9 src="../../../assets/images/common/icon-up.png" 10 v-if="expandedKeys.includes(item.key)" 11 /> 12 <img src="../../../assets/images/common/icon-down.png" v-else /> 13 </div> 14 <div class="tree-item-img" v-if="$slots.treeIcon" :class="{ 'ml-16': !item.children }"> 15 <slot name="treeIcon"></slot> 16 </div> 17 <div class="tree-item-content" :class="{ 'ml-8': !item.children }"> 18 <div class="tree-item-title" :title="item.title"> 19 {{ item.title }} 20 </div> 21 <div class="tree-item-desc"> 22 <slot name="desc"></slot> 23 <span v-if="!$slots.desc && item.desc">{{ item.desc }}</span> 24 </div> 25 </div> 26 </div> 27 <div class="tree-item-right" @click="selectItem(item)"> 28 <slot name="right"></slot> 29 <span 30 v-if="!$slots.right" 31 class="ok-checkbox" 32 :class="{ 'ok-checkbox-checked': selectedKeys.includes(item.key) }" 33 > 34 <span class="ok-checkbox-inner"></span> 35 </span> 36 </div> 37 <div class="tree-item-line"></div> 38 </div> 39 <!-- 调用自己生成子级 --> 40 <!-- v-bind="$props",v-on="$listeners":多级嵌套的中间件,用于跨级传递 --> 41 <TreeSelect 42 :list="item.children" 43 v-bind="$props" 44 :selectIds.sync="selectedKeys" 45 v-if="item.children && expandedKeys.includes(item.key)" 46 style="padding-left: 16px" 47 v-on="$listeners" 48 > 49 <!-- 自定义内容 --> 50 <template slot="treeIcon"> 51 <slot name="treeIcon"></slot> 52 </template> 53 <template slot="desc"> 54 <slot name="desc"></slot> 55 </template> 56 <template slot="right"> 57 <slot name="right"></slot> 58 </template> 59 </TreeSelect> 60 </div> 61 </div> 62 </template> 63 64 <script> 65 export default { 66 name: 'TreeSelect', 67 props: { 68 // 传入的树形结构数据 69 list: { 70 type: Array, 71 default() { 72 return []; 73 } 74 }, 75 // 选中的选项 76 selectedIds: { 77 type: Array, 78 default() { 79 return []; 80 } 81 } 82 }, 83 data() { 84 return { 85 listMap: {}, // 数组对象 86 treeData: [], // 数据 87 selectedKeys: [], // 选中的keys 88 expandedKeys: [] // 展开的keys 89 }; 90 }, 91 watch: { 92 // 监听选中项改变 93 selectedIds(val) { 94 this.selectedKeys = val; 95 } 96 }, 97 created() { 98 this.treeData = this.list; 99 this.selectedKeys = this.selectedIds; 100 }, 101 methods: { 102 hanlderOpen(data) { 103 if (!data.children) return; 104 // 展开/收起 树形控件,请求数据 105 const targ = this.expandedKeys.includes(data.key); 106 if (!targ) { 107 // 展开项数组中无对应数据,则为展开操作 108 this.expandedKeys = [...this.expandedKeys, data.key]; 109 } else { 110 //反之,收起操作 111 this.expandedKeys = this.expandedKeys.filter((item) => item !== data.key); 112 } 113 // 展开/收起抛出方法,用于父级操作数据 114 this.$emit('expand', targ, this.expandedKeys, data); 115 }, 116 selectItem(data) { 117 // 选择操作,与展开/收起逻辑相同 118 const targ = this.selectedKeys.includes(data.key); 119 if (!targ) { 120 this.selectedKeys.push(data.key); 121 } else { 122 this.selectedKeys = this.selectedKeys.filter((item) => item !== data.key); 123 } 124 // 抛出选择方法 125 this.$emit('selectKeys', this.selectedKeys); 126 } 127 } 128 }; 129 </script> 130 131 <style lang="less" scoped> 132 .tree-select-page { 133 background: #fff; 134 .tree-item-line { 135 height: 1px; 136 width: calc(100% - 8px); 137 margin-left: 8px; 138 background: #eaeaea; 139 position: absolute; 140 bottom: 0; 141 left: 0; 142 right: 0; 143 } 144 .tree-item-options { 145 padding: 8px 15px 8px 8px; 146 display: flex; 147 align-items: center; 148 justify-content: space-between; 149 position: relative; 150 151 .tree-item-left { 152 display: flex; 153 align-items: center; 154 width: calc(100% - 24px); 155 .tree-item-icon { 156 margin-right: 8px; 157 width: 24px; 158 img { 159 width: 24px; 160 height: 24px; 161 } 162 } 163 .tree-item-img { 164 height: 40px; 165 width: 40px; 166 margin-right: 16px; 167 } 168 .ml-8 { 169 margin-left: 8px; 170 } 171 .ml-16 { 172 margin-left: 16px; 173 } 174 .tree-item-content { 175 text-align: left; 176 flex-grow: 1; 177 overflow: hidden; 178 .tree-item-title { 179 font-size: 18px; 180 color: #2f2f2e; 181 line-height: 24px; 182 font-weight: 500; 183 overflow: hidden; 184 width: 100%; 185 text-overflow: ellipsis; 186 white-space: nowrap; 187 } 188 .tree-item-desc { 189 margin-top: 4px; 190 font-size: 14px; 191 color: #999999; 192 line-height: 16px; 193 font-weight: 400; 194 overflow: hidden; 195 text-overflow: ellipsis; 196 display: -webkit-box; 197 -webkit-line-clamp: 3; 198 -webkit-box-orient: vertical; 199 } 200 } 201 } 202 } 203 } 204 :deep(.ok-checkbox.ok-checkbox-checked .ok-checkbox-inner) { 205 // border-color: #07c160; 206 // background: #07c160; 207 border-color: var(--feature-color-primary); 208 background: var(--feature-color-primary); 209 } 210 </style>
父级组件:(部分代码)
1 <TreeSelect 2 :list="treeData" 3 :selectedIds="selectedKeys" 4 @selectKeys="treeSelectKeys" 5 @expand="expandTree" 6 > 7 <div slot="desc">自定义说明书</div> 8 <div class="tree-left-icon" slot="treeIcon"> 9 <img src="../../assets/images/broadcast/icon-group.png" /> 10 </div> 11 </TreeSelect> 12 <div class="click-btn-box" @click="submitTreeSelect">提交树形控件选中</div>
父组件传给子组件的数据
1 // 树形控件选择器 2 selectedIds: [], 3 selectedKeys: [], 4 treeData: [ 5 { 6 title: '一一级', 7 key: 'one-one-key', 8 desc: '说明书', 9 children: [ 10 { 11 title: '一二级', 12 key: 'one-two-key', 13 children: [ 14 { 15 title: '一三级', 16 key: 'one-three-key' 17 } 18 ] 19 } 20 ] 21 }, 22 { 23 title: '二一级', 24 key: 'two-one-key', 25 desc: '说明书', 26 children: [ 27 { 28 title: '二二级', 29 key: 'two-two-key', 30 children: [ 31 { 32 title: '二三级', 33 key: 'two-three-key' 34 } 35 ] 36 } 37 ] 38 } 39 ],
方法的调用,数据回传显示
1 treeSelectKeys(ids) { 2 this.selectedKeys = ids; 3 console.log('this.selectedKeys--', this.selectedKeys); 4 console.log('tree调用---keys---回传', this.selectedKeys); 5 }, 6 expandTree(targ, keys, data) { 7 console.log('expandTree---', targ, keys, data); 8 if (targ) { 9 // 收起 10 } else { 11 // 展开 12 } 13 }, 14 submitTreeSelect() { 15 // 树形控件提交 16 console.log('submitTreeSelect---', this.selectedKeys); 17 },
实现的效果如下:
标签:控件,vue,tree,selectedKeys,item,树形,key,data From: https://www.cnblogs.com/liangxia/p/17716951.html