yunshangxie/tuniao-ui/components/tn-read-more/tn-read-more.vue

223 lines
5.3 KiB
Vue
Raw Permalink Normal View History

2023-12-25 17:56:30 +08:00
<template>
<view>
<view class="tn-read-more-class tn-read-more">
<!-- 内容 -->
<view
:id="elId"
class="tn-read-more__content"
:style="[contentStyle]"
>
<slot></slot>
</view>
<!-- 展开收起按钮 -->
<view
v-if="isLongContent"
class="tn-read-more__show-more__wrap"
:class="{'tn-read-more__show-more': showMore}"
:style="[innerShadowStyle]"
@tap="toggleReadMore">
<text class="tn-read-more__show-more--text" :style="[fontStyle]">{{ showMore ? closeText : openText }}</text>
<view class="tn-read-more__show-more--icon">
<view :class="[tipIconClass]" :style="[fontStyle]"></view>
</view>
</view>
</view>
</view>
</template>
<script>
import componentsColorMixin from '../../libs/mixin/components_color.js'
export default {
name: 'tn-read-more',
mixins: [componentsColorMixin],
props: {
// 默认占位高度
showHeight: {
type: Number,
default: 400
},
// 显示收起按钮
closeBtn: {
type: Boolean,
default: false
},
// 展开提示文字
openText: {
type: String,
default: '展开阅读全文'
},
// 收起提示文字
closeText: {
type: String,
default: '收起'
},
// 展开提示图标
openIcon: {
type: String,
default: 'down'
},
// 收起提示图标
closeIcon: {
type: String,
default: 'up'
},
// 阴影样式
shadowStyle: {
type: Object,
default () {
return {
backgroundImage: "linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)",
paddingTop: "300rpx",
marginTop: "-300rpx"
}
}
},
// 组件标识
index: {
type: [Number, String],
default: ''
}
},
computed: {
paramsChange() {
return `${this.open}-${this.showHeight}`
},
contentStyle() {
let style = {}
if (this.isLongContent && !this.showMore) {
style.height = `${this.showHeight}rpx`
} else {
if (!this.initHeight) {
style.height = 'auto'
} else {
style.height = `${this.contentHeight}px`
}
}
return style
},
innerShadowStyle() {
let style = {}
// 折叠时才需要阴影样式
if (!this.showMore) {
style = Object.assign(style, this.shadowStyle)
}
return style
},
fontStyle() {
let style = {}
style.color = this.fontColorStyle ? this.fontColorStyle : '#01BEFF'
style.fontSize = this.fontSizeStyle ? this.fontSizeStyle : '28rpx'
return style
},
tipIconClass() {
if (this.showMore) {
if (this.closeIcon) {
return `tn-icon-${this.closeIcon}`
}
} else {
if (this.openIcon) {
return `tn-icon-${this.openIcon}`
}
}
}
},
data() {
return {
elId: this.$tn.uuid(),
// 标记是否已经初始化高度完成
initHeight: false,
// 是否需要隐藏一部分内容
isLongContent: false,
// 当前展开的打开、关闭状态
showMore: false,
// 内容的高度
contentHeight: 0
}
},
watch: {
paramsChange(value) {
this.initHeight = false
this.isLongContent = false
this.showMore = true
this.$nextTick(() => {
this.init()
})
}
},
mounted() {
this.$nextTick(() => {
this.init()
})
},
methods: {
// 初始化组件
init() {
// 判断高度,如果真实内容的高度大于占位高度,则显示展开与收起的控制按钮
this._tGetRect('#' + this.elId).then(res => {
this.contentHeight = res.height
this.initHeight = true
if (res.height > uni.upx2px(this.showHeight)) {
this.isLongContent = true
this.showMore = false
}
})
},
// 展开或者收起内容
toggleReadMore() {
this.showMore = !this.showMore
// 是否显示收起按钮
if (!this.closeBtn) this.isLongContent = false
this.$emit(this.showMore ? 'open' : 'closed', this.index)
}
}
}
</script>
<style lang="scss" scoped>
.tn-read-more {
&__content {
font-size: 28rpx;
color: $tn-font-color;
line-height: 1.8;
text-align: left;
overflow: hidden;
transition: all 0.3s linear;
}
&__show-more {
padding-top: 0;
background: none;
margin-top: 20rpx;
&__wrap {
position: relative;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding-bottom: 26rpx;
}
&--text {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
line-height: 1;
}
&--icon {
margin-left: 14rpx;
}
}
}
</style>