ReadMore 查看更多
长内容(公告、评论、文章详情)预先收起一部分的展开/收起容器:收起态内容裁到指定高度、底部盖渐变遮罩;展开/收起由同一按钮行完成。内容自然高度不足时退化为普通内容块(撤除收起高度,不渲染遮罩与按钮)。
平台兼容性
| App | Web | 微信小程序 |
|---|---|---|
| ✓ | ✓ | ✓ |
展开高度切换带过渡动画;内容自然高度在挂载时自动测量,异步内容变化后自动重测。
基础用法
html
<n-read-more :height="88">
<text>很长的内容……</text>
</n-read-more>
受控与拦截(付费解锁模式)
html
<n-read-more v-model="expanded" disabled index="article-1" expand-text="付费解锁" @click="onPayClick">
<text>付费专栏内容……</text>
</n-read-more>
js
const expanded = ref(false);
// disabled 态 click 仍触发并返回 index;toggle 返回点击前状态和 index;
// 在回调里完成确认后置 expanded = true 放行,watch 同步展开
function onPayClick(index: string) {
uni.showModal({
title: "提示",
content: `解锁 ${index} 的全部内容?`,
success: (res) => {
if (res.confirm) expanded.value = true;
}
});
}
自定义收展按钮
html
<n-read-more>
<text>内容……</text>
<template #toggle="{ isExpanded }">
<text>{{ isExpanded ? "收起文章" : "展开阅读全文" }}</text>
</template>
</n-read-more>
#toggle接管展开/收起按钮行;渐变遮罩只负责内容渐隐,不承载按钮。
动态内容与程序化收展
插槽内列表异步刷新、图片撑高后高度自动重测;也可手动触发,toggle() 等价点击收展按钮行(事件序列一致):
js
const readMore = ref<NReadMoreComponentPublicInstance | null>(null);
if (readMore.value != null) readMore.value.remeasure();
readMore.value?.toggle();
API
Props
| 属性 | 类型 | 说明 |
|---|---|---|
| modelValue | boolean | 展开状态(受控),默认 false |
| height | number | 收起态内容可见高度(px),默认 88 |
| content | string | 默认插槽缺省文本,默认 "" |
| expandText | string | 展开按钮文字,空 = 语言包文案,默认 "" |
| collapseText | string | 收起按钮文字,空 = 语言包文案,默认 "" |
| expandIcon | string | 收起态展开按钮图标名,默认 "down" |
| collapseIcon | string | 展开态收起按钮图标名,默认 "up" |
| showToggle | boolean | 是否显示收展按钮行;关闭后只能由外部改 modelValue 切换,默认 true |
| showMask | boolean | 是否显示收起态渐变遮罩;不影响收展按钮交互,默认 true |
| textSize | number | 切换按钮文字字号(px),默认 14 |
| color | string | 切换按钮与图标颜色,空 = 主题品牌色,默认 "" |
| textColor | string | 切换按钮文字颜色,空时沿用 color,再回落主题品牌色,默认 "" |
| iconSize | number | 切换按钮图标字号(px),默认 16 |
| disabled | boolean | 禁用(拦截收展,click 与 toggle 仍触发),默认 false |
| index | string | 组件索引标识,随 click、change 和 toggle 返回,默认 "" |
| contentStyle | string | 缺省文本行内样式,默认 "" |
| maskStyle | string | 遮罩行内样式(渐变色之外的部分),默认 "" |
| customClass | string | 根节点额外 class,默认 "" |
| customStyle | string | 根节点行内样式,默认 "" |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
| update:modelValue | isExpanded: boolean | 展开状态变化;配合 :model-value 手动双向绑定 |
| change | isExpanded: boolean, index: string | 展开状态变化;禁用态不触发 |
| click | index: string, isExpanded: boolean | 点击收展按钮行时触发,禁用态仍触发 |
| toggle | isExpanded: boolean, index: string | 禁用态点击收展入口时触发 |
Slots
| 插槽 | 参数 | 说明 |
|---|---|---|
| default | — | 收展的内容 |
| toggle | isExpanded: boolean, value: boolean, index: string | 自定义收展按钮行(整行接管);value 与 isExpanded 表示相同状态 |
Expose
| 方法 | 说明 |
|---|---|
| remeasure(): void | 强制重测内容自然高度(内容异步刷新后;一般无需手动调用) |
| toggle(): void | 程序化收展,等价点击收展按钮行(事件序列一致;禁用态只发 click 与 toggle) |
实现说明
与参考实现(同类展开/收起组件)的机制对照:
| 机制 | 参考做法 | 本库做法 |
|---|---|---|
| 收起高度 | 固定值(约 40px)或字符串高度 | 数字 px,默认 88(约 4 行正文);自然高不超该值时整体退化为普通内容块 |
| 展开入口 | 按钮行 | 按钮行在展开与收起态保持一致;showMask 只控制视觉遮罩 |
| 高度动画 | CSS height 过渡(iOS 端个别版本关闭) | 同款 height 过渡;首测定型前不播动画,挂载即展开不从 0 播放 |
| 内容高度测量 | 挂载 + 内容变化重测 | 同款;50ms 合并高频更新,另暴露 remeasure() 手动触发 |
| 测量不可得时 | 无降级 | 显式降级:有限重试耗尽后进入降级模式 —— 收起 max-height 裁切、展开自适应、无过渡,收展入口始终提供(内容不足判定失效,入口不消失);后续测量成功自动退出降级(部分小程序环境组件作用域查询不可用,降级保证功能完整) |
| 遮罩与主题 | 56px 遮罩,页面底色从遮罩底部向上渐隐,深浅主题分别使用对应底色 | 同为 56px;浅色与深色分别使用静态 RGBA 渐变(渐变上 35% 全透明、渐隐集中到贴裁切线段,避免整行雾蒙);主题类并入装配位键,深浅翻转整根重建——background-image 换类不重绘是已知平台行为,残留会在浅色卡上呈灰影带 |
| 遮罩定位 | absolute + bottom(锚定折叠区底边,随裁切线移动) | absolute + bottom(锚定折叠区底边,随裁切线移动) |
| 遮罩显隐 | 收起态显示,展开态隐藏,并过渡透明度 | 遮罩常驻渲染(节点不销毁),行内 opacity 200ms 渐隐;显隐走行内样式是因为微信端类切换的过渡不生效(瞬跳),行内变更与折叠区高度过渡同机制 |
| 切换事件 | click(index) / toggle(禁用态) | click 返回实例 index 与点击前状态,toggle 为禁用态拦截事件(付费解锁等场景),change 返回状态与 index |
| 程序化收展 | toggle()(另有 getContentHeight / init 等辅助) | toggle() 等价点击收展按钮行;重测走 remeasure(),事件序列与手动点击完全一致 |
| 短内容表现 | 入口不渲染;折叠区仍钉收起高(留底部空白) | 入口不渲染且折叠区撤除高度约束(保持原样);两处装配等首测定型后再翻转,长内容不闪整屏展开、短内容不闪入口 |
| 遮罩定制 | maskStyle 可整体覆盖渐变 | 渐变随深浅主题自动适配(换主题整根重建遮罩),maskStyle 只开放渐变之外部分;App 端行内渐变改值存在不重绘的已知平台问题,不开放以避免配置踩坑 |
| 文案 | 默认中文 | 语言包(expand / collapse 两键),切换语言即时刷新 |