158 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
		
		
			
		
	
	
			158 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Vue
		
	
	
	
|  | <template> | |||
|  | 	<view class="u-read-more"> | |||
|  | 		<view | |||
|  | 		    class="u-read-more__content" | |||
|  | 		    :style="{ | |||
|  | 				height: isLongContent && status === 'close' ? $u.addUnit(showHeight) : $u.addUnit(contentHeight), | |||
|  | 				textIndent: textIndent | |||
|  | 			}" | |||
|  | 		> | |||
|  | 			<view | |||
|  | 			    class="u-read-more__content__inner" | |||
|  | 			    ref="u-read-more__content__inner" | |||
|  | 			    :class="[elId]" | |||
|  | 			> | |||
|  | 				<slot></slot> | |||
|  | 			</view> | |||
|  | 		</view> | |||
|  | 		<view | |||
|  | 		    class="u-read-more__toggle" | |||
|  | 		    :style="[innerShadowStyle]" | |||
|  | 		    v-if="isLongContent" | |||
|  | 		> | |||
|  | 			<slot name="toggle"> | |||
|  | 				<view | |||
|  | 				    class="u-read-more__toggle__text" | |||
|  | 				    @tap="toggleReadMore" | |||
|  | 				> | |||
|  | 					<u--text | |||
|  | 					    :text="status === 'close' ? closeText : openText" | |||
|  | 					    :color="color" | |||
|  | 					    :size="fontSize" | |||
|  | 					    :lineHeight="fontSize" | |||
|  | 					    margin="0 5px 0 0" | |||
|  | 					></u--text> | |||
|  | 					<view class="u-read-more__toggle__icon"> | |||
|  | 						<u-icon | |||
|  | 						    :color="color" | |||
|  | 						    :size="fontSize + 2" | |||
|  | 						    :name="status === 'close' ? 'arrow-down' : 'arrow-up'" | |||
|  | 						></u-icon> | |||
|  | 					</view> | |||
|  | 				</view> | |||
|  | 			</slot> | |||
|  | 		</view> | |||
|  | 	</view> | |||
|  | </template> | |||
|  | 
 | |||
|  | <script> | |||
|  | 	// #ifdef APP-NVUE
 | |||
|  | 	const dom = uni.requireNativePlugin('dom') | |||
|  | 	// #endif
 | |||
|  | 	import props from './props.js'; | |||
|  | 	/** | |||
|  | 	 * readMore 阅读更多 | |||
|  | 	 * @description 该组件一般用于内容较长,预先收起一部分,点击展开全部内容的场景。 | |||
|  | 	 * @tutorial https://www.uviewui.com/components/readMore.html
 | |||
|  | 	 * @property {String | Number}	showHeight	内容超出此高度才会显示展开全文按钮,单位px(默认 400 ) | |||
|  | 	 * @property {Boolean}			toggle		展开后是否显示收起按钮(默认 false ) | |||
|  | 	 * @property {String}			closeText	关闭时的提示文字(默认 '展开阅读全文' ) | |||
|  | 	 * @property {String}			openText	展开时的提示文字(默认 '收起' ) | |||
|  | 	 * @property {String}			color		提示文字的颜色(默认 '#2979ff' ) | |||
|  | 	 * @property {String | Number}	fontSize	提示文字的大小,单位px (默认 14 ) | |||
|  | 	 * @property {Object}			shadowStyle	显示阴影的样式 | |||
|  | 	 * @property {String}			textIndent	段落首行缩进的字符个数 (默认 '2em' ) | |||
|  | 	 * @property {String | Number}	name		用于在 open 和 close 事件中当作回调参数返回 | |||
|  | 	 * @event {Function} open 内容被展开时触发 | |||
|  | 	 * @event {Function} close 内容被收起时触发 | |||
|  | 	 * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more> | |||
|  | 	 */ | |||
|  | 	export default { | |||
|  | 		name: 'u-read-more', | |||
|  | 		mixins: [uni.$u.mpMixin, uni.$u.mixin, props], | |||
|  | 		data() { | |||
|  | 			return { | |||
|  | 				isLongContent: false, // 是否需要隐藏一部分内容
 | |||
|  | 				status: 'close', // 当前隐藏与显示的状态,close-收起状态,open-展开状态
 | |||
|  | 				elId: uni.$u.guid(), // 生成唯一class
 | |||
|  | 				contentHeight: 100, // 内容高度
 | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		computed: { | |||
|  | 			// 展开后无需阴影,收起时才需要阴影样式
 | |||
|  | 			innerShadowStyle() { | |||
|  | 				if (this.status === 'open') return {} | |||
|  | 				else return this.shadowStyle | |||
|  | 			} | |||
|  | 		}, | |||
|  | 		mounted() { | |||
|  | 			this.init() | |||
|  | 		}, | |||
|  | 		methods: { | |||
|  | 			async init() { | |||
|  | 				this.getContentHeight().then(height => { | |||
|  | 					this.contentHeight = height | |||
|  | 					// 判断高度,如果真实内容高度大于占位高度,则显示收起与展开的控制按钮
 | |||
|  | 					if (height > uni.$u.getPx(this.showHeight)) { | |||
|  | 						this.isLongContent = true | |||
|  | 						this.status = 'close' | |||
|  | 					} | |||
|  | 				}) | |||
|  | 			}, | |||
|  | 			// 获取内容的高度
 | |||
|  | 			async getContentHeight() { | |||
|  | 				// 延时一定时间再获取节点
 | |||
|  | 				await uni.$u.sleep(30) | |||
|  | 				return new Promise(resolve => { | |||
|  | 					// #ifndef APP-NVUE
 | |||
|  | 					this.$uGetRect('.' + this.elId).then(res => { | |||
|  | 						resolve(res.height) | |||
|  | 					}) | |||
|  | 					// #endif
 | |||
|  | 
 | |||
|  | 					// #ifdef APP-NVUE
 | |||
|  | 					const ref = this.$refs['u-read-more__content__inner'] | |||
|  | 					dom.getComponentRect(ref, (res) => { | |||
|  | 						resolve(res.size.height) | |||
|  | 					}) | |||
|  | 					// #endif
 | |||
|  | 				}) | |||
|  | 			}, | |||
|  | 			// 展开或者收起
 | |||
|  | 			toggleReadMore() { | |||
|  | 				this.status = this.status === 'close' ? 'open' : 'close' | |||
|  | 				// 如果toggle为false,隐藏"收起"部分的内容
 | |||
|  | 				if (this.toggle == false) this.isLongContent = false | |||
|  | 				// 发出打开或者收齐的事件
 | |||
|  | 				this.$emit(this.status, this.name) | |||
|  | 			} | |||
|  | 		} | |||
|  | 	} | |||
|  | </script> | |||
|  | 
 | |||
|  | <style lang="scss" scoped> | |||
|  | @import "../../libs/css/components.scss"; | |||
|  | 
 | |||
|  | .u-read-more { | |||
|  | 
 | |||
|  | 	&__content { | |||
|  | 		overflow: hidden; | |||
|  | 		color: $u-content-color; | |||
|  | 		font-size: 15px; | |||
|  | 		text-align: left; | |||
|  | 	} | |||
|  | 
 | |||
|  | 	&__toggle { | |||
|  | 		@include flex; | |||
|  | 		justify-content: center; | |||
|  | 
 | |||
|  | 		&__text { | |||
|  | 			@include flex; | |||
|  | 			align-items: center; | |||
|  | 			justify-content: center; | |||
|  | 			margin-top: 5px; | |||
|  | 		} | |||
|  | 	} | |||
|  | } | |||
|  | </style> |