别离应用 Vue2 和 Vue3 创立一个组件,用一个对象数组作为组件的状态,以它的长度作为变量,考查 Vue2 和 Vue3 性能。

内存占用

数组长度Vue2Vue3
110.2 MB11.1 MB
10 00017.9 MB12.1 MB
100 00067.4 MB14.4 MB
1 000 000568 MB36.0 MB

初始化工夫

数组长度Vue2Vue3
17.2 ms7.8 ms
10 000110 ms6.9 ms
100 000803 ms6.7 ms
1 000 0002282 ms7.0 ms

测试代码

Vue2

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title>  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script></head><body>  <div id="app">{{ message }}</div>  <script>    const len = 1000000    const arr = new Array(len)    for (let i = 0; i < len; i++) {      arr[i] = { id: i, name: 'test' }    }        console.time('vue2:')    new Vue({      el: '#app',      data() {        return {          message: 'Hello Vue!',          arr        }      },      created() {        console.timeEnd('vue2:')      }    })  </script></body></html>

Vue3

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title>  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script></head><body>  <div id="app">{{ message }}</div>  <script>    const { createApp } = Vue    const len = 1000000    const arr = new Array(len)    for (let i = 0; i < len; i++) {      arr[i] = { id: i, name: 'test' }    }    console.time('vue3:')    createApp({      data() {        return {          message: 'Hello Vue!',          arr        }      },      created() {        console.timeEnd('vue3:')      }    }).mount('#app')  </script></body></html>

揣测

Vue2 应用Object.defineProperty()创立响应式属性,初始化时,除了遍历propsdata的每个属性,还会深度遍历子对象和子数组,从新定义它们的属性,并创立如ObserverDep实例,来察看属性变动,并且Object.defineProperty()重写的getset办法也是挂载在实例上。深度遍历加上创立这些实例的花销远大于原始对象,于是,能够看到 Vue2 无论是内存,还是初始化工夫随着数组长度减少猛涨,和 Vue3 产生了显著的差距。

当数组长度达到 100 万,Vue3 内存仅减少 25 MB,但 Vue2 内存暴增了 500+ MB,这些多进去的内存便是创立这些实例产生的额定开销。察看 Vue2 内存快照,发现 Vue2 创立了 100 万个Observer实例,相当于每个对象一个(另外三个Observer实例别离用于察看组件propsdata和数组自身)。数组中每个对象有两个属性,相应创立 200 万个Dep实例,100 万个Observer实例相应创立了100 万个Dep实例,共创立超过 300 万个Dep实例。

初始化工夫来看,Vue3 简直不受数组长度影响,而 Vue2 则随数组长度显著变长。这是因为 Vue3 应用Proxy类实现响应式,零碎会代理响应式对象的操作,如组件的propsdata,包含属性读取、赋值等,不会进行深度遍历。当读取响应式对象的属性时,才会创立Dep实例,如果读取的属性值也是对象时,再将这个对象响应式化,能够说 Vue3 是“懒”响应式。因而,初始化过程中 Vue3 运行工夫简直不变,如果不去操作这些属性,也简直不会有太多内存耗费。

列表渲染

别离应用 Vue2 和 Vue3 渲染 50000 个元素:

<ul>  <li v-for="item in arr">{{ item.id }}</li>  </ul>

能够看出,无论是内存占用或渲染实现工夫,Vue3 更占优势:

Vue2Vue3
内存124 MB53.1 MB
渲染实现工夫862ms284 ms