vue 项目优化

基础优化

所谓的基础优化是任何 web 项目都要作的,而且是问题的根源。HTML,CSS,JS 是第一步要优化的点css

分别对应到 .vue 文件内的,<template>,<style>,<script>,下面逐个谈下 vue 项目里都有哪些值得优化的点html

template

语义化标签,避免乱嵌套,合理命名属性等等标准推荐的东西就不谈了。vue

模板部分帮助咱们展现结构化数据,vue 经过数据驱动视图,主要注意一下几点webpack

  • v-show,v-if 用哪一个?在我来看要分两个维度去思考问题,第一个维度是权限问题,只要涉及到权限相关的展现无疑要用 v-if,第二个维度在没有权限限制下根据用户点击的频次选择,频繁切换的使用 v-show,不频繁切换的使用 v-if,这里要说的优化点在于减小页面中 dom 总数,我比较倾向于使用 v-if,由于减小了 dom 数量,加快首屏渲染,至于性能方面我感受肉眼看不出来切换的渲染过程,也不会影响用户的体验。ios

  • 不要在模板里面写过多的表达式与判断 v-if="isShow && isAdmin && (a || b)",这种表达式虽然说能够识别,可是不是长久之计,当看着不舒服时,适当的写到 methods 和 computed 里面封装成一个方法,这样的好处是方便咱们在多处判断相同的表达式,其余权限相同的元素再判断展现的时候调用同一个方法便可。web

  • 循环调用子组件时添加 key,key 能够惟一标识一个循环个体,可使用例如 item.id 做为 key,假如数组数据是这样的 ['a' , 'b', 'c', 'a'],使用 :key="item" 显然没有意义,更好的办法就是在循环的时候 (item, index) in arr,而后 :key="index"来确保 key 的惟一性。vue-router

style

  • 将样式文件放在 vue 文件内仍是外?讨论起来没有意义,重点是按模块划分,个人习惯是放在 vue 文件内部,方便写代码是在同一个文件里跳转上下对照,不管内外建议加上 <style scopeed> 将样式文件锁住,目的很简单,再好用的标准也避免不了多人开发的麻烦,约定命名规则也可能会冲突,锁定区域后尽可能采用简短的命名规则,不须要 .header-title__text 之类的 class,直接 .title 搞定。vuex

  • 为了和上一条做区分,说下全局的样式文件,全局的样式文件,尽可能抽象化,既然不在每个组件里重复写,就尽可能通用,这部分抽象作的越好说明你的样式文件体积越小,复用率越高。建议将复写组件库如 Element 样式的代码也放到全局中去。axios

  • 不使用 float 布局,以前看到不少人封装了 .fl -- float: left 到全局文件里去,而后又要 .clear,如今的浏览器还不至于弱到非要用 float 去兼容,彻底能够 flex,grid 兼容性通常,功能其实 flex 布局均可以实现,float 会带来布局上的麻烦,用过的都知道不相信解释坑了。后端

至于其余通用的规范这里不赘述,相关文章不少。

script

这部分也是最难优化的点,说下我的意见吧。

  • 多人开发时尽可能保持每一个组件 export default {} 内的方法顺序一致,方便查找对应的方法。我我的习惯 data、props、钩子、watch、computed、components。

  • data 里要说的就是初始化数据的结构尽可能详细,命名清晰,简单易懂,避免无用的变量,isEditing 实际能够表明两个状态,true 或 false,不要再去定义 notEditing 来控制展现,彻底能够在模板里 {{ isEditing ? 编辑中 : 保存 }}

  • props 父子组件传值时尽可能 :width="" :heigth="" 不要 :option={},细化的好处是只传须要修改的参数,在子组件 props 里加数据类型,是否必传,以及默认值,便于排查错误,让传值更严谨。

  • 钩子理解好生命周期的含义就好,什么时间应该请求,什么时间注销方法,哪些方法须要注销。简单易懂,官网都有写。

  • metheds 中每个方法必定要简单,只作一件事,尽可能封装可复用的简短的方法,参数不易过多。若是十分依赖 lodash 开发,methed 看着会简洁许多,代价就是总体的 bundle 体积会大,假如项目仅仅用到小部分方法能够局部引入 loadsh,不想用 lodash 的话能够本身封装一个 util.js 文件

  • watch 和 computed 用哪一个的问题看官网的例子,计算属性主要是作一层 filter 转换,切忌加一些调用方法进去,watch 的做用就是监听数据变化去改变数据或触发事件如 this.$store.dispatch('update', { ... })

组件优化

vue 的组件化深受你们喜好,到底组件拆到什么程度算是合理,还要因项目大小而异,小型项目能够简单几个组件搞定,甚至不用 vuex,axios 等等,若是规模较大就要细分组件,越细越好,包括布局的封装,按钮,表单,提示框,轮播等,推荐看下 Element 组件库的代码,没时间写这么详细能够直接用 Element 库,分几点进行优化

  • 组件有明确含义,只处理相似的业务。复用性越高越好,配置性越强越好。

  • 本身封装组件仍是遵循配置 props 细化的规则。

  • 组件分类,我习惯性的按照三类划分,page、page-item 和 layout,page 是路由控制的部分,page-item 属于 page 里各个布局块如 banner、side 等等,layout 里放置多个页面至少出现两次的组件,如 icon, scrollTop 等

vue-router 和 vuex 优化

vue-router 除了切换路由,用的最多的是处理权限的逻辑,关于权限的控制这里不赘述,相关 demo 和文章有许多,那么说到优化,值得一提的就是组件懒加载

中午官网连接如上,例子以下

 

  1.  
    const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo')
  2.  
    const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo')
  3.  
    const Baz = r => require.ensure([], () => r(require('./Baz.vue')), 'group-foo')

这段代码将 Foo, Bar, Baz 三个组件打包进了名为 group-foo 的 chunk 文件,固然啦是 js 文件

其他部分正常写就能够,在网站加载时会自动解析须要加载哪一个 chunk,虽然分别打包的整体积会变大,可是单看请求首屏速度的话,快了好多。

vuex 面临的问题和解决方案有几点

  • 当网站足够大时,一个状态树下,根的部分字段繁多,解决这个问题就要模块化 vuex,官网提供了模块化方案,容许咱们在初始化 vuex 的时候配置 modules。每个 module 里面又分别包含 state 、action 等,看似是多个状态树,其实仍是基于 rootState 的子树。细分后整个 state 结构就清晰了,管理起来也方便许多。

  • 因为 vuex 的灵活性,带来了编码不统一的状况,完整的闭环是 store.dispatch('action') -> action -> commit -> mutation -> getter -> computed,实际上中间的环节有的能够省略,由于 API 文档提供了如下几个方法 mapState、mapGetters、mapActions、mapMutations,而后在组件里能够直接调取任何一步,仍是项目小想怎么调用均可以,项目大的时候,就要考虑 vuex 使用的统一性,个人建议是不论多简单的流程都跑完整个闭环,造成代码的统一,方便后期管理,在个人组件里只容许出现 dispatch 和 mapGetters,其他的流程都在名为 store 的 vuex 文件夹里进行。

  • 基于上面一条,说下每一个过程里面要作什么,先后端数据必定会有不一致的地方,或是数据结构,或是字段命名,那么究竟应该在哪一步处理数据转换的逻辑呢?有人会说其实哪一步均可以实现,其实否则,个人建议以下

  1. 在发 dispatch 以前就处理好组件内须要传的参数的数据结构和字段名

  2. 到了 action 容许咱们作的事情不少,由于这部支持异步,支持 state, rootState, commit, dispatch, getters,因而可知责任重大,首先若是后端须要部分其余 module 里面的数据,要经过 rootState 取值再整合到原有数据上,下一步发出请求,建议(async await + axios),拿到数据后进行筛选转换,再发送 commit 到 mutation

  3. 这一步是将转换后的数据更新到 state 里,可能会有数据分发的过程(传进一个 object 改变多个 state 中 key 的 value),能够转换数据结构,可是尽可能不作字段转换,在上一步作

  4. 此时的 store 已经更新,使用 getter 方法来取值,token: state => state.token,单单的取值,尽可能不要作数据转换,须要转换的点在于多个地方用相同的字段,可是结构不一样的状况(不多出现)。

  5. 在组件里用 mapGetters 拿到对应的 getter 值。

打包优化

上面说了代码方面的规范和优化,下面说下重点的打包优化,前段时间打包的 vender bundle 足足 1.4M,app bundle 也有 270K,app bundle 能够经过组件懒加载解决,vender 包该怎么解决?

有人会质疑是否是没压缩或依赖包没去重,其实都作了就是看到的 1.4M。

解决方法很简单,打包 vender 时不打包 vue、vuex、vue-router、axios 等,换用国内的 bootcdn 直接引入到根目录的 index.html 中。

例如:

  1.  
    <script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
  2.  
    <script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
  3.  
    <script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
  4.  
    <script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>


在 webpack 里有个 externals,能够忽略不须要打包的库

  1.  
    externals: {
  2.  
    'vue': 'Vue',
  3.  
    'vue-router': 'VueRouter',
  4.  
    'vuex': 'Vuex',
  5.  
    'axios': 'axios'
  6.  
    }

 

此时的 vender 包会很是小,若是不够小还能够拆分其余的库,此时增长了请求的数量,可是远比加载一个 1.4M 的 bundle 快的多。

总结

本文谈的优化能够解决部分性能问题,实际开发细节不少,总之按着规范写代码,团队的编码风格尽可能统一,处理细节上多加思考,大部分性能问题都能迎刃而解。

相关文章
相关标签/搜索