uni-collapse-item.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. <template>
  2. <view class="uni-collapse-item">
  3. <view class="uni-collapse-item__title" @click="openCollapse(!is_open)">
  4. <text class="uni-collapse-item__title-text" :class="{'is-disabled':disabled,'open--active':is_open}">{{title}}</text>
  5. <view class="down_arrow" :class="{'down_arrow--active': is_open}"></view>
  6. </view>
  7. <view ref="boxRef" class="uni-collapse-item__content" :class="{'box-open--active':is_open}">
  8. <view ref="contentRef" class="uni-collapse-item__content-box" :class="{'content-open--active':box_is_open}">
  9. <slot></slot>
  10. </view>
  11. </view>
  12. </view>
  13. </template>
  14. <script lang="uts">
  15. import { $dispatch } from './util.uts'
  16. export default {
  17. name: "UniCollapseItem",
  18. props: {
  19. // 列表标题
  20. title: {
  21. type: String,
  22. default: ''
  23. },
  24. open: {
  25. type: Boolean,
  26. default: false
  27. },
  28. disabled: {
  29. type: Boolean,
  30. default: false
  31. }
  32. },
  33. data() {
  34. return {
  35. height: 0,
  36. is_open: this.open as boolean,
  37. box_is_open: this.open as boolean,
  38. boxNode: null as UniElement | null,
  39. contentNode: null as UniElement | null,
  40. };
  41. },
  42. watch: {
  43. open(value : boolean) {
  44. // this.is_open = value
  45. if (this.boxNode != null) {
  46. this.openCollapse(value)
  47. }
  48. }
  49. },
  50. created() {
  51. $dispatch(this, 'UniCollapse', 'init', this)
  52. },
  53. mounted() {
  54. this.boxNode = this.$refs['boxRef'] as UniElement;
  55. this.contentNode = this.$refs['contentRef'] as UniElement;
  56. // this.openCollapse(this.open)
  57. },
  58. methods: {
  59. // 开启或关闭折叠面板
  60. openCollapse(open : boolean) {
  61. if (this.disabled) return
  62. // 关闭其他已打开
  63. $dispatch(this, 'UniCollapse', 'cloceAll')
  64. this.is_open = open
  65. this.openOrClose(open)
  66. },
  67. openOrClose(open : boolean) {
  68. // #ifdef MP-WEIXIN
  69. setTimeout(() => {
  70. this.box_is_open = open
  71. }, 10)
  72. // #endif
  73. // #ifndef MP-WEIXIN
  74. const boxNode = this.boxNode?.style!;
  75. const contentNode = this.contentNode?.style!;
  76. let hide = open ? 'flex' : 'none';
  77. const opacity = open ? "1" : "0"
  78. let ani_transform = open ? 'translateY(0)' : 'translateY(-100%)';
  79. boxNode.setProperty('display', hide);
  80. this.$nextTick(() => {
  81. setTimeout(() => {
  82. contentNode.setProperty('transform', ani_transform);
  83. contentNode.setProperty('opacity', opacity);
  84. }, 10)
  85. })
  86. // #endif
  87. }
  88. }
  89. }
  90. </script>
  91. <style>
  92. /* .uni-collapse-item {
  93. background-color: #fff;
  94. } */
  95. .uni-collapse-item .uni-collapse-item__title {
  96. flex-direction: row;
  97. align-items: center;
  98. padding: 12px 18px;
  99. background-color: #ffffff;
  100. }
  101. .uni-collapse-item .down_arrow {
  102. width: 8px;
  103. height: 8px;
  104. transform: rotate(45deg);
  105. border-right: 1px #999 solid;
  106. border-bottom: 1px #999 solid;
  107. margin-top: -3px;
  108. transition-property: transform;
  109. transition-duration: 0.2s;
  110. }
  111. .uni-collapse-item .down_arrow--active {
  112. transform: rotate(-135deg);
  113. margin-top: 0px;
  114. }
  115. .uni-collapse-item .uni-collapse-item__title-text {
  116. flex: 1;
  117. color: #000;
  118. font-size: 14px;
  119. font-weight: 400;
  120. }
  121. .uni-collapse-item .open--active {
  122. /* background-color: #f0f0f0; */
  123. color: #bbb;
  124. }
  125. .uni-collapse-item .is-disabled {
  126. color: #999;
  127. }
  128. .uni-collapse-item .uni-collapse-item__content {
  129. display: none;
  130. position: relative;
  131. overflow: hidden;
  132. }
  133. .uni-collapse-item .box-open--active {
  134. display: flex;
  135. }
  136. .uni-collapse-item .uni-collapse-item__content-box {
  137. width: 100%;
  138. transition-property: transform, opacity;
  139. transition-duration: 0.2s;
  140. transform: translateY(-100%);
  141. opacity: 0;
  142. }
  143. /* #ifdef MP-WEIXIN */
  144. .uni-collapse-item .content-open--active {
  145. transform: translateY(0%);
  146. opacity: 1;
  147. }
  148. /* #endif */
  149. </style>