A few days ago, I saw everyone saying that the larger the Vue project, the more difficult it is to optimize, causing a lot of pain. This is unavoidable. The problem must be solved eventually. There is no problem with the performance of the framework. All major testing websites have relevant data. Let’s get to the point
The so-called basic optimization is required for any web project and is the root of the problem. HTML, CSS, and JS are the first steps to optimize.
correspond to the ones in the .vue file,
<template>,<style>,<script>
, below one by one Let’s talk about what are the points worth optimizing in the vue project
Semantic tags, avoiding random nesting, reasonably naming attributes and other standard recommended things will not be discussed. .
The template part helps us display structured data. Vue drives the view through data. Pay attention to the following points
Which one should be used for v-show and v-if? In my opinion, we need to think about the problem in two dimensions. The first dimension is the permission issue. As long as permission-related displays are involved, v-if
will undoubtedly be used. The second dimension is without permission restrictions. According to the frequency of user clicks, use v-show
for frequent switching, and v-if
for infrequent switching. The optimization point to be mentioned here is to reduce the number of pages in the page.
For the total number of doms, I prefer to use v-if
, because it reduces the number of doms and speeds up the rendering of the first screen. As for performance, I feel that the switching rendering process cannot be seen with the naked eye, and it will not affect the user experience. .
Don’t write too many expressions and judgments in the template v-if="isShow
&& isAdmin && (a || b)"
, although this expression can be recognized, it is not a long-term solution. When it looks uncomfortable, write it appropriately in methods and computed and encapsulate it into a method, like this The advantage is that it is convenient for us to judge the same expression in multiple places, and other elements with the same permissions can call the same method when judging and displaying
Add key when calling subcomponents in a loop. Key can uniquely identify a loop individual. For example, item.id
can be used as
key, if the array data is like this ['a', 'b', 'c', 'a']
, using :key="item"
is obviously meaningless, more A good way is to loop (item,
index) in arr
, and then :key="index"
to ensure the uniqueness of the key.
Should the style file be placed inside the vue file or outside it? It is meaningless to discuss. The focus is on dividing by modules. My habit is to put it inside the vue file. It is convenient to write code by jumping up and down in the same file. Regardless of internal or external suggestions, add <style
scoped>
The purpose of locking style files is very simple. No matter how easy-to-use the standard is, it cannot avoid the trouble of multi-person development. The agreed naming rules may also conflict. After locking the area, try to use short naming rules. No need .header-title__text
and the like
class, just .title
to get it done.
In order to distinguish it from the previous one, let’s talk about the global style file. The global style file should be as abstract as possible. Since it is not repeated in every component, it should be as general as possible. This part The better the abstraction, the smaller the size of your style file and the higher the reuse rate. It is recommended to put the code of the copied component library such as Element style into the global.
Do not use float layout, I have seen many people encapsulating it before .fl --
float: left
Go to the global file, and then .clear
, the current browser is not so weak that you have to use float
to be compatible, it is completely fine
The compatibility of flex and grid is average. In fact, the functions can be implemented in flex layout. Float will cause trouble in layout. Anyone who has used it will not believe that the explanation is confusing.
As for other general specifications, I won’t go into details here. There are many related articles.
This part is also the most difficult to optimize. Let me give you my personal opinion.
When developing with multiple people, try to keep the order of methods in each component export default {}
consistent to facilitate finding the corresponding method. My personal habit
data, props, hooks, watch, computed, components.
data What I want to say is that the structure of the initialized data should be as detailed as possible, with clear naming, simple and easy to understand, and avoid useless variables. isEditing can actually represent two states, true or false, no Then define notEditing to control the display, which can be done in the template {{
isEditing ? Editing: Save}}
props When passing values between parent and child components, try to :width="" :heigth=""
Don't :option={}
, the advantage of refinement is that only the parameters that need to be modified are passed in the sub-component
Add the data type to props, whether it must be passed, and the default value to facilitate troubleshooting errors and make the value transmission more rigorous.
The hook just needs to understand the meaning of the life cycle, when should the request be made, when should the method be logged out, and which methods need to be logged out. Simple and easy to understand, it is written on the official website.
Every method in methods must be simple and only do one thing. Try to encapsulate short and reusable methods without too many parameters. If you rely heavily on lodash development, method will look much simpler, but the cost is that the overall bundle size will be larger. If the project only uses a small number of methods, loadsh can be introduced locally. If you don't want to use lodash, you can encapsulate a util.js file yourself
Which question to use between watch and computed is shown on the official website for examples. Calculated properties are mainly a layer of filter conversion. Do not add some calling methods. The function of watch is to monitor data changes to change data or trigger Events such as this.$store.dispatch('update',
{ ... })
Vue’s componentization is deeply loved by everyone. To what extent is a reasonable level of component disassembly depends on the project. The size varies. Small projects can be completed with just a few components, without even using vuex, axios, etc. If the scale is large, components must be subdivided, the more detailed the better, including layout encapsulation, buttons, forms, prompt boxes, and carousels. Wait, it is recommended to look at the code of the Element component library. If you don’t have time to write such details, you can directly use the Element library and optimize it in several points.
Components have clear meanings and only handle similar businesses. The higher the reusability, the better, and the stronger the configurability, the better.
When encapsulating components yourself, you should still follow the rules of configuring props refinement.
Component classification, I habitually divide it into three categories, page, page-item and layout. Page is the routing control part, and page-item belongs to each layout block in the page such as banner. , side, etc., place components that appear at least twice on multiple pages in the layout, such as icon, scrollTop, etc.
vue-router In addition to switching routes, the most commonly used logic is to handle permissions. I won’t go into details about permission control here. There are many related demos and articles. When it comes to optimization, it is worth mentioning that lazy loading of components
中午官网链接如上,例子如下
const Foo = r => require.ensure([], () => r(require('./Foo.vue')), 'group-foo') const Bar = r => require.ensure([], () => r(require('./Bar.vue')), 'group-foo') 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 文件夹里进行。
基于上面一条,说下每个过程里面要做什么,前后端数据一定会有不一致的地方,或是数据结构,或是字段命名,那么究竟应该在哪一步处理数据转换的逻辑呢?有人会说其实哪一步都可以实现,其实不然,我的建议如下
在发 dispatch 之前就处理好组件内需要传的参数的数据结构和字段名
到了 action 允许我们做的事情很多,因为这部支持异步,支持 state, rootState, commit, dispatch, getters,由此可见责任重大,首先如果后端需要部分其他 module 里面的数据,要通过 rootState 取值再整合到原有数据上,下一步发出请求,建议(async await + axios),拿到数据后进行筛选转换,再发送 commit 到 mutation
这一步是将转换后的数据更新到 state 里,可能会有数据分发的过程(传进一个 object 改变多个 state 中 key 的 value),可以转换数据结构,但是尽量不做字段转换,在上一步做
此时的 store 已经更新,使用 getter 方法来取值,token:
state => state.token
,单单的取值,尽量不要做数据转换,需要转换的点在于多个地方用相同的字段,但是结构不同的情况(很少出现)。
在组件里用 mapGetters 拿到对应的 getter 值。
上面说了代码方面的规范和优化,下面说下重点的打包优化,前段时间打包的 vender bundle 足足 1.4M,app bundle 也有 270K,app bundle 可以通过组件懒加载解决,vender 包该怎么解决?
有人会质疑是不是没压缩或依赖包没去重,其实都做了就是看到的 1.4M。
解决方法很简单,打包 vender 时不打包 vue、vuex、vue-router、axios 等,换用国内的 bootcdn 直接引入到根目录的 index.html 中。
例如:
<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script> <script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script> <script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script> <script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>
在 webpack 里有个 externals,可以忽略不需要打包的库
externals: { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'axios': 'axios' }
此时的 vender 包会非常小,如果不够小还可以拆分其他的库,此时增加了请求的数量,但是远比加载一个 1.4M 的 bundle 快的多。
The above is the detailed content of How to optimize Vue projects. For more information, please follow other related articles on the PHP Chinese website!