index.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import baseComponent from '../helpers/baseComponent'
  2. import classNames from '../helpers/libs/classNames'
  3. import arrayTreeFilter from '../helpers/libs/arrayTreeFilter'
  4. import fieldNamesBehavior from '../helpers/mixins/fieldNamesBehavior'
  5. import { props } from '../multi-picker-view/props'
  6. baseComponent({
  7. behaviors: [fieldNamesBehavior],
  8. properties: {
  9. ...props,
  10. cols: {
  11. type: Number,
  12. value: 3,
  13. },
  14. },
  15. data: {
  16. inputValue: [],
  17. showOptions: [],
  18. },
  19. observers: {
  20. inputValue(newVal) {
  21. // HACK: 去掉不必要的属性,防止数据溢出
  22. const valueName = this.getFieldName('value')
  23. const labelName = this.getFieldName('label')
  24. const disabledName = this.getFieldName('disabled')
  25. const showOptions = this.getShowOptions(newVal).reduce((acc, option) => (
  26. [...acc, option.map((v) => ({
  27. [valueName]: v[valueName],
  28. [labelName]: v[labelName],
  29. [disabledName]: !!v[disabledName],
  30. }))]
  31. ), [])
  32. this.setData({ showOptions })
  33. },
  34. ['value, options, cols'](value, options, cols) {
  35. this.setValue(value, options, cols)
  36. },
  37. },
  38. methods: {
  39. updated(inputValue) {
  40. if (this.data.inputValue !== inputValue) {
  41. this.setData({
  42. inputValue,
  43. })
  44. }
  45. },
  46. setValue(value, options, cols) {
  47. const inputValue = this.getRealValue(options, value, cols)
  48. this.updated(inputValue)
  49. },
  50. onValueChange(e) {
  51. const { value, index } = e.detail
  52. const newValue = this.getNextValue(value, index)
  53. const inputValue = this.getRealValue(this.data.options, newValue)
  54. const values = this.getValue(inputValue)
  55. // forceUpdate picker
  56. this.updated(inputValue)
  57. this.triggerEvent('valueChange', { ...values, index })
  58. },
  59. getValue(value = this.data.inputValue) {
  60. const newValue = this.getRealValue(this.data.options, Array.isArray(value) ? value : [])
  61. const newShowOptions = this.getShowOptions(newValue)
  62. this.picker = this.picker || this.querySelector('#wux-picker')
  63. return this.picker.getValue(newValue, newShowOptions)
  64. },
  65. getNextValue(activeValue, index) {
  66. const { options } = this.data
  67. const value = this.getFieldName('value')
  68. const childrenKeyName = this.getFieldName('children')
  69. const children = arrayTreeFilter(options, (option, level) => level <= index && option[value] === activeValue[level], { childrenKeyName })
  70. let data = children[index]
  71. let i = index + 1
  72. while (i < this.data.cols) {
  73. if (data && data[childrenKeyName] && data[childrenKeyName].length) {
  74. data = data[childrenKeyName][0]
  75. activeValue[i] = data[value]
  76. }
  77. i++
  78. }
  79. activeValue.length = i
  80. return activeValue
  81. },
  82. getRealValue(options, activeValue, cols = this.data.cols) {
  83. if (!activeValue || !activeValue.length || activeValue.indexOf(undefined) > -1 || activeValue.length !== cols) {
  84. const value = this.getFieldName('value')
  85. const childrenKeyName = this.getFieldName('children')
  86. let newValue = []
  87. let data = [...options]
  88. let i = 0
  89. while (i < cols) {
  90. if (data && data.length) {
  91. newValue[i] = activeValue[i] || data[0][value]
  92. let index = 0
  93. if (newValue[i]) {
  94. index = data.map((v) => v[value]).indexOf(newValue[i])
  95. if (index === -1) {
  96. index = 0
  97. newValue[i] = data[0][value]
  98. }
  99. }
  100. data = data[index][childrenKeyName]
  101. }
  102. i++
  103. }
  104. return newValue
  105. }
  106. return activeValue
  107. },
  108. getActiveOptions(activeValue) {
  109. const { options } = this.data
  110. const value = this.getFieldName('value')
  111. const childrenKeyName = this.getFieldName('children')
  112. return arrayTreeFilter(options, (option, level) => option[value] === activeValue[level], { childrenKeyName })
  113. },
  114. getShowOptions(activeValue) {
  115. const { options, cols } = this.data
  116. const children = this.getFieldName('children')
  117. const result = this.getActiveOptions(activeValue).map((activeOption) => activeOption[children]).filter((activeOption) => !!activeOption)
  118. return [options, ...result].filter((_, i) => i < cols)
  119. },
  120. },
  121. attached() {
  122. const { value, options, cols } = this.data
  123. this.setValue(value, options, cols)
  124. },
  125. })