| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402 | 
							- <template>
 
- 	<view class="uni-collapse-item">
 
- 		<!-- onClick(!isOpen) -->
 
- 		<view @click="onClick(!isOpen)" class="uni-collapse-item__title"
 
- 			:class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}">
 
- 			<view class="uni-collapse-item__title-wrap">
 
- 				<slot name="title">
 
- 					<view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}">
 
- 						<image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
 
- 						<text class="uni-collapse-item__title-text">{{ title }}</text>
 
- 					</view>
 
- 				</slot>
 
- 			</view>
 
- 			<view v-if="showArrow"
 
- 				:class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }"
 
- 				class="uni-collapse-item__title-arrow">
 
- 				<uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" />
 
- 			</view>
 
- 		</view>
 
- 		<view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}"
 
- 			:style="{height: (isOpen?height:0) +'px'}">
 
- 			<view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content"
 
- 				:class="{open:isheight,'uni-collapse-item--border':border&&isOpen}">
 
- 				<slot></slot>
 
- 			</view>
 
- 		</view>
 
- 	</view>
 
- </template>
 
- <script>
 
- 	// #ifdef APP-NVUE
 
- 	const dom = weex.requireModule('dom')
 
- 	// #endif
 
- 	/**
 
- 	 * CollapseItem 折叠面板子组件
 
- 	 * @description 折叠面板子组件
 
- 	 * @property {String} title 标题文字
 
- 	 * @property {String} thumb 标题左侧缩略图
 
- 	 * @property {String} name 唯一标志符
 
- 	 * @property {Boolean} open = [true|false] 是否展开组件
 
- 	 * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线
 
- 	 * @property {Boolean} border = [true|false] 是否显示分隔线
 
- 	 * @property {Boolean} disabled = [true|false] 是否展开面板
 
- 	 * @property {Boolean} showAnimation = [true|false] 开启动画
 
- 	 * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头
 
- 	 */
 
- 	export default {
 
- 		name: 'uniCollapseItem',
 
- 		props: {
 
- 			// 列表标题
 
- 			title: {
 
- 				type: String,
 
- 				default: ''
 
- 			},
 
- 			name: {
 
- 				type: [Number, String],
 
- 				default: ''
 
- 			},
 
- 			// 是否禁用
 
- 			disabled: {
 
- 				type: Boolean,
 
- 				default: false
 
- 			},
 
- 			// #ifdef APP-PLUS
 
- 			// 是否显示动画,app 端默认不开启动画,卡顿严重
 
- 			showAnimation: {
 
- 				type: Boolean,
 
- 				default: false
 
- 			},
 
- 			// #endif
 
- 			// #ifndef APP-PLUS
 
- 			// 是否显示动画
 
- 			showAnimation: {
 
- 				type: Boolean,
 
- 				default: true
 
- 			},
 
- 			// #endif
 
- 			// 是否展开
 
- 			open: {
 
- 				type: Boolean,
 
- 				default: false
 
- 			},
 
- 			// 缩略图
 
- 			thumb: {
 
- 				type: String,
 
- 				default: ''
 
- 			},
 
- 			// 标题分隔线显示类型
 
- 			titleBorder: {
 
- 				type: String,
 
- 				default: 'auto'
 
- 			},
 
- 			border: {
 
- 				type: Boolean,
 
- 				default: true
 
- 			},
 
- 			showArrow: {
 
- 				type: Boolean,
 
- 				default: true
 
- 			}
 
- 		},
 
- 		data() {
 
- 			// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
 
- 			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
 
- 			return {
 
- 				isOpen: false,
 
- 				isheight: null,
 
- 				height: 0,
 
- 				elId,
 
- 				nameSync: 0
 
- 			}
 
- 		},
 
- 		watch: {
 
- 			open(val) {
 
- 				this.isOpen = val
 
- 				this.onClick(val, 'init')
 
- 			}
 
- 		},
 
- 		updated(e) {
 
- 			this.$nextTick(() => {
 
- 				this.init(true)
 
- 			})
 
- 		},
 
- 		created() {
 
- 			this.collapse = this.getCollapse()
 
- 			this.oldHeight = 0
 
- 			this.onClick(this.open, 'init')
 
- 		},
 
- 		// #ifndef VUE3
 
- 		// TODO vue2
 
- 		destroyed() {
 
- 			if (this.__isUnmounted) return
 
- 			this.uninstall()
 
- 		},
 
- 		// #endif
 
- 		// #ifdef VUE3
 
- 		// TODO vue3
 
- 		unmounted() {
 
- 			this.__isUnmounted = true
 
- 			this.uninstall()
 
- 		},
 
- 		// #endif
 
- 		mounted() {
 
- 			if (!this.collapse) return
 
- 			if (this.name !== '') {
 
- 				this.nameSync = this.name
 
- 			} else {
 
- 				this.nameSync = this.collapse.childrens.length + ''
 
- 			}
 
- 			if (this.collapse.names.indexOf(this.nameSync) === -1) {
 
- 				this.collapse.names.push(this.nameSync)
 
- 			} else {
 
- 				console.warn(`name 值 ${this.nameSync} 重复`);
 
- 			}
 
- 			if (this.collapse.childrens.indexOf(this) === -1) {
 
- 				this.collapse.childrens.push(this)
 
- 			}
 
- 			this.init()
 
- 		},
 
- 		methods: {
 
- 			init(type) {
 
- 				// #ifndef APP-NVUE
 
- 				this.getCollapseHeight(type)
 
- 				// #endif
 
- 				// #ifdef APP-NVUE
 
- 				this.getNvueHwight(type)
 
- 				// #endif
 
- 			},
 
- 			uninstall() {
 
- 				if (this.collapse) {
 
- 					this.collapse.childrens.forEach((item, index) => {
 
- 						if (item === this) {
 
- 							this.collapse.childrens.splice(index, 1)
 
- 						}
 
- 					})
 
- 					this.collapse.names.forEach((item, index) => {
 
- 						if (item === this.nameSync) {
 
- 							this.collapse.names.splice(index, 1)
 
- 						}
 
- 					})
 
- 				}
 
- 			},
 
- 			onClick(isOpen, type) {
 
- 				if (this.disabled) return
 
- 				this.isOpen = isOpen
 
- 				if (this.isOpen && this.collapse) {
 
- 					this.collapse.setAccordion(this)
 
- 				}
 
- 				if (type !== 'init') {
 
- 					this.collapse.onChange(isOpen, this)
 
- 				}
 
- 			},
 
- 			getCollapseHeight(type, index = 0) {
 
- 				const views = uni.createSelectorQuery().in(this)
 
- 				views
 
- 					.select(`#${this.elId}`)
 
- 					.fields({
 
- 						size: true
 
- 					}, data => {
 
- 						// TODO 百度中可能获取不到节点信息 ,需要循环获取
 
- 						if (index >= 10) return
 
- 						if (!data) {
 
- 							index++
 
- 							this.getCollapseHeight(false, index)
 
- 							return
 
- 						}
 
- 						// #ifdef APP-NVUE
 
- 						this.height = data.height + 1
 
- 						// #endif
 
- 						// #ifndef APP-NVUE
 
- 						this.height = data.height
 
- 						// #endif
 
- 						this.isheight = true
 
- 						if (type) return
 
- 						this.onClick(this.isOpen, 'init')
 
- 					})
 
- 					.exec()
 
- 			},
 
- 			getNvueHwight(type) {
 
- 				const result = dom.getComponentRect(this.$refs['collapse--hook'], option => {
 
- 					if (option && option.result && option.size) {
 
- 						// #ifdef APP-NVUE
 
- 						this.height = option.size.height + 1
 
- 						// #endif
 
- 						// #ifndef APP-NVUE
 
- 						this.height = option.size.height
 
- 						// #endif
 
- 						this.isheight = true
 
- 						if (type) return
 
- 						this.onClick(this.open, 'init')
 
- 					}
 
- 				})
 
- 			},
 
- 			/**
 
- 			 * 获取父元素实例
 
- 			 */
 
- 			getCollapse(name = 'uniCollapse') {
 
- 				let parent = this.$parent;
 
- 				let parentName = parent.$options.name;
 
- 				while (parentName !== name) {
 
- 					parent = parent.$parent;
 
- 					if (!parent) return false;
 
- 					parentName = parent.$options.name;
 
- 				}
 
- 				return parent;
 
- 			}
 
- 		}
 
- 	}
 
- </script>
 
- <style lang="scss">
 
- 	.uni-collapse-item {
 
- 		/* #ifndef APP-NVUE */
 
- 		box-sizing: border-box;
 
- 		/* #endif */
 
- 		&__title {
 
- 			/* #ifndef APP-NVUE */
 
- 			display: flex;
 
- 			width: 100%;
 
- 			box-sizing: border-box;
 
- 			/* #endif */
 
- 			flex-direction: row;
 
- 			align-items: center;
 
- 			transition: border-bottom-color .3s;
 
- 			// transition-property: border-bottom-color;
 
- 			// transition-duration: 5s;
 
- 			&-wrap {
 
- 				width: 100%;
 
- 				flex: 1;
 
- 			}
 
- 			&-box {
 
- 				padding: 0 15px;
 
- 				/* #ifndef APP-NVUE */
 
- 				display: flex;
 
- 				width: 100%;
 
- 				box-sizing: border-box;
 
- 				/* #endif */
 
- 				flex-direction: row;
 
- 				justify-content: space-between;
 
- 				align-items: center;
 
- 				height: 48px;
 
- 				line-height: 48px;
 
- 				background-color: #fff;
 
- 				color: #303133;
 
- 				font-size: 13px;
 
- 				font-weight: 500;
 
- 				/* #ifdef H5 */
 
- 				cursor: pointer;
 
- 				outline: none;
 
- 				/* #endif */
 
- 				&.is-disabled {
 
- 					.uni-collapse-item__title-text {
 
- 						color: #999;
 
- 					}
 
- 				}
 
- 			}
 
- 			&.uni-collapse-item-border {
 
- 				border-bottom: 1px solid #ebeef5;
 
- 			}
 
- 			&.is-open {
 
- 				border-bottom-color: transparent;
 
- 			}
 
- 			&-img {
 
- 				height: 22px;
 
- 				width: 22px;
 
- 				margin-right: 10px;
 
- 			}
 
- 			&-text {
 
- 				flex: 1;
 
- 				font-size: 14px;
 
- 				/* #ifndef APP-NVUE */
 
- 				white-space: nowrap;
 
- 				color: inherit;
 
- 				/* #endif */
 
- 				/* #ifdef APP-NVUE */
 
- 				lines: 1;
 
- 				/* #endif */
 
- 				overflow: hidden;
 
- 				text-overflow: ellipsis;
 
- 			}
 
- 			&-arrow {
 
- 				/* #ifndef APP-NVUE */
 
- 				display: flex;
 
- 				box-sizing: border-box;
 
- 				/* #endif */
 
- 				align-items: center;
 
- 				justify-content: center;
 
- 				width: 20px;
 
- 				height: 20px;
 
- 				margin-right: 10px;
 
- 				transform: rotate(0deg);
 
- 				&-active {
 
- 					transform: rotate(-180deg);
 
- 				}
 
- 			}
 
- 		}
 
- 		&__wrap {
 
- 			/* #ifndef APP-NVUE */
 
- 			will-change: height;
 
- 			box-sizing: border-box;
 
- 			/* #endif */
 
- 			background-color: #fff;
 
- 			overflow: hidden;
 
- 			position: relative;
 
- 			height: 0;
 
- 			&.is--transition {
 
- 				// transition: all 0.3s;
 
- 				transition-property: height, border-bottom-width;
 
- 				transition-duration: 0.3s;
 
- 				/* #ifndef APP-NVUE */
 
- 				will-change: height;
 
- 				/* #endif */
 
- 			}
 
- 			&-content {
 
- 				position: absolute;
 
- 				font-size: 13px;
 
- 				color: #303133;
 
- 				// transition: height 0.3s;
 
- 				border-bottom-color: transparent;
 
- 				border-bottom-style: solid;
 
- 				border-bottom-width: 0;
 
- 				&.uni-collapse-item--border {
 
- 					border-bottom-width: 1px;
 
- 					border-bottom-color: red;
 
- 					border-bottom-color: #ebeef5;
 
- 				}
 
- 				&.open {
 
- 					position: relative;
 
- 				}
 
- 			}
 
- 		}
 
- 		&--animation {
 
- 			transition-property: transform;
 
- 			transition-duration: 0.3s;
 
- 			transition-timing-function: ease;
 
- 		}
 
- 	}
 
- </style>
 
 
  |