Vue开发中一些可以提升性能的技巧(持续更新~)

3/17/2022, 11:23:02 PM

Vue开发中一些可以提升性能的技巧

总结一些在Vue项目开发过程中可以提升性能的写法

避免模板中包含复杂计算

<template>
	<div :style="{ width: width }">
        {{ members.map(m => m.name.slice(0, 1)).join('、')}}
    </div>
</template>
<script>
export default {
    data() {
        width: '100px',
        members: [{ name: '王小明' }, ...]
    }
}
</script>

div 依赖 width, members 两个响应式数据,任意一个数据变化都会触发组件的 render 和 patch,当 width 变化而 member 并没有发生变化时,依然会触发div中内容的计算,尤其是当width频繁变更时,会造成大量无意义的计算。这种计算牵扯到Vue2中的过滤器,Vue3中已移除,滥用过滤器很容易造成性能问题,所以应该避免封装计算过程复杂的过滤器,可以封装成通用的工具函数。

正确写法

<template>
	<div :style="{ width: width }">
        {{ brief }}
    </div>
</template>
<script>
export default {
    data() {
        width: '100px',
        members: [{ name: '王小明' }, ...]
    },
    computed: {
    	brief() { 
            return this.members.map(m => m.name.slice(0, 1)).join('、')
        }
    }
}
</script>

避免模板中重复的条件判断

<template>
    <div>
        <span
             :style="{
                 width: width,
                 color: member.length > 20 ? '#333' : '#666'
             }"
         >
        	{{ members.length }} 
   		</span>
        <span
             :class="[
                 member.length > 20  ? 'long' : 'short',
             ]">
            人
        </span>
    </div>
</template>
<script>
export default {
    data() {
        width: '100px',
        members: [{ name: '王小明' }, ...]
    }
}
</script>
<style>
    .long {
        font-weight: bold;
        color: #333;
    }
    .short {
        color: #999;
    }
</style>

模板中的重复的条件判断组件render时,一方面会导致很多无意义的判断,因为此时状态不可变,结果都是一致的。另一方面,条件依赖响应式数据,每次执行条件语句都会触发响应式数据的getter,执行依赖收集的相关逻辑

正确写法

<template>
    <div
         :class="[
         	member.length > 20 ? 'mode-long' : 'mode-short'
         ]"
     >
        <span class="count">{{ members.length }}</span>
        <span class="desc">人</span>
    </div>
</template>
<script>
export default {
    data() {
        width: '100px',
        members: [{ name: '王小明' }, ...]
    }
}
</script>
<style>
    .mode-long .count{
        color: #333;
    }
    .mode-short .count{
        color: #666;
    }
    .mode-long .desc {
        font-weight: bold;
        color: #333;
    }
    .mode-short .desc {
        color: #999;
    }
</style>

 

优先使用局部变量

<template>
	<div :style="{ width: width + 'px' }">
        {{ brief }}
    </div>
</template>
<script>
export default {
    data() {
        width: 100,
        members: [{ name: '王小明', allowShort: true }, ...]
    },
    computed: {
    	brief() { 
            return this.members.map(m => {
                return this.width < 200 && m.allowShort  ? m.name.slice(0, 1) : m.name
            }).join('、')
        }
    }
}
</script>

计算属性 brief 中,遍历 members 时,每次都会读取 data 中的 width,读取 width 是通过getter 获取,意味着每次都会触发 Vue 依赖收集相关的逻辑。

正确写法

<template>
	<div :style="{ width: width + 'px' }">
        {{ brief }}
    </div>
</template>
<script>
export default {
    data() {
        width: 100,
        members: [{ name: '王小明', allowShort: true }, ...]
    },
    computed: {
    	brief() { 
            const { width } =  this
            return this.members.map(m => {
                return width < 200 && m.allowShort  ? m.name.slice(0, 1) : m.name
            }).join('、')
        }
    }
}
</script>

合理拆分组件

这里不做代码演示了,组件拆分粒度需要根据业务情况灵活去做,这是一个权衡和取舍问题。组件的创建是有开销的,过度的拆分意味着更多的内存消耗,每个组件都是一个vue实例,都会从创建到销毁的过程。

但对于一些频繁变更状态的dom,拆分成小的组件是最佳选择。vue的更新是以组件为粒度,拆分独立的组件可以减少 diff 的过程,同时也能减少每次重新渲染的dom数量。