让前端飞Web前端之路工具集

Vue.js 应用性能优化的几条建议,最后一条你用过吗?

2020-04-15  本文已影响0人  1024译站

任何项目达到一定规模,往往会带来性能问题,Vue.js 也不例外。本文简单介绍几个小技巧,帮你在一定程度上对项目做性能上的优化。

图片懒加载

如果应用里需要展示大量图片,比如电商网站,通常的做法是懒加载图片。懒加载的基本原理是提前准备好图片 URL,当图片真正进入可视范围时才去加载。可以手动实现懒加载机制,不过更方便的是直接用现成的插件,比如 [vue-lazyload]
安装:

npm i vue-lazyload -S

入口文件里引入:

// in main.js

import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload)

new Vue({
  el: '#app',
  components: {
    App
  }
})

在模板里使用该插件提供的指令:

  <ul>
    <li v-for="img in list">
      <img v-lazy="img.src">
    </li>
  </ul>

按需使用第三方库

如今前端开发生态可谓是蓬勃发展,各种第三方库应有尽有。但是,项目引入过多的第三方库也会增大项目体积,带来性能问题。以 Bootstrap 为例,如果你只是用一下它的响应式机制,还不如自己手写相关的 CSS,也不会太复杂,完全没有必要引入整个库。再比如 Moment.js,如果只是简单做下日期时间格式化,自己写个工具函数也就几行代码,引入庞大的完整包也是大材小用。这些库为了普适性,提供了尽可能多的功能,但你的项目可能只用了极少部分。我们不鼓励重复造轮子,但是要按需引入。现在很多库都提供了 ES 模块化的方式,也可以做到这一点。

路由懒加载

路由懒加载也可以提高入口页面的加载速度,因为很多路由页面在多数情况下并没有被访问,在打包的时候放到单独的文件里可以减少入口页的体积。路由懒加载是通过 webpack 的动态 import来实现的。

// in router.js

import Home from '@/views/Home.vue'; // 静态 import
const About = () => import('@/views/About.vue'); // 动态 import

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

另外,这些懒加载的路由还可以分组,让相关性模块的多个路由页面打包到同一个 chunk,算是一种折中方案:既实现了按需加载,又不会过于碎片化。适用于子路由页面。

// in router.js

import Home from '@/views/Home.vue'; // traditonal imports
import User from '@/views/User.vue';

const About = () =>  import('@/views/About.vue'); // dynamic import

const router = new VueRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/user/:id', component: User, 
      children: [
        {
          path: '/settings',
          component: () => import(/* webpackChunkName: "user" */ '@/views/UserSettings')
        },
        {
          path: '/articles',
          component: () => import(/* webpackChunkName: "user" */ '@/views/UserArticles')
        }
      ]
    } 
  ]
})

这是通过 webpack 的注释语法/* webpackChunkName: "user" */实现的,webpackChunkName相同的路由会打进同一个 chunk文件。

不要滥用 Vuex store

Vuex 几乎是 Vue.js 项目全局状态管理的标配,以至于有些人一上来就把接口请求的数据全部往 store 里塞。时间一长,store 里的字段搞得一团糟。所谓全局状态,应该是在多个组件里都要用到的数据。经验值是少于三个组件的话,就没必要放在 Vuex 里了。store 过大会影响性能,也不方便管理。

大列表禁用响应式功能

默认情况下,定义在 Vue 组件data 里的数据都是响应式的,这种机制方便了数据绑定,当数据变化时界面得到自动更新。但有时候我们只是将数据显示到界面上,之后也不会改变它。这种情况下我们根本用不上响应式机制,而实现响应式是有性能代价的,特别是对于大对象和大列表。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = users;
  }
};

上面代码里的 users可能包含了非常多的数据,这样的对象数组要实现响应式会比较耗时。如果只是为了显示,不用于编辑,可以通过Object.freeze()禁用对象的响应式特性。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

在 Vuex 里也一样:

const mutations = {
  setUsers(state, users) {
    state.users = Object.freeze(users);
  }
};

如果确实需要修改数据,也可以重新生成数组:

state.users = Object.freeze([...state.users, user]);

根据测试,优化后的代码,对于同样的数据量,组件初始化的时间从几百毫秒缩短到几毫秒。

总结

以上是 Vue.js 应用代码优化的一点经验之谈,希望对你有用。欢迎在评论区留言,补充更多优化方法!

看到这个颇有气质的 logo,不来关注下吗?

image
上一篇下一篇

猜你喜欢

热点阅读