1. 程式人生 > 其它 >Vue專案優化.

Vue專案優化.

技術標籤:Vuevue

程式碼優化

1.使用keep-alive快取不活動的元件例項。

keel-alive是一個抽象元件:它自身不會渲染一個DOM元素,也不會出現在父元件鏈中;使用keep-alive包裹動態元件時,會快取不活動的元件例項,而不是銷燬它們。

  • 在動態元件中的應用
<keep-alive :include="whiteList" :exclude="blackList" :max="amount">
     <component :is="currentComponent"
></component> </keep-alive>
  • 在vue-router中的應用
<keep-alive :include="whiteList" :exclude="blackList">
    <router-view></router-view>
</keep-alive>

include定義快取白名單,keep-alive會快取命中的元件;exclude定義快取黑名單,被命中的元件將不會被快取;
很多時候也可以配合路由的meta屬性使用

export default
[ { path:'/', name:'home', components:Home, meta:{ keepAlive:true //需要被快取的元件 }, { path:'/book', name:'book', components:Book, meta:{ keepAlive:false //不需要被快取的元件 } ] <keep-alive> <router-view v-if="this.$route.meat.keepAlive"></router-view> <!
--這裡是會被快取的元件--> </keep-alive> <keep-alive v-if="!this.$router.meta.keepAlive"></keep-alive> <!--這裡是不會被快取的元件-->

2.使用路由懶載入

Vue 是單頁面應用,可能會有很多的路由引入 ,這樣使用 webpcak 打包後的檔案很大,當進入首頁時,載入的資源過多,頁面會出現白屏的情況,不利於使用者體驗。如果我們能把不同路由對應的元件分割成不同的程式碼塊,然後當路由被訪問的時候才載入對應的元件,這樣就更加高效了。這樣會大大提高首屏顯示的速度,但是可能其他的頁面的速度就會降下來。

路由懶載入:

export default new Router({
  mode: 'history',
  routes: [
			{
		     path: '/',
		     component: ()=>import('@/components/DefaultIndex') }
		     ]
		     })

3.圖片懶載入
對於圖片過多的頁面,為了提高頁面的載入速度,所以很多時候我們需要將頁面內未出現在可視區域內的圖片先不做載入,等到圖片進入可視區域內的時候再去載入。這樣對於頁面載入效能上會有很大的提升,也提高了使用者的體驗,使用圖片懶載入我們需要在專案中使用Vue的vue-lazyload外掛:

npm引入:npm i vue-lazyload -S
CDN引入:[https://unpkg.com/vue-lazyload/vue-lazyload.js](https://unpkg.com/vue-lazyload/vue-lazyload.js)

使用:
main.js:

import Vue from 'vue'
import App from './App.vue'
import VueLazyload from 'vue-lazyload'
 
Vue.use(VueLazyload)
 
// or with options
Vue.use(VueLazyload, {
  preLoad: 1.3,
  error: 'dist/error.png',
  loading: 'dist/loading.gif',
  attempt: 1
})
 
new Vue({
  el: 'body',
  components: {
    App
  }
})

template:

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

4.使用防抖節流函式(效能優化)
那麼怎麼在Vue中使用呢?
在公共方法(untils.js中),加入函式防抖和節流方法:

// 防抖
export function _debounce(fn, delay) {
    var delay = delay || 200;
    var timer;
    return function () {
        var th = this;
        var args = arguments;
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
            timer = null;
            fn.apply(th, args);
        }, delay);
    };
}
// 節流
export function _throttle(fn, interval) {
    var last;
    var timer;
    var interval = interval || 200;
    return function () {
        var th = this;
        var args = arguments;
        var now = +new Date();
        if (last && now - last < interval) {
            clearTimeout(timer);
            timer = setTimeout(function () {
                last = now;
                fn.apply(th, args);
            }, interval);
        } else {
            last = now;
            fn.apply(th, args);
        }
    }
}


在需要的元件中引用:

import { _debounce } from "@/utils/public";

在methods中使用:

  methods: {
    // 改變場數
    changefield: _debounce(function(_type, index, item) {
        // do something ...
    }, 200)
  }

應用:

函式防抖(debounce)

在事件被觸發n秒後再執行回撥,如果在這n秒內又被觸發,則重新計時。

<body>
      <input type="text" id='unDebounce'>
</body>
</html>

<script>

    //模擬一段ajax請求
    function ajax(content){ 
        console.log('ajax request ' + content) 
        };
    letinputa = document.getElementById('unDebounce');
        function fn(e){ ajax(e.target.value) }
    //防抖函式,處理多次被觸發的事件,只執行最後一次
    inputa.addEventListener('input', fn)
</script>

看一下執行效果:
在這裡插入圖片描述
可以看到,我們只要輸入一個字元,就會觸發這次ajax請求。不僅從資源上來說是很浪費的行為,而且實際應用中,使用者也是輸出完整的字元後,才會請求。下面我們優化一下:

<body>
      <input type="text" id='unDebounce'>
</body>
</html>

<script>
    //防抖函式
    function _debounce(fn, delay) {
    var delay = delay || 200;
    var timer;
    return function () {
        var th = this;
        var args = arguments;
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
            timer = null;
            fn.apply(th, args);
        }, delay);
    };
}

    //模擬一段ajax請求
    function ajax(content){ 
        console.log('ajax request ' + content) 
        };
    let inputa = document.getElementById('unDebounce');
    function fn(e){ ajax(e.target.value) }
    //防抖函式,處理多次被觸發的事件,只執行最後一次
    inputa.addEventListener('input', _debounce(fn,1000))
</script>

在這裡插入圖片描述
我們加入了防抖以後,當你在頻繁的輸入時,並不會傳送請求,只有當你在指定間隔內沒有輸入時,才會執行函式。如果停止輸入但是在指定間隔內又輸入,會重新觸發計時。

個人理解 函式防抖就是法師發技能的時候要讀條,技能讀條沒完再按技能就會重新讀條。

函式節流(throttle)

規定在一個單位時間內,只能觸發一次函式。如果這個單位時間內觸發多次函式,只有一次生效。


<body>
      <input type="text" id='unDebounce'>
</body>
</html>

<script>
//節流函式
function _throttle(fn, interval) {
    var last;
    var timer;
    var interval = interval || 200;
    return function () {
        var th = this;
        var args = arguments;
        var now = +new Date();
        if (last && now - last < interval) {
            clearTimeout(timer);
            timer = setTimeout(function () {
                last = now;
                fn.apply(th, args);
            }, interval);
        } else {
            last = now;
            fn.apply(th, args);
        }
    }
}
    //模擬一段ajax請求
    function ajax(content){ 
        console.log('ajax request ' + content) 
        };
    let inputa = document.getElementById('unDebounce');
    function fn(e){ ajax(e.target.value) }
    //防抖節流,無論你輸入多塊,每隔1秒鐘執行一次
    inputa.addEventListener('input', _throttle(fn,1000))
</script>

在這裡插入圖片描述
不管我們設定的執行時間間隔多小,總是1s內只執行一次。

個人理解 函式節流就是fps遊戲的射速,就算一直按著滑鼠射擊,也只會在規定射速內射出子彈。

總結

函式防抖和函式節流都是防止某一時間頻繁觸發,但是這兩兄弟之間的原理卻不一樣。
函式防抖是某一段時間內只執行一次,而函式節流是間隔時間執行。

結合應用場景

debounce

  • search搜尋聯想,使用者在不斷輸入值時,用防抖來節約請求資源。
  • window觸發resize的時候,不斷的調整瀏覽器視窗大小會不斷的觸發這個事件,用防抖來讓其只觸發一次

throttle

  • 滑鼠不斷點選觸發,mousedown(單位時間內只觸發一次)
  • 拖拽事件,每拖動1px都會觸發onmousemove(可以用throttle優化,每秒觸發一次)
  • 監聽滾動事件,比如是否滑到底部自動載入更多,用throttle來判斷

5.v-for遍歷必須為item新增key,避免同時使用v-if

  • v-for 遍歷必須為 item 新增 key

在列表資料進行遍歷渲染時,需要為每一項 item 設定唯一 key 值,方便 Vue.js 內部機制精準找到該條列表資料。當 state
更新時,新的狀態值和舊的狀態值對比,較快地定位到 diff 。

  • v-for 遍歷避免同時使用 v-if

v-for 比 v-if 優先順序高,如果每一次都需要遍歷整個陣列,將會影響速度,尤其是當之需要渲染很小一部分的時候,必要情況下應該替換成
computed 屬性。

推薦:

<template>
  <div class="home">
    <ul>
      <li
        v-for="user in activeUsers"
        :key="user.id">
        {{ user.name }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data(){
    return {
      users:[{id:1,name:'zhangsan',isActive:true},{id:2,name:'lisi',isActive:true},{id:3,name:'wangwu',isActive:false},{id:4,name:'maliu',isActive:true},]
    }
  },
  computed: {
    activeUsers: function () {
    //  [js 的filter()方法](https://www.cnblogs.com/qiu2841/p/8961017.html)
      return this.users.filter(function (user) {
          return user.isActive
      })
    }
  }
}
</script>

不推薦:

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id">
    {{ user.name }}
  </li>
</ul>

6.v-if和v-show區分使用場景
v-if是真正的條件渲染,因為它會確保在切換過程中條件塊內的事件監聽器和子元件適當的被銷燬和重建;也是惰性的:如果在初始渲染時條件為假,則什麼也不做——直到條件第一次變為真時,才會開始渲染條件塊。

v-show就簡單得多, 不管初始條件是什麼,元素總是會被渲染,並且只是簡單地基於 CSS 的 display 屬性進行切換。

所以,v-if 適用於在執行時很少改變條件,不需要頻繁切換條件的場景; v-show則適用於需要非常頻繁切換條件的場景。