blob: 3b66bfa5583883cc5f779cab7f7cb9d96f7a5d41 [file] [log] [blame]
guangchao.xu070005a2020-12-07 09:56:40 +08001<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
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 },
97 watch: {
98 open(val) {
99 this.isShow = val;
100 }
101 },
102 created() {
103 this.parent = false;
104 // 获取u-collapse的信息,放在u-collapse是为了方便,不用每个u-collapse-item写一遍
105 this.isShow = this.open;
106 },
107 methods: {
108 // 异步获取内容,或者动态修改了内容时,需要重新初始化
109 init() {
110 this.parent = this.$u.$parent.call(this, 'u-collapse');
111 if(this.parent) {
112 this.nameSync = this.name ? this.name : this.parent.childrens.length;
113 this.parent.childrens.push(this);
114 this.headStyle = this.parent.headStyle;
115 this.bodyStyle = this.parent.bodyStyle;
116 this.arrowColor = this.parent.arrowColor;
117 this.hoverClass = this.parent.hoverClass;
118 this.arrow = this.parent.arrow;
119 this.itemStyle = this.parent.itemStyle;
120 }
121 this.$nextTick(() => {
122 this.queryRect();
123 });
124 },
125 // 点击collapsehead头部
126 headClick() {
127 if (this.disabled) return;
128 if (this.parent && this.parent.accordion == true) {
129 this.parent.childrens.map(val => {
130 // 自身不设置为false,因为后面有this.isShow = !this.isShow;处理了
131 if (this != val) {
132 val.isShow = false;
133 }
134 });
135 }
136
137 this.isShow = !this.isShow;
138 // 触发本组件的事件
139 this.$emit('change', {
140 index: this.index,
141 show: this.isShow
142 })
143 // 只有在打开时才发出事件
144 if (this.isShow) this.parent && this.parent.onChange();
145 this.$forceUpdate();
146 },
147 // 查询内容高度
148 queryRect() {
149 // $uGetRect为uView自带的节点查询简化方法,详见文档介绍:https://www.uviewui.com/js/getRect.html
150 // 组件内部一般用this.$uGetRect,对外的为this.$u.getRect,二者功能一致,名称不同
151 this.$uGetRect('#' + this.elId).then(res => {
152 this.height = res.height;
153 })
154 }
155 },
156 mounted() {
157 this.init();
158 }
159 };
160</script>
161
162<style lang="scss" scoped>
163 @import "../../libs/css/style.components.scss";
164
165 .u-collapse-head {
166 position: relative;
167 @include vue-flex;
168 justify-content: space-between;
169 align-items: center;
170 color: $u-main-color;
171 font-size: 30rpx;
172 line-height: 1;
173 padding: 24rpx 0;
174 text-align: left;
175 }
176
177 .u-collapse-title {
178 flex: 1;
179 overflow: hidden;
180 }
181
182 .u-arrow-down-icon {
183 transition: all 0.3s;
184 margin-right: 20rpx;
185 margin-left: 14rpx;
186 }
187
188 .u-arrow-down-icon-active {
189 transform: rotate(180deg);
190 transform-origin: center center;
191 }
192
193 .u-collapse-body {
194 overflow: hidden;
195 transition: all 0.3s;
196 }
197
198 .u-collapse-content {
199 overflow: hidden;
200 font-size: 28rpx;
201 color: $u-tips-color;
202 text-align: left;
203 }
204</style>