组件
创建多行文本展开折叠组件
本文档使用 MrDoc 发布
-
+
首页
创建多行文本展开折叠组件
先看下效果  创建一个`vue`文件 编写基本结构 ~~~vue <script setup name="collapseToExpand" lang="ts"> import { ref, onMounted, onUnmounted } from "vue"; const props = defineProps({ /* text: { type: String, default: '' }, */ row: { type: Number, default: 2, }, }); let text = ref( "生活有五颜六色,但并不是十全十美,所以我们需要从生活中汲取一些人生营养,于是乎阅读就成为了一部分人的生活常态。阅读这个东西对于人生来说似乎是一件必不可少的事,任由书上的情节来摆布我们的喜怒哀惧,或许一个不经意间的话语就成为我们刻骨铭心的深刻阅读记忆。无知的我们总被生活所敷衍,就像小时候的我们只爱吃甜的一样,但一个道理永远说服不了所有人,甜点也并不是最好吃的。在深入之后才明白阅读并不是容颜的羞花闭月、举止的温文尔雅、也不是财富的腰缠万贯、更不是权力的叱咤风云,而是一棵向阳性的草,在整个季节里开满了盛状的花。", ); // 组件ref const refMoreText = ref(); // 内容ref const refContent = ref(); // 标识ref const refTrigger = ref(); // 是否展开 const isExceed = ref(false); // 是否显示更多 const moreVisible = ref(false); </script> <template> <div ref="refMoreText" class="more-text"> <div ref="refContent" class="content">{{ text }}</div> <div ref="refTrigger" class="trigger text-primary bg" @click="handleTrigger" v-if="isExceed" > <span>{{ moreVisible ? "收起" : "... 展开更多" }}</span> </div> </div> </template> <style lang="scss" scoped></style> ~~~ 接下来获取一开始显示的高度(正常显示的高度)、文本的行高 ~~~js onMounted(() => { // 获取一开始的高度 fullHeight = refContent.value.clientHeight; // 获取行高 lineHeight = Number(window.getComputedStyle(refMoreText.value).lineHeight.slice(0, -2)); // 折叠的高度 textHeight = lineHeight * props.row; }); ~~~ > + `window.getComputedStyle()`方法获取指定DOM元素的当前的样式,这意味着它返回的是浏览器实际应用到元素上的CSS样式,包括所有CSS规则(内联样式、外部样式表和浏览器默认样式)的最终结果。 一开始应该是折叠的高度,开始写css样式 ~~~css .more-text { position: relative; // 超出隐藏 overflow: hidden; // 高度 height: var(--height); // 换行类型 word-break: break-all; // 空白处理 white-space: pre-wrap; // 添加动画 改变的是高度 transition: height 0.3s; // 内容设为absolute,避免高度被父元素影响 .content { position: absolute; } // 设置标记的样式 .trigger { position: absolute; right: 0; bottom: 0; display: flex; align-items: center; justify-content: flex-end; // 设置高度和内容一样 height: var(--lineHeight); line-height: var(--lineHeight); padding-left: 120px; cursor: pointer; } .bg { background: linear-gradient( to right, rgb(255, 255, 255, 0) 0, rgb(255, 255, 255, 1) 60%, #fff 100% ); } } ~~~ > - **`word-break: break-all;`** > > - `word-break: break-all;` 属性用于规定如何在单词内断行。当这个属性被应用时,如果文本内容到达容器边界而无法在当前行继续显示时,浏览器将在单词内的任意字符处断开,以适应容器宽度,哪怕这意味着单词会被拆分。这在处理包含长英文单词或URL等连续无空格文本时特别有用,可以避免内容溢出容器。 > > - **`white-space: pre-wrap;`** > > - ``` > white-space: pre-wrap; > ``` > > 控制元素中的空白符和换行符如何处理。这个值结合了两方面特性: > > - **`pre`**: 保留空白符序列,比如空格和制表符,文本中的每一行都会按照源代码中的排版来显示,不会被折叠。 > - **`wrap`**: 允许文本自动换行。即使文本中包含换行符(\n),也会在必要时在这些换行符之外的地方换行,以避免内容溢出容器。 接下来需要处理css中的高度 ~~~js // 设置css中的高度,需要传递一个参数,表示展开还是折叠 // true表示展开 const setCssVar = visible => { if (visible) { refMoreText.value.style.setProperty("--height", fullHeight + lineHeight + "px"); refMoreText.value.style.setProperty("--row", ""); } else { refMoreText.value.style.setProperty("--row", props.row); refMoreText.value.style.setProperty("--height", textHeight + "px"); } }; ~~~ > - **`refMoreText.value`**: 在Vue中,`ref`是一个用于获取DOM元素或组件实例的引用。`.value`是在Vue的Composition API中访问ref引用的实际DOM元素或组件实例时所必需的。因此,`refMoreText.value`就是我们想要操作的DOM元素。 > - **`.style`**: 这是JavaScript DOM元素的一个属性,用于访问和修改元素的内联样式。 > - **`.setProperty`**: 这是`style`对象的一个方法,用于设置CSS样式,特别是对于CSS变量(也称为自定义属性)非常有用。它接受两个参数:属性名(在这里是CSS变量名)和属性值。 > - **`"--height"`**: 这是CSS变量的名称。CSS变量允许你在CSS中定义可重用的值,就像这里的`--height`,可以在多个地方引用并更新。 > - **`fullHeight + lineHeight + "px"`**: 这是设置给`--height`变量的新值。这里,`fullHeight`和`lineHeight`应该是之前已经定义好的JavaScript变量,分别代表某个元素的全高和单行高度(单位可能是像素,但未明确指出)。这两个数值相加后,再加上字符串`"px"`,以确保设置的高度值是以像素为单位的,这是CSS中常用的长度单位。 接下来判断是否显示标志 ~~~js onMounted(() => { // 获取一开始的高度 fullHeight = refContent.value.clientHeight; // 获取行高 lineHeight = Number(window.getComputedStyle(refMoreText.value).lineHeight.slice(0, -2)); // 折叠的高度 textHeight = lineHeight * props.row; // 设置标识的行高 if (refTrigger.value) { refTrigger.value.style["lineHeight"] = lineHeight + "px"; } // 判断是都显示 标志 isExceed.value = textHeight < fullHeight; // 设置css中的高度 setCssVar(); }); ~~~ 添加切换事件 ~~~js // 点击展开和隐藏 const handleTrigger = () => { // 修改是否显示表示 moreVisible.value = !moreVisible.value; // 如果是展开就隐藏背景颜色,否则添加背景颜色 if (moreVisible.value) { refTrigger.value.classList.remove("bg"); } else { refTrigger.value.classList.add("bg"); } // 重新设置css中高度变量 setCssVar(moreVisible.value); }; ~~~ 经过以上基本上就完成了 当尺寸变化之后,容器不能变化,需要修改一下   在发生变化之后需要获取一开始的高度、是否显示标识、如何设置css中的高度 ~~~js let resizeObserver: ResizeObserver | null = null; onMounted(() => { // 获取一开始的高度 fullHeight = refContent.value.clientHeight; // 获取行高 lineHeight = Number(window.getComputedStyle(refMoreText.value).lineHeight.slice(0, -2)); // 折叠的高度 textHeight = lineHeight * props.row; // 设置标识的行高 if (refTrigger.value) { refTrigger.value.style["lineHeight"] = lineHeight + "px"; } // 判断是都显示 标志 // isExceed.value = textHeight < fullHeight; // 设置css中的高度 // setCssVar(); resizeObserver = new ResizeObserver(entries => { for (let entry of entries) { fullHeight = entry.contentRect.height; isExceed.value = textHeight < fullHeight; setCssVar(moreVisible.value); } }); resizeObserver.observe(refContent.value); }); ~~~ > ResizeObserver 是一个现代 JavaScript API,用于监听 DOM 元素的尺寸变化。在过去,监听元素尺寸变化通常依赖于 window 的 resize 事件,但这只能捕捉到窗口尺寸变化。ResizeObserver 为监控特定元素的尺寸变化提供了精确的方法,而不依赖于窗口尺寸。 > > 回调函数的参数 entries 是一个包含 ResizeObserverEntry 对象的数组。每个ResizeObserverEntry 对象代表一个被观察的元素,并提供以下信息: > > target: 被观察的元素。 > contentRect: 一个 DOMRectReadOnly 对象,包含元素的尺寸和位置信息。可以使用 contentRect.width 和 contentRect.height 获取元素的新尺寸。 > borderBoxSize: (可选)如果浏览器支持,这个属性会包含元素的边框尺寸。 经过这样处理就不会在出现上面的问题了 最后在组件销毁的时候应该停止监听 将代码中的`text`删除,打开`props中的text`这样文本就是传递的了,一个折叠展开组件就做好了
admin
2024年7月2日 11:54
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码