Vue 프로젝트를 최적화하는 방법

一个新手
풀어 주다: 2017-09-07 13:45:29
원래의
1708명이 탐색했습니다.

몇일 전, Vue 프로젝트가 커질수록 최적화가 어려워지고 많은 고통을 겪는다고 다들 말하는 것을 봤습니다. 이 문제는 결국에는 해결되어야 할 문제입니다. 모든 주요 테스트 웹사이트에는 관련 데이터가 있습니다. 본론으로 들어가죠

기본 최적화

소위 기본 최적화는 모든 웹 프로젝트에 필요하며 문제의 근원입니다. HTML, CSS, JS는 .vue 파일, <p style="margin-top:1.5em; margin-bottom:1.5em; color:rgb(51,51,51); font-size:14px">을 최적화하는 첫 번째 단계입니다. -size:0.93em; padding:2px 4px; color:rgb(199,37,78) background-color:rgb(249,242,244)"></p>

<template>,<style>,<script>
로그인 후 복사

,下面逐个谈下 vue 项目里都有哪些值得优化的点

template

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

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

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

  • 不要在模板里面写过多的表达式与判断 v-if="isShow && isAdmin && (a || b)"

    const Foo = r => require.ensure([], () => r(require(&#39;./Foo.vue&#39;)), &#39;group-foo&#39;)
    const Bar = r => require.ensure([], () => r(require(&#39;./Bar.vue&#39;)), &#39;group-foo&#39;)
    const Baz = r => require.ensure([], () => r(require(&#39;./Baz.vue&#39;)), &#39;group-foo&#39;)
    로그인 후 복사
    로그인 후 복사

    , vue 프로젝트에서 최적화할 만한 포인트를 하나씩 이야기해보겠습니다
    🎜

    템플릿

    🎜의미 태그, 임의 중첩 방지, 합리적인 이름 지정 속성 및 기타 표준 권장 사항은 논의되지 않습니다. 🎜🎜템플릿 부분은 구조화된 데이터를 표시하는 데 도움이 됩니다. Vue는 데이터를 통해 뷰를 구동합니다. 🎜
    • v-show, v-if 어느 것을 사용할 것인가? 제 생각에는 이 문제를 두 가지 차원에서 생각해 볼 필요가 있습니다. 첫 번째 차원은 권한 관련 표시가 포함되는 한 v-if, 두 번째 차원은 권한 제한 없이 사용자 클릭 빈도를 기준으로 선택되며 빈번한 전환에 사용됩니다. v-show v-if, 여기서 최적화 포인트는 총 돔 수에 대해서는 v-if, 이는 DOM 수를 줄이고 첫 번째 화면 렌더링 속도를 높이기 때문입니다. 전환 렌더링은 육안으로 볼 수 없다고 생각합니다. 이 프로세스는 사용자 경험에 영향을 미치지 않습니다. 🎜

    • 템플릿 v -if="is쇼 && isAdmin && (a || b)", 이 표현식은 인식 가능하지만 장기적인 해결책은 아닙니다. 불편해 보일 때는 메소드에 적절하게 작성하고 계산하여 메소드에 캡슐화하고, 그래서 장점은 여러 곳에서 동일한 표현을 판단하는 것이 편리하고, 동일한 권한을 가진 다른 요소는 판단하고 표시할 때 동일한 메소드를 호출할 수 있다는 것입니다.

    • 루프에서 하위 구성 요소를 호출할 때 키를 추가하세요. 예를 들어 item.id 키, 배열 데이터가 다음과 같은 경우 ['a', 'b', 'c', 'a'], :key="item"은 분명히 의미가 없습니다. 더 좋은 방법은 (항목, index) arr에서 :key="index" 키의 고유성을 보장합니다. item.id 作为 key,假如数组数据是这样的 [&#39;a&#39; , &#39;b&#39;, &#39;c&#39;, &#39;a&#39;],使用 :key="item" 显然没有意义,更好的办法就是在循环的时候 (item, index) in arr,然后 :key="index"来确保 key 的唯一性。

    style

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

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

    • 不使用 float 布局,之前看到很多人封装了 .fl -- float: left 到全局文件里去,然后又要 .clear,现在的浏览器还不至于弱到非要用 float

    style

      스타일 파일을 vue 파일 내부에 넣으시겠습니까, 아니면 외부에 넣으시겠습니까? 토론의 의미가 없습니다. 초점은 모듈별로 나누는 것입니다. 내부 또는 외부 제안에 관계없이 동일한 파일에서 위아래로 코드를 작성하는 것이 편리합니다. code style="font-family:" 소스 코드 프로",Consolas,Menlo,Monaco,"Courier New",monospace; 글꼴 크기:0.93em; 패딩:2px 4px; 색상:rgb(199,37,78); 배경색:rgb(249,242,244)" ><스타일 범위 지정> 스타일 파일을 잠그는 목적은 매우 간단합니다. 표준이 아무리 사용하기 쉽다고 해도 잠긴 후 합의된 명명 규칙이 충돌할 수 있습니다. 영역에서는 짧은 이름 지정 규칙을 사용해 보세요. .header-title__text 등 클래스, 직접 .title 완료되었습니다.

      🎜이전 글과 구별하기 위해 전역 스타일 파일에 대해 이야기해 보겠습니다. 전역 스타일 파일은 모든 구성 요소에서 반복되지 않으므로 최대한 일반적이어야 합니다. 추상화의 이 부분이 좋을수록 스타일 파일의 크기가 작을수록 재사용률이 높아집니다. Element 스타일 등 복사한 컴포넌트 라이브러리의 코드를 글로벌에 넣는 것을 권장합니다. 🎜🎜🎜🎜float 레이아웃을 사용하지 마세요. .fl float: 왼쪽을 전역 파일로 가져온 다음 .clear, 현재 브라우저는 float이 호환되므로 완전히 괜찮습니다. Flex와 Grid의 호환성은 보통 수준입니다. 실제로 Flex 레이아웃에서 기능을 구현할 수 있습니다. Float를 사용하면 레이아웃에 문제가 발생할 수 있습니다. 🎜🎜🎜🎜기타 일반적인 사양에 대해서는 여기서 자세히 다루지 않겠습니다. 🎜🎜script🎜🎜이 부분이 최적화하기 가장 어려운 부분이기도 한데 개인적인 의견을 말씀드리겠습니다. 🎜
      • 여러 사람과 함께 개발할 때는 각 구성 요소를 export default {} 메소드의 순서가 동일하므로 해당 메소드를 쉽게 찾을 수 있습니다. 내 개인적인 습관 데이터, 소품, 후크, 시계, 계산, 구성 요소. 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(&#39;update&#39;, { ... })

      데이터에서 제가 말하고 싶은 것은 초기화된 데이터의 구조가 가능한 한 상세해야 하고, 명확한 이름을 지정하고, 간단하고 이해하기 쉬워야 하며, 쓸모 없는 변수를 피해야 한다는 것입니다. isEditing은 실제로 true 또는 두 가지 상태를 나타낼 수 있습니다. false. 표시를 제어하기 위해 notEditing을 정의하지 마십시오. { isEditing ? 편집: 저장}}

      props 상위 구성 요소와 하위 구성 요소 간에 값을 전달할 때 :width="" :heigth="" < code style="font-family:"Source Code Pro",Consolas,Menlo,Monaco,"Courier New",monospace; 글꼴 크기:0.93em; padding:2px 4px; color:rgb (199,37,78); background-color:rgb(249,242,244)">:option={}, 개선의 장점은 수정해야 하는 매개변수만 하위 구성 요소에 전달된다는 것입니다. props에 데이터 유형을 추가하고, 전달해야 하는지 여부와 기본값을 추가하여 오류 문제 해결을 용이하게 하고 값 전송을 더욱 엄격하게 만듭니다.
      • 훅은 라이프 사이클의 의미, 언제 요청해야 하는지, 언제 메소드를 로그아웃해야 하는지, 어떤 메소드를 로그아웃해야 하는지 이해하면 됩니다. 간단하고 이해하기 쉽게 공식 홈페이지에 적혀있습니다.
      • 메서드의 각 메서드는 단순해야 하며 한 가지 작업만 수행해야 합니다. 너무 많은 매개변수 없이 짧고 재사용 가능한 메서드를 캡슐화하세요. 개발을 위해 lodash에 크게 의존하는 경우 방법은 훨씬 간단해 보이지만 전체 번들 크기가 더 커지게 됩니다. 프로젝트에서 소수의 방법만 사용하는 경우 loadsh를 로컬로 도입할 수 있습니다. lodash를 사용하려면 util.js 파일을 직접 캡슐화할 수 있습니다
      • 어떤 것을 사용할지에 대한 질문은 공식 웹사이트의 예를 참조하세요. 계산된 속성은 주로 필터 변환 레이어입니다. 일부 호출 방법을 추가하지 마십시오. watch의 기능은 데이터 변경을 모니터링하여 this.$store.dispatch('update', { ... })

      컴포넌트 최적화

      vue의 컴포넌트화는 모두가 좋아합니다. 컴포넌트의 합리적인 정도는 프로젝트 규모에 따라 다릅니다. , vuex, axios 등도 필요하지 않습니다. 규모가 큰 경우 레이아웃 캡슐화, 버튼, 양식, 프롬프트 상자, 캐러셀 등을 포함하여 구성 요소가 작을수록 좋습니다. Element 컴포넌트 라이브러리의 코드를 살펴보세요. 이렇게 자세히 작성할 시간이 없다면 Element 라이브러리를 직접 사용하여 여러 가지 측면에서 최적화할 수 있습니다. 재사용성이 높을수록 좋고, 구성 가능성이 강할수록 좋습니다. 🎜🎜🎜🎜구성 요소를 직접 캡슐화하거나 소품 구체화 구성 규칙을 따를지 여부. 🎜🎜🎜🎜컴포넌트 분류, 나는 습관적으로 페이지, 페이지 항목, 레이아웃의 세 가지 범주로 나눕니다. 페이지 항목은 배너, 측면 등 페이지의 각 레이아웃 블록에 속합니다. , 레이아웃에 배치됩니다. 아이콘, 스크롤탑 등 여러 페이지에 두 번 이상 표시됩니다. 🎜🎜🎜🎜vue-router 및 vuex 최적화 🎜🎜vue-router 경로 전환 외에도 가장 일반적으로 사용되는 논리는 권한을 처리하는 것입니다. 세부적으로 설명하면 최적화와 관련하여 언급할 가치가 있는 한 가지는 구성 요소의 지연 로딩입니다.

      中午官网链接如上,例子如下

      const Foo = r => require.ensure([], () => r(require(&#39;./Foo.vue&#39;)), &#39;group-foo&#39;)
      const Bar = r => require.ensure([], () => r(require(&#39;./Bar.vue&#39;)), &#39;group-foo&#39;)
      const Baz = r => require.ensure([], () => r(require(&#39;./Baz.vue&#39;)), &#39;group-foo&#39;)
      로그인 후 복사
      로그인 후 복사

      这段代码将 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 中。

      例如:

      <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: {  
          &#39;vue&#39;: &#39;Vue&#39;,  
          &#39;vue-router&#39;: &#39;VueRouter&#39;,  
          &#39;vuex&#39;: &#39;Vuex&#39;,  
          &#39;axios&#39;: &#39;axios&#39;
      }
      로그인 후 복사

      此时的 vender 包会非常小,如果不够小还可以拆分其他的库,此时增加了请求的数量,但是远比加载一个 1.4M 的 bundle 快的多。

      위 내용은 Vue 프로젝트를 최적화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!