u-collapse-item.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <view class="u-collapse-item" :style="[itemStyle]">
  3. <view :hover-stay-time="200" class="u-collapse-head" @tap.stop="headClick" :hover-class="hoverClass" :style="[headStyle]">
  4. <block v-if="!$slots['title-all']">
  5. <view v-if="!$slots['title']" class="u-collapse-title u-line-1" :style="[{ textAlign: align ? align : 'left' },
  6. isShow && activeStyle && !arrow ? activeStyle : '']">
  7. {{ title }}
  8. </view>
  9. <slot v-else name="title" />
  10. <view class="u-icon-wrap">
  11. <u-icon v-if="arrow" :color="arrowColor" :class="{ 'u-arrow-down-icon-active': isShow }"
  12. class="u-arrow-down-icon" name="arrow-down"></u-icon>
  13. </view>
  14. </block>
  15. <slot v-else name="title-all" />
  16. </view>
  17. <view class="u-collapse-body" :style="[{
  18. height: isShow ? height + 'px' : '0'
  19. }]">
  20. <view class="u-collapse-content" :id="elId" :style="[bodyStyle]">
  21. <slot></slot>
  22. </view>
  23. </view>
  24. </view>
  25. </template>
  26. <script>
  27. /**
  28. * collapseItem 手风琴Item
  29. * @description 通过折叠面板收纳内容区域(搭配u-collapse使用)
  30. * @tutorial https://www.uviewui.com/components/collapse.html
  31. * @property {String} title 面板标题
  32. * @property {String Number} index 主要用于事件的回调,标识那个Item被点击
  33. * @property {Boolean} disabled 面板是否可以打开或收起(默认false)
  34. * @property {Boolean} open 设置某个面板的初始状态是否打开(默认false)
  35. * @property {String Number} name 唯一标识符,如不设置,默认用当前collapse-item的索引值
  36. * @property {String} align 标题的对齐方式(默认left)
  37. * @property {Object} active-style 不显示箭头时,可以添加当前选择的collapse-item活动样式,对象形式
  38. * @event {Function} change 某个item被打开或者收起时触发
  39. * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
  40. */
  41. export default {
  42. name: "u-collapse-item",
  43. props: {
  44. // 标题
  45. title: {
  46. type: String,
  47. default: ''
  48. },
  49. // 标题的对齐方式
  50. align: {
  51. type: String,
  52. default: 'left'
  53. },
  54. // 是否可以点击收起
  55. disabled: {
  56. type: Boolean,
  57. default: false
  58. },
  59. // collapse显示与否
  60. open: {
  61. type: Boolean,
  62. default: false
  63. },
  64. // 唯一标识符
  65. name: {
  66. type: [Number, String],
  67. default: ''
  68. },
  69. //活动样式
  70. activeStyle: {
  71. type: Object,
  72. default () {
  73. return {}
  74. }
  75. },
  76. // 标识当前为第几个
  77. index: {
  78. type: [String, Number],
  79. default: ''
  80. }
  81. },
  82. data() {
  83. return {
  84. isShow: false,
  85. elId: this.$u.guid(),
  86. height: 0, // body内容的高度
  87. headStyle: {}, // 头部样式,对象形式
  88. bodyStyle: {}, // 主体部分样式
  89. itemStyle: {}, // 每个item的整体样式
  90. arrowColor: '', // 箭头的颜色
  91. hoverClass: '', // 头部按下时的效果样式类
  92. arrow: true, // 是否显示右侧箭头
  93. };
  94. },
  95. watch: {
  96. open(val) {
  97. this.isShow = val;
  98. }
  99. },
  100. created() {
  101. this.parent = false;
  102. // 获取u-collapse的信息,放在u-collapse是为了方便,不用每个u-collapse-item写一遍
  103. this.isShow = this.open;
  104. },
  105. methods: {
  106. // 异步获取内容,或者动态修改了内容时,需要重新初始化
  107. init() {
  108. this.parent = this.$u.$parent.call(this, 'u-collapse');
  109. if(this.parent) {
  110. this.nameSync = this.name ? this.name : this.parent.childrens.length;
  111. // 不存在时才添加本实例
  112. !this.parent.childrens.includes(this) && this.parent.childrens.push(this);
  113. this.headStyle = this.parent.headStyle;
  114. this.bodyStyle = this.parent.bodyStyle;
  115. this.arrowColor = this.parent.arrowColor;
  116. this.hoverClass = this.parent.hoverClass;
  117. this.arrow = this.parent.arrow;
  118. this.itemStyle = this.parent.itemStyle;
  119. }
  120. this.$nextTick(() => {
  121. this.queryRect();
  122. });
  123. },
  124. // 点击collapsehead头部
  125. headClick() {
  126. if (this.disabled) return;
  127. if (this.parent && this.parent.accordion == true) {
  128. this.parent.childrens.map(val => {
  129. // 自身不设置为false,因为后面有this.isShow = !this.isShow;处理了
  130. if (this != val) {
  131. val.isShow = false;
  132. }
  133. });
  134. }
  135. this.isShow = !this.isShow;
  136. // 触发本组件的事件
  137. this.$emit('change', {
  138. index: this.index,
  139. show: this.isShow
  140. })
  141. // 只有在打开时才发出事件
  142. if (this.isShow) this.parent && this.parent.onChange();
  143. this.$forceUpdate();
  144. },
  145. // 查询内容高度
  146. queryRect() {
  147. // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://www.uviewui.com/js/getRect.html
  148. // 组件内部一般用this.$uGetRect,对外的为this.$u.getRect,二者功能一致,名称不同
  149. this.$uGetRect('#' + this.elId).then(res => {
  150. this.height = res.height;
  151. })
  152. }
  153. },
  154. mounted() {
  155. this.init();
  156. }
  157. };
  158. </script>
  159. <style lang="scss" scoped>
  160. @import "../../libs/css/style.components.scss";
  161. .u-collapse-head {
  162. position: relative;
  163. @include vue-flex;
  164. justify-content: space-between;
  165. align-items: center;
  166. color: $u-main-color;
  167. font-size: 30rpx;
  168. line-height: 1;
  169. padding: 24rpx 0;
  170. text-align: left;
  171. }
  172. .u-collapse-title {
  173. flex: 1;
  174. overflow: hidden;
  175. }
  176. .u-arrow-down-icon {
  177. transition: all 0.3s;
  178. margin-right: 20rpx;
  179. margin-left: 14rpx;
  180. }
  181. .u-arrow-down-icon-active {
  182. transform: rotate(180deg);
  183. transform-origin: center center;
  184. }
  185. .u-collapse-body {
  186. overflow: hidden;
  187. transition: all 0.3s;
  188. }
  189. .u-collapse-content {
  190. overflow: hidden;
  191. font-size: 28rpx;
  192. color: $u-tips-color;
  193. text-align: left;
  194. }
  195. </style>