项目提了新需求,要求把拿到的对话数据,逐条显示在界面上,并且第一次展示的时候要有打字机效果。刚开始的实现:把打字机效果抽离成一个组件,接受父组件传递的要显示的数据,在组件内利用定时器和字符串截取方法,实现打字机效果。代码如下:
<template>
<div class="box">
<img :src="avatarUrl(item.name)" alt="">
<div class="content">
<span class="name">{{item.name}}</span>
<span class="time">{{item.time}}</span>
</div>
<p class="detail">{{str1}}</p>
</div>
</template>
<script>
export default {
props: ['item'],
data() {
return{
str1: '',
timer: 0,
i: 1,
}
},
methods:{
typeing() {
if (this.i <= this.item.text.length) {
this.str1 = this.item.text.slice(0, this.i++)
}else {
clearInterval(this.timer);
}
},
avatarUrl(name) {
......
},
},
created(){
this.timer = setInterval(() => {this.typeing()}, 60)
},
}
</script>
实现是实现了,但是性能不太好,当数据生成了成百上千条的时候,页面就会卡顿,更新数据也延缓,当滚动数据的时候甚至产生白屏情况。于是就想用插件实现,我用了 vue-typed-js ,然而还是没有解决这个问题。究其原因,插件和第一次用组件实现,两种造成的内存消耗是一样的,当对话数据不断增加,它们都会创建相同多的组件(事实上这个组件创建是没有必要的),除了 vue-typed-js 这个插件,我还尝试了其他能实现打字机效果的组件,其中要么不能达到的我的诉求,要么依然解决不了问题,感觉这些插件的实现原理都是差不多,都是会用组件包裹你需要打字机效果的数据。
最后,还是化繁为简,简简单单的用自定义指令实现了,它就不会再生成无穷无尽的没必要的组件了。(感觉真的是饶了一个大圈,又回到了起点,最最初版本就是想用指令来实现,毕竟诉求没有那么复杂)
代码:
<template>
<div>
<span v-type>{{ str }}</span>
</div>
</template>
<script>
export default {
data() {
return {
str: '今天很开心'
}
},
directives: {
type: {
inserted(el) {
const msg1 = el.innerText;
let i = 1;
let msg = '';
el.innerText = '';
let timer = setInterval(() => {
if (i <= msg1.length) {
msg = msg1.slice(0, i++)
el.innerText = msg
} else {
clearInterval(timer)
}
}, 40)
}
}
}
}
</script>