selecttree.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <div class="selectTree">
  3. <el-select
  4. ref="elSelect"
  5. v-model="newVal"
  6. :placeholder="placeholder"
  7. :filter-method="filterTree"
  8. @change="$forceUpdate()"
  9. @clear="clear"
  10. popper-append-to-body
  11. >
  12. <el-option :value="newVal" :label="label" class="hasTree" disabled>
  13. <el-tree
  14. :data="openSearch ? searchData : list"
  15. ref="tree"
  16. :node-key="defaultParentProps.value"
  17. :expand-on-click-node="false"
  18. :default-expanded-keys="defaultExpandedKeys"
  19. :current-node-key="newVal"
  20. highlight-current
  21. :props="defaultParentProps"
  22. check-on-click-node
  23. auto-expand-parent
  24. @node-click="handleNodeClick"
  25. ></el-tree>
  26. </el-option>
  27. </el-select>
  28. </div>
  29. </template>
  30. <script>
  31. export default {
  32. name: "ElSelectTree",
  33. props: {
  34. value: {
  35. type: String,
  36. require: true,
  37. },
  38. list: {
  39. //树状列表:{label:'',value:'',children:[]}
  40. type: Array,
  41. default: () => {
  42. return [];
  43. },
  44. },
  45. placeholder: {
  46. type: String,
  47. default: "请选择",
  48. },
  49. type: {
  50. type: String,
  51. default: "0",
  52. },
  53. defaultParentProps: {
  54. type: Object,
  55. default: () => {
  56. return {
  57. children: "children",
  58. label: "companyName",
  59. value: "companyCode",
  60. };
  61. },
  62. },
  63. },
  64. data() {
  65. return {
  66. defaultProps: {},
  67. newVal: "", //本页面选中的数据
  68. label: "",
  69. selectTree: {},
  70. defaultExpandedKeys: [], //默认展开
  71. searchData: [], //带搜索数据
  72. openSearch: false, //是否开启搜索
  73. };
  74. },
  75. watch: {
  76. value: {
  77. handler(value) {
  78. if (value) {
  79. this.newVal = value;
  80. this.defaultExpandedKeys = [value];
  81. this.$nextTick(() => {
  82. this.$refs.tree.setCurrentKey(value); //设置默认选择
  83. });
  84. const check = this.findLabel(this.list, value);
  85. if (check) {
  86. this.label = check.companyName;
  87. }
  88. } else {
  89. this.newVal = "";
  90. this.label = "";
  91. }
  92. },
  93. deep: true, // 深度监听
  94. immediate: true, //首次触发
  95. },
  96. list: {
  97. handler(value) {
  98. if (value && this.type === "1") {
  99. this.newVal = value[0][this.defaultParentProps.value];
  100. }
  101. },
  102. deep: true, // 深度监听
  103. },
  104. newVal(value) {
  105. const check = this.findLabel(this.list, value);
  106. if (check) {
  107. this.label = check.companyName;
  108. }
  109. this.$emit("input", value);
  110. },
  111. },
  112. created() {
  113. // el-select 中加了filterable 点击箭头回收不去问题
  114. Object.getPrototypeOf(
  115. this.$options.components
  116. ).ElSelect.options.methods.handleFocus = () => {};
  117. },
  118. mounted() {},
  119. methods: {
  120. //节点选择事件
  121. handleNodeClick(data) {
  122. this.newVal = data[this.defaultParentProps.value];
  123. this.label = data[this.defaultParentProps.label];
  124. this.$refs.elSelect.blur();
  125. this.searchData = [];
  126. this.openSearch = false;
  127. this.$emit("change", data);
  128. },
  129. //筛选树
  130. async filterTree(value) {
  131. if (value) {
  132. this.openSearch = true;
  133. this.searchData = [];
  134. await this.findItem(this.list, value);
  135. } else {
  136. this.openSearch = false;
  137. this.searchData = [];
  138. }
  139. },
  140. //递归筛选,查询时用
  141. findItem(arr, value) {
  142. return new Promise((resolve) => {
  143. for (let i = 0; i < arr.length; i++) {
  144. const item = arr[i];
  145. if (item.label.includes(value)) {
  146. this.searchData.push(item);
  147. } else if (item.children && item.children.length > 0) {
  148. this.findItem(item.children, value);
  149. }
  150. }
  151. resolve(true);
  152. });
  153. },
  154. //递归筛选,回显label
  155. findLabel(arr, value) {
  156. for (let i = 0; i < arr.length; i++) {
  157. const item = arr[i];
  158. if (item[this.defaultParentProps.value] === value) {
  159. return item;
  160. } else if (item.children && item.children.length > 0) {
  161. const result = this.findLabel(item.children, value);
  162. if (result) {
  163. return result;
  164. }
  165. }
  166. }
  167. },
  168. //清空事件
  169. clear() {
  170. this.$refs.tree.setCurrentKey(null); //清空高亮
  171. this.label = "";
  172. this.newVal = "";
  173. this.searchData = [];
  174. this.openSearch = false;
  175. this.$emit("change", {});
  176. },
  177. },
  178. };
  179. </script>
  180. <style scoped lang="scss">
  181. .selectTree {
  182. display: inline-block;
  183. width: 100%;
  184. }
  185. .el-select {
  186. width: 100%;
  187. }
  188. .hasTree {
  189. padding: 0 !important;
  190. margin: 0;
  191. overflow: auto;
  192. line-height: normal;
  193. height: auto;
  194. cursor: default !important;
  195. font-weight: 500 !important;
  196. ::v-deep .el-tree-node__content {
  197. height: 34px;
  198. line-height: 34px;
  199. }
  200. ::v-deep .el-tree-node__label {
  201. font-size: 14px !important;
  202. }
  203. }
  204. </style>