• vue: 使用下拉树组件@riophae/vue-treeselect


    前言:  在vue中, 因为element-ui 2.X是没有tree-select组件的,到了element-plus就有了 @riophae/vue-treeselect是一个基于 Vue.js 的树形选择器组件,可以用于选择树形结构的数据。它支持多选、搜索、异步加载等功能,可以自定义选项的样式和模板。该组件易于使用和扩展,适用于各种类型的项目。

     1. 安装第三方包

    npm i @riophae/vue-treeselect

    2. 导入并注册

    1. import Treeselect from '@riophae/vue-treeselect'
    2. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
    3. export default {
    4. components: { Treeselect }
    5. }

    3. 基本使用

    1. <script>
    2. import Treeselect from '@riophae/vue-treeselect'
    3. import '@riophae/vue-treeselect/dist/vue-treeselect.css'
    4. import treeData from './data/tree'
    5. export default {
    6. data() {
    7. return {
    8. value: null,
    9. options: []
    10. }
    11. },
    12. components: { Treeselect },
    13. mounted(){
    14. // 延迟模拟请求数据
    15. setTimeout(() => {
    16. this.options = treeData
    17. this.value = [111, 113] // 测试回显操作
    18. }, 300)
    19. },
    20. methods:{
    21. // 选中触发(第一次回显的时候会触发,清除值的时候会触发, value值为undefined) input事件用于v-model双向绑定组件更新父组件值
    22. treeSelectInput(value, instanceId) {
    23. console.log(value, 'input事件')
    24. console.log(this.value, 'this.value -- input') // 这个不需要 延迟
    25. },
    26. // 选中触发(清除值的时候不会触发)
    27. treeSelectChange(raw, instanceId) {
    28. console.log(raw, '当前的对象')
    29. setTimeout(() => { // 如果用到this.value 需要setTimeout延迟一下拿到最新的值
    30. console.log(this.value, 'this.value -- select')
    31. })
    32. },
    33. // 移除选项时触发 当设置multiple为true时生效 raw为当前移除的对象
    34. treeSelectDeselect(raw, instanceId) {
    35. console.log(raw, 'deselect-->>')
    36. },
    37. // 搜索
    38. treeSelectSearch(searchQuery, instanceId) {
    39. console.log(searchQuery, '当前搜索的值')
    40. },
    41. // 展开触发
    42. treeSelectOpen(instanceId) {
    43. console.log('展开了')
    44. },
    45. // 关闭触发
    46. treeSelectClose(value, instanceId) {
    47. console.log(value, '当前的value值')
    48. },
    49. // 字段默认 id label 用于规范化数据源
    50. tenantIdnormalizer(node, instanceId) {
    51. if (node.children && !node.children.length) {
    52. delete node.children
    53. }
    54. return {
    55. id: node.id,
    56. label: node.title,
    57. children: node.children
    58. }
    59. }
    60. }
    61. }
    62. script>
    63. <style scoped>
    64. .main {
    65. width: 100%;
    66. height: 100%;
    67. padding: 60px 0 0 200px;
    68. }
    69. .main .tree {
    70. width: 240px;
    71. height: 40px;
    72. }
    73. ::v-deep .vue-treeselect__label {
    74. color: #606266;
    75. }
    76. style>

    4. 比较全面的属性配置参考

    1. props: {
    2. /**
    3. * 即使有禁用的选定节点,是否允许重置值
    4. */
    5. allowClearingDisabled: {
    6. type: Boolean,
    7. default: false,
    8. },
    9. /**
    10. * 选择/取消选择祖先节点时,是否应选择/取消选中其禁用的后代
    11. * 和 allowClearingDisabled 一起使用
    12. */
    13. allowSelectingDisabledDescendants: {
    14. type: Boolean,
    15. default: false,
    16. },
    17. /**
    18. * 菜单是否应始终打开
    19. */
    20. alwaysOpen: {
    21. type: Boolean,
    22. default: false,
    23. },
    24. /**
    25. * 是否将菜单加到body上
    26. */
    27. appendToBody: {
    28. type: Boolean,
    29. default: false,
    30. },
    31. /**
    32. * 是否启用异步搜索模式
    33. */
    34. async: {
    35. type: Boolean,
    36. default: false,
    37. },
    38. /**
    39. * 是否自动将组件集中在装载上?
    40. */
    41. autoFocus: {
    42. type: Boolean,
    43. default: false,
    44. },
    45. /**
    46. * 装载时自动加载根选项。当设置为“false”时,打开菜单时将加载根选项。
    47. */
    48. autoLoadRootOptions: {
    49. type: Boolean,
    50. default: true,
    51. },
    52. /**
    53. * 当用户取消选择一个节点时,会自动取消选择其祖先。仅适用于平面模式。
    54. */
    55. autoDeselectAncestors: {
    56. type: Boolean,
    57. default: false,
    58. },
    59. /**
    60. * 当用户取消选择节点时,会自动取消选择其子节点。仅适用于平面模式。
    61. */
    62. autoDeselectDescendants: {
    63. type: Boolean,
    64. default: false,
    65. },
    66. /**
    67. * 当用户选择一个节点时,会自动选择其祖先。仅适用于平面模式。
    68. */
    69. autoSelectAncestors: {
    70. type: Boolean,
    71. default: false,
    72. },
    73. /**
    74. * 当用户选择一个节点时,会自动选择其子节点。仅适用于平面模式。
    75. */
    76. autoSelectDescendants: {
    77. type: Boolean,
    78. default: false,
    79. },
    80. /**
    81. * 如果没有文本输入,按退格键是否删除最后一项。
    82. */
    83. backspaceRemoves: {
    84. type: Boolean,
    85. default: true,
    86. },
    87. /**
    88. * 在清除所有输入字段之前进行处理的函数。
    89. * 返回“false”以防止清除值
    90. * @type {function(): (boolean|Promise)}
    91. */
    92. beforeClearAll: {
    93. type: Function,
    94. default: constant(true),
    95. },
    96. /**
    97. * 在叶节点之前显示分支节点?
    98. */
    99. branchNodesFirst: {
    100. type: Boolean,
    101. default: false,
    102. },
    103. /**
    104. * 是否应该缓存每个搜索请求的结果?
    105. */
    106. cacheOptions: {
    107. type: Boolean,
    108. default: true,
    109. },
    110. /**
    111. * 是否显示重置值的“×”按钮?
    112. */
    113. clearable: {
    114. type: Boolean,
    115. default: true,
    116. },
    117. /**
    118. * 清楚文本,multiple为true时
    119. */
    120. clearAllText: {
    121. type: String,
    122. default: 'Clear all',
    123. },
    124. /**
    125. * 选择后是否清除搜索输入。
    126. * 仅当“multiple”为“true”时使用。
    127. * 对于单选模式,无论道具值如何,它总是**在选择一个选项后清除输入。
    128. */
    129. clearOnSelect: {
    130. type: Boolean,
    131. default: false,
    132. },
    133. /**
    134. * “×”按钮的标题。
    135. */
    136. clearValueText: {
    137. type: String,
    138. default: 'Clear value',
    139. },
    140. /**
    141. * 选择选项后是否关闭菜单?
    142. * 仅当“multiple”为“true”时使用。
    143. */
    144. closeOnSelect: {
    145. type: Boolean,
    146. default: true,
    147. },
    148. /**
    149. * 加载时应自动展开多少级别的分支节点。
    150. * 设置Infinity以使所有分支节点在默认情况下展开。
    151. */
    152. defaultExpandLevel: {
    153. type: Number,
    154. default: 0,
    155. },
    156. /**
    157. * 在用户开始搜索之前要显示的默认选项集。用于异步搜索模式。
    158. * 当设置为“true”时,将自动加载作为空字符串的搜索查询结果。
    159. * @type {boolean|node[]}
    160. */
    161. defaultOptions: {
    162. default: false,
    163. },
    164. /**
    165. * 如果没有文本输入,按delete键是否删除最后一项。
    166. */
    167. deleteRemoves: {
    168. type: Boolean,
    169. default: true,
    170. },
    171. /**
    172. * 用于连接隐藏字段值的多个值的分隔符。
    173. */
    174. delimiter: {
    175. type: String,
    176. default: ',',
    177. },
    178. /**
    179. * 仅显示与搜索值直接匹配的节点,不包括其祖先。
    180. *
    181. * @type {Object}
    182. */
    183. flattenSearchResults: {
    184. type: Boolean,
    185. default: false,
    186. },
    187. /**
    188. * 是否阻止选择分支节点?
    189. */
    190. disableBranchNodes: {
    191. type: Boolean,
    192. default: false,
    193. },
    194. /**
    195. * 禁用控制?
    196. */
    197. disabled: {
    198. type: Boolean,
    199. default: false,
    200. },
    201. /**
    202. * 是否禁用模糊匹配功能?
    203. */
    204. disableFuzzyMatching: {
    205. type: Boolean,
    206. default: false,
    207. },
    208. /**
    209. *是否启用平面模式。非平面模式(默认)是指:
    210. * - 每当检查分支节点时,它的所有子节点也将被检查
    211. * - 每当一个分支节点检查了所有子节点时,该分支节点本身也会被检查
    212. * 设置“true”以禁用此机制
    213. */
    214. flat: {
    215. type: Boolean,
    216. default: false,
    217. },
    218. /**
    219. * 将以所有事件作为最后一个参数进行传递。
    220. * 有助于识别事件的起源。
    221. */
    222. instanceId: {
    223. // Add two trailing "$" to distinguish from explictly specified ids.
    224. default: () => `${instanceId++}$$`,
    225. type: [String, Number],
    226. },
    227. /**
    228. * Joins multiple values into a single form field with the `delimiter` (legacy mode).
    229. * 使用“分隔符”将多个值合并到一个表单字段中(传统模式)。
    230. */
    231. joinValues: {
    232. type: Boolean,
    233. default: false,
    234. },
    235. /**
    236. * 限制所选选项的显示。
    237. * 其余部分将隐藏在limitText字符串中。
    238. */
    239. limit: {
    240. type: Number,
    241. default: Infinity,
    242. },
    243. /**
    244. * Function that processes the message shown when selected elements pass the defined limit.
    245. * @type {function(number): string}
    246. */
    247. limitText: {
    248. type: Function,
    249. default: function limitTextDefault(count) { // eslint-disable-line func-name-matching
    250. return `and ${count} more`
    251. },
    252. },
    253. /**
    254. * Text displayed when loading options.
    255. */
    256. loadingText: {
    257. type: String,
    258. default: 'Loading...',
    259. },
    260. /**
    261. * Used for dynamically loading options.
    262. * @type {function({action: string, callback: (function((Error|string)=): void), parentNode: node=, instanceId}): void}
    263. */
    264. loadOptions: {
    265. type: Function,
    266. },
    267. /**
    268. * Which node properties to filter on.
    269. */
    270. matchKeys: {
    271. type: Array,
    272. default: constant(['label']),
    273. },
    274. /**
    275. * Sets `maxHeight` style value of the menu.
    276. */
    277. maxHeight: {
    278. type: Number,
    279. default: 300,
    280. },
    281. /**
    282. * Set `true` to allow selecting multiple options (a.k.a., multi-select mode).
    283. */
    284. multiple: {
    285. type: Boolean,
    286. default: false,
    287. },
    288. /**
    289. * Generates a hidden tag with this field name for html forms.
    290. */
    291. name: {
    292. type: String,
    293. },
    294. /**
    295. * Text displayed when a branch node has no children.
    296. */
    297. noChildrenText: {
    298. type: String,
    299. default: 'No sub-options.',
    300. },
    301. /**
    302. * Text displayed when there are no available options.
    303. */
    304. noOptionsText: {
    305. type: String,
    306. default: 'No options available.',
    307. },
    308. /**
    309. * Text displayed when there are no matching search results.
    310. */
    311. noResultsText: {
    312. type: String,
    313. default: 'No results found...',
    314. },
    315. /**
    316. * Used for normalizing source data.
    317. * @type {function(node, instanceId): node}
    318. */
    319. normalizer: {
    320. type: Function,
    321. default: identity,
    322. },
    323. /**
    324. * By default (`auto`), the menu will open below the control. If there is not
    325. * enough space, vue-treeselect will automatically flip the menu.
    326. * You can use one of other four options to force the menu to be always opened
    327. * to specified direction.
    328. * Acceptable values:
    329. * - `"auto"`
    330. * - `"below"`
    331. * - `"bottom"`
    332. * - `"above"`
    333. * - `"top"`
    334. */
    335. openDirection: {
    336. type: String,
    337. default: 'auto',
    338. validator(value) {
    339. const acceptableValues = ['auto', 'top', 'bottom', 'above', 'below']
    340. return includes(acceptableValues, value)
    341. },
    342. },
    343. /**
    344. * Whether to automatically open the menu when the control is clicked.
    345. */
    346. openOnClick: {
    347. type: Boolean,
    348. default: true,
    349. },
    350. /**
    351. * Whether to automatically open the menu when the control is focused.
    352. */
    353. openOnFocus: {
    354. type: Boolean,
    355. default: false,
    356. },
    357. /**
    358. * Array of available options.
    359. * @type {node[]}
    360. */
    361. options: {
    362. type: Array,
    363. },
    364. /**
    365. * Field placeholder, displayed when there's no value.
    366. */
    367. placeholder: {
    368. type: String,
    369. default: 'Select...',
    370. },
    371. /**
    372. * Applies HTML5 required attribute when needed.
    373. */
    374. required: {
    375. type: Boolean,
    376. default: false,
    377. },
    378. /**
    379. * Text displayed asking user whether to retry loading children options.
    380. */
    381. retryText: {
    382. type: String,
    383. default: 'Retry?',
    384. },
    385. /**
    386. * Title for the retry button.
    387. */
    388. retryTitle: {
    389. type: String,
    390. default: 'Click to retry',
    391. },
    392. /**
    393. * Enable searching feature?
    394. */
    395. searchable: {
    396. type: Boolean,
    397. default: true,
    398. },
    399. /**
    400. * Search in ancestor nodes too.
    401. */
    402. searchNested: {
    403. type: Boolean,
    404. default: false,
    405. },
    406. /**
    407. * Text tip to prompt for async search.
    408. */
    409. searchPromptText: {
    410. type: String,
    411. default: 'Type to search...',
    412. },
    413. /**
    414. * Whether to show a children count next to the label of each branch node.
    415. */
    416. showCount: {
    417. type: Boolean,
    418. default: false,
    419. },
    420. /**
    421. * Used in conjunction with `showCount` to specify which type of count number should be displayed.
    422. * Acceptable values:
    423. * - "ALL_CHILDREN"
    424. * - "ALL_DESCENDANTS"
    425. * - "LEAF_CHILDREN"
    426. * - "LEAF_DESCENDANTS"
    427. */
    428. showCountOf: {
    429. type: String,
    430. default: ALL_CHILDREN,
    431. validator(value) {
    432. const acceptableValues = [ALL_CHILDREN, ALL_DESCENDANTS, LEAF_CHILDREN, LEAF_DESCENDANTS]
    433. return includes(acceptableValues, value)
    434. },
    435. },
    436. /**
    437. * Whether to show children count when searching.
    438. * Fallbacks to the value of `showCount` when not specified.
    439. * @type {boolean}
    440. */
    441. showCountOnSearch: null,
    442. /**
    443. * In which order the selected options should be displayed in trigger & sorted in `value` array.
    444. * Used for multi-select mode only.
    445. * Acceptable values:
    446. * - "ORDER_SELECTED"
    447. * - "LEVEL"
    448. * - "INDEX"
    449. */
    450. sortValueBy: {
    451. type: String,
    452. default: ORDER_SELECTED,
    453. validator(value) {
    454. const acceptableValues = [ORDER_SELECTED, LEVEL, INDEX]
    455. return includes(acceptableValues, value)
    456. },
    457. },
    458. /**
    459. * Tab index of the control.
    460. */
    461. tabIndex: {
    462. type: Number,
    463. default: 0,
    464. },
    465. /**
    466. * The value of the control.
    467. * Should be `id` or `node` object for single-select mode, or an array of `id` or `node` object for multi-select mode.
    468. * Its format depends on the `valueFormat` prop.
    469. * For most cases, just use `v-model` instead.
    470. * @type {?Array}
    471. */
    472. value: null,
    473. /**
    474. * Which kind of nodes should be included in the `value` array in multi-select mode.
    475. * Acceptable values:
    476. * - "ALL" - Any node that is checked will be included in the `value` array
    477. * - "BRANCH_PRIORITY" (default) - If a branch node is checked, all its descendants will be excluded in the `value` array
    478. * - "LEAF_PRIORITY" - If a branch node is checked, this node itself and its branch descendants will be excluded from the `value` array but its leaf descendants will be included
    479. * - "ALL_WITH_INDETERMINATE" - Any node that is checked will be included in the `value` array, plus indeterminate nodes
    480. */
    481. valueConsistsOf: {
    482. type: String,
    483. default: BRANCH_PRIORITY,
    484. validator(value) {
    485. const acceptableValues = [ALL, BRANCH_PRIORITY, LEAF_PRIORITY, ALL_WITH_INDETERMINATE]
    486. return includes(acceptableValues, value)
    487. },
    488. },
    489. /**
    490. * Format of `value` prop.
    491. * Note that, when set to `"object"`, only `id` & `label` properties are required in each `node` object in `value` prop.
    492. * Acceptable values:
    493. * - "id"
    494. * - "object"
    495. */
    496. valueFormat: {
    497. type: String,
    498. default: 'id',
    499. },
    500. /**
    501. * z-index of the menu.
    502. */
    503. zIndex: {
    504. type: [Number, String],
    505. default: 999,
    506. }
    507. }

    5. 插件的的方法配置

    1. @input // // 选中触发(第一次回显的时候会触发,清除值的时候会触发, value值为undefined) input事件用于v-model双向绑定组件更新父组件值
    2. @select // 选中触发(清除值的时候不会触发)
    3. @deselect // 移除选项时触发 当设置multiple为true时生效 raw为当前移除的对象
    4. @search-change // 搜索触发(输入框输入 值改变时)
    5. @open // 展开时触发
    6. @close // 关闭时触发

    6. 最终的效果

  • 相关阅读:
    java基础Object转String的四种方式
    weapp-tailwindcss - 在开发小程序中使用 tailwindcss 的最佳方式,免费开源,支持国内各家主流小程序平台
    JavaWeb | HTTP 协议请求与响应格式
    redisson使用过程常见问题汇总
    【解决】Unity3D中无法在MQTT事件中执行Animator
    抽象工厂模式
    Groovy反序列化链分析
    WinCC趋势跨度设置(时间范围)
    Spring实例化源码解析之循环依赖CircularReference(十三)
    nginx实现https与http共存方案
  • 原文地址:https://blog.csdn.net/qq_43340606/article/details/132755638