第一个需求
1、内容
将会议中收集到的与会者发言识别成的文字,实时的按照一定格式显示在列表中,生成当前会议记录,并支持 txt 导出到本地。
2、要求
- 每行文字以打字机的形式显示
- 列表底部一直保持最新的聊天内容
- 可以滑动滚动条查看历史记录,当有新的内容时,展示“查看最新消息”按钮,点击后可以直接刷到列表底部
- 可以导出列表中所有的文字记录到本地
- 点击相关显示按钮,可以切换列表的大小,且在切换后,最底部能保持最新消息显示
3、难点
- 当列表产生滚动条,由于最新的文字内容有一个打字机效果,在没有打完所有文字前,该段文字没有足够的空间来撑起列表,这会导致部分文字会被遮挡,直到下一段文字开始打印显示。尝试过动态设置列表高度,需要提前计算好这段文字可能会占据的高度,但是又因为很难估算好这个“动态高度”(一段文字中可能有汉字、英文、字母、符号,每一种占据的空间不同,比较有难度),为了稳妥不出bug,放弃了。
解决方法:找“替身”,当真正的内容完整显示前先有一个替身占空间,内容准备好了,再把替身隐藏。
<-- v-type 实现打字机效果 !-->
<p id="myId" v-type>文本</p>
<p style="display:block;color:transparent">相同文本</p>
js:
// 在渲染元素前执行
let subtitleText = this.$el.querySelectorAll('#myId');// element数组
for (let i = 0; i < subtitleText.length; i++) {
let lastText = subtitleText[subtitleText.length - 1];
lastText.nextElementSibling.style.display = 'none';// 获取到替身标签元素
}
- 切换列表显示时,偶现无法显示最新内容到最底部。
解决方法:利用vue中的this.$nextTick
1.(官方)nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后立即使用 $nextTick,则可以在回调中获取更新后的 DOM
2.(通俗理解)nextTick方法相当于当页面渲染结束的使用再调用nextTick方法,nextTick方法能获取页面最新的dom元素
(ps: 有点像插队,着急更新这个东西,所以排在了下一次更新)
- 当数据累计到成千上万条时,列表会出现白屏效果。
解决方法:一开始用了插件来实现打字机效果,但是数据一旦过多,整个页面要加载的内容就无法流畅显示,占用内存、cpu极高。不使用三方插件,会增加运行压力,自己手写,利用vue的自定义指令,直接给每个内容添加指定。
directives: {
type: {
inserted(el) {
let i = 1, msg = '';
const elMsg = el.innerText;
el.innerText = '';
let timer = setInterval(() => {
if (i < elMsg.length) {
msg = elMsg.slice(0, i++);
el.innerText = msg;
} else {
clearInterval(timer);
}
}, 40)
}
}
}