uni-collapse.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. <template>
  2. <view class="uni-collapse">
  3. <slot />
  4. </view>
  5. </template>
  6. <script>
  7. /**
  8. * Collapse 折叠面板
  9. * @description 展示可以折叠 / 展开的内容区域
  10. * @tutorial https://ext.dcloud.net.cn/plugin?id=23
  11. * @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array)
  12. * @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果
  13. * @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array
  14. */
  15. export default {
  16. name: 'uniCollapse',
  17. emits:['change','activeItem','input','update:modelValue'],
  18. props: {
  19. value: {
  20. type: [String, Array],
  21. default: ''
  22. },
  23. modelValue: {
  24. type: [String, Array],
  25. default: ''
  26. },
  27. accordion: {
  28. // 是否开启手风琴效果
  29. type: [Boolean, String],
  30. default: false
  31. },
  32. },
  33. data() {
  34. return {}
  35. },
  36. computed: {
  37. // TODO 兼容 vue2 和 vue3
  38. dataValue() {
  39. let value = (typeof this.value === 'string' && this.value === '') ||
  40. (Array.isArray(this.value) && this.value.length === 0)
  41. let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') ||
  42. (Array.isArray(this.modelValue) && this.modelValue.length === 0)
  43. if (value) {
  44. return this.modelValue
  45. }
  46. if (modelValue) {
  47. return this.value
  48. }
  49. return this.value
  50. }
  51. },
  52. watch: {
  53. dataValue(val) {
  54. this.setOpen(val)
  55. }
  56. },
  57. created() {
  58. this.childrens = []
  59. this.names = []
  60. },
  61. mounted() {
  62. this.$nextTick(()=>{
  63. this.setOpen(this.dataValue)
  64. })
  65. },
  66. methods: {
  67. setOpen(val) {
  68. let str = typeof val === 'string'
  69. let arr = Array.isArray(val)
  70. this.childrens.forEach((vm, index) => {
  71. if (str) {
  72. if (val === vm.nameSync) {
  73. if (!this.accordion) {
  74. console.warn('accordion 属性为 false ,v-model 类型应该为 array')
  75. return
  76. }
  77. vm.isOpen = true
  78. }
  79. }
  80. if (arr) {
  81. val.forEach(v => {
  82. if (v === vm.nameSync) {
  83. if (this.accordion) {
  84. console.warn('accordion 属性为 true ,v-model 类型应该为 string')
  85. return
  86. }
  87. vm.isOpen = true
  88. }
  89. })
  90. }
  91. })
  92. this.emit(val)
  93. },
  94. setAccordion(self) {
  95. if (!this.accordion) return
  96. this.childrens.forEach((vm, index) => {
  97. if (self !== vm) {
  98. vm.isOpen = false
  99. }
  100. })
  101. },
  102. resize() {
  103. this.childrens.forEach((vm, index) => {
  104. // #ifndef APP-NVUE
  105. vm.getCollapseHeight()
  106. // #endif
  107. // #ifdef APP-NVUE
  108. vm.getNvueHwight()
  109. // #endif
  110. })
  111. },
  112. onChange(isOpen, self) {
  113. let activeItem = []
  114. if (this.accordion) {
  115. activeItem = isOpen ? self.nameSync : ''
  116. } else {
  117. this.childrens.forEach((vm, index) => {
  118. if (vm.isOpen) {
  119. activeItem.push(vm.nameSync)
  120. }
  121. })
  122. }
  123. this.$emit('change', activeItem)
  124. this.emit(activeItem)
  125. },
  126. emit(val){
  127. this.$emit('input', val)
  128. this.$emit('update:modelValue', val)
  129. }
  130. }
  131. }
  132. </script>
  133. <style lang="scss" >
  134. .uni-collapse {
  135. /* #ifndef APP-NVUE */
  136. width: 100%;
  137. display: flex;
  138. /* #endif */
  139. /* #ifdef APP-NVUE */
  140. flex: 1;
  141. /* #endif */
  142. flex-direction: column;
  143. background-color: #fff;
  144. }
  145. </style>