u-collapse-item.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <view :style="[itemStyle]" class="u-collapse-item">
  3. <view :hover-class="hoverClass" :hover-stay-time="200" :style="[headStyle]" class="u-collapse-head"
  4. @tap.stop="headClick">
  5. <block v-if="!$slots['title-all']">
  6. <view v-if="!$slots['title']" :style="[{ textAlign: align ? align : 'left' },
  7. isShow && activeStyle && !arrow ? activeStyle : '']" class="u-collapse-title u-line-1">
  8. {{ title }}
  9. </view>
  10. <slot v-else name="title"/>
  11. <view class="u-icon-wrap">
  12. <u-icon v-if="arrow" :class="{ 'u-arrow-down-icon-active': isShow }" :color="arrowColor"
  13. class="u-arrow-down-icon" name="arrow-down"></u-icon>
  14. </view>
  15. </block>
  16. <slot v-else name="title-all"/>
  17. </view>
  18. <view :style="[{
  19. height: isShow ? height + 'px' : '0'
  20. }]" class="u-collapse-body">
  21. <view :id="elId" :style="[bodyStyle]" class="u-collapse-content">
  22. <slot></slot>
  23. </view>
  24. </view>
  25. </view>
  26. </template>
  27. <script>
  28. /**
  29. * collapseItem 手风琴Item
  30. * @description 通过折叠面板收纳内容区域(搭配u-collapse使用)
  31. * @tutorial https://www.uviewui.com/components/collapse.html
  32. * @property {String} title 面板标题
  33. * @property {String Number} index 主要用于事件的回调,标识那个Item被点击
  34. * @property {Boolean} disabled 面板是否可以打开或收起(默认false)
  35. * @property {Boolean} open 设置某个面板的初始状态是否打开(默认false)
  36. * @property {String Number} name 唯一标识符,如不设置,默认用当前collapse-item的索引值
  37. * @property {String} align 标题的对齐方式(默认left)
  38. * @property {Object} active-style 不显示箭头时,可以添加当前选择的collapse-item活动样式,对象形式
  39. * @event {Function} change 某个item被打开或者收起时触发
  40. * @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
  41. */
  42. export default {
  43. name: "u-collapse-item",
  44. props: {
  45. // 标题
  46. title: {
  47. type: String,
  48. default: ''
  49. },
  50. // 标题的对齐方式
  51. align: {
  52. type: String,
  53. default: 'left'
  54. },
  55. // 是否可以点击收起
  56. disabled: {
  57. type: Boolean,
  58. default: false
  59. },
  60. // collapse显示与否
  61. open: {
  62. type: Boolean,
  63. default: false
  64. },
  65. // 唯一标识符
  66. name: {
  67. type: [Number, String],
  68. default: ''
  69. },
  70. //活动样式
  71. activeStyle: {
  72. type: Object,
  73. default() {
  74. return {}
  75. }
  76. },
  77. // 标识当前为第几个
  78. index: {
  79. type: [String, Number],
  80. default: ''
  81. }
  82. },
  83. data() {
  84. return {
  85. isShow: false,
  86. elId: this.$u.guid(),
  87. height: 0, // body内容的高度
  88. headStyle: {}, // 头部样式,对象形式
  89. bodyStyle: {}, // 主体部分样式
  90. itemStyle: {}, // 每个item的整体样式
  91. arrowColor: '', // 箭头的颜色
  92. hoverClass: '', // 头部按下时的效果样式类
  93. arrow: true, // 是否显示右侧箭头
  94. };
  95. },
  96. watch: {
  97. open(val) {
  98. this.isShow = val;
  99. }
  100. },
  101. created() {
  102. this.parent = false;
  103. // 获取u-collapse的信息,放在u-collapse是为了方便,不用每个u-collapse-item写一遍
  104. this.isShow = this.open;
  105. },
  106. methods: {
  107. // 异步获取内容,或者动态修改了内容时,需要重新初始化
  108. init() {
  109. this.parent = this.$u.$parent.call(this, 'u-collapse');
  110. if (this.parent) {
  111. this.nameSync = this.name ? this.name : this.parent.childrens.length;
  112. 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: 30 rpx;
  168. line-height: 1;
  169. padding: 24 rpx 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: 20 rpx;
  179. margin-left: 14 rpx;
  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: 28 rpx;
  192. color: $u-tips-color;
  193. text-align: left;
  194. }
  195. </style>