vue進階 -- 技巧總結

一、合理利用watch的immediate屬性

例如在組件創建時需要獲取一次數據列表,然後監聽數據的變化,根據數據改變重新獲取列表。通常這麼寫:

created(){
    this.fetchPostList()
},
    watch: {
        changeValue(){
            this.fetchPostList()
        }
    }

但是上面的這種寫法我們可以精簡寫成如下:

watch: {
    changeValue:{
        handler: 'fetchPostList',
            immediate: true
    }
}
聲明 immediate:true, 表示創建的時候立即執行一次。

二、利用require.context()進行組件引入和註冊

一般情況下,組件寫法如下:

import BaseButton from './baseButton'
import BaseIcon from './baseIcon'
import BaseInput from './baseInput'

export default {
    components: {
        BaseButton,
        BaseIcon,
        BaseInput
    }
}
<BaseInput v-model="searchText" @keydown.enter="search" />
<BaseButton @click="search"> <BaseIcon name="search"/></BaseButton>

一般步驟有三步:

  1. 引入
  2. 註冊組件
  3. 正式使用

這是最常見和通用的寫法。但是如果組件過多,則要引入多次,註冊多次。

我們可以藉助一下webpack,使用 require.context() 方法來創建自己的(模塊)上下文,從而實現自動動態require組件。

思路是:在src文件夾下面main.js中,藉助webpack動態地將需要的基礎組件統統打包進來。

代碼如下:

一些方法解釋: upperFirstcamelCaserequire.context()
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

// Require in a base component context
const requireComponent = require.context(
    ‘./components', false, /base-[\w-]+\.vue$/
)

requireComponent.keys().forEach(fileName => {
    // Get component config
    const componentConfig = requireComponent(fileName)

    // Get PascalCase name of component
    const componentName = upperFirst(
        camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
    )

    // Register component globally
    Vue.component(componentName, componentConfig.default || componentConfig)
})

這樣我們引入組件只需要第三步就可以了:

<BaseInput v-model="searchText" @keydown.enter="search" />
<BaseButton @click="search">
    <BaseIcon name="search" /></BaseButton>

三、精簡vuex的modules引入

對於vuex,我們輸出store寫法如下:

import auth from './modules/auth'
import posts from './modules/posts'
import comments from './modules/comments'
...

export default new Vuex.Store({
    modules: {
        auth,
        posts,
        comments,
        ...
    }
})

要引入很多modules,然後再註冊到Vuex.Store中。。

精簡的做法也是運用 require.context()讀取文件,代碼如下:

import camelCase from 'lodash/camelCase'
const requireModule = require.context('.', false, /\.js$/)
const modules = {}
requireModule.keys().forEach(fileName => {
    // Don't register this file as a Vuex module
    if (fileName === './index.js') return

    const moduleName = camelCase(
        fileName.replace(/(\.\/|\.js)/g, '')
    )
    modules[moduleName] = {
        namespaced: true,
        ...requireModule(fileName),
    }
})
export default modules

這樣我們只需如下代碼就可以了:

import modules from './modules'
export default new Vuex.Store({
    modules
})

四、組件的異步加載(按需加載組件)

在平時的demo中,可能不會遇見這個需求。當頁面很多,組件很多的時候,SPA頁面在首次加載的時候,就會變的很慢。這是因爲vue首次加載的時候把可能一開始看不見的組件也一次加載了,這個時候就需要對頁面進行優化,就需要異步組件了。

在路由index.js裏(路徑: src/router/index.js ),通過require方式或者import()方式動態加載組件。像下面這樣:

{
    path: '/home',
    name: 'home',
    component:require('@views/home').default
}

或者

{
    path: '/home',
    name: 'home',
    component:() => import('@views/home')
}

五、通過router :key進行組件刷新

首先默認使用的是Vue-router來實現路由的控制。

假設現在在寫一個網站,需求是從 /post/a 跳轉到 /post/b 。然後我們就會發現,頁面跳轉後數據竟然沒更新?!原因是vue-router “智能地” 發現這是同一個組件,然後它就決定要複用這個組件,所以在created函數裏寫的方法全部沒有執行。

通常的解決方案是監聽$route的變化來初始化數據,如下:

data() {
    return {
        loading: false,
        error: null,
        post: null
    }
}, 
watch: {
   '$route': {
       handler: 'resetData',
       immediate: true
    }
},
methods: {
    resetData() {
       this.loading = false
       this.error = null
       this.post = null
       this.getPost(this.$route.params.id)
     },
    getPost(id){}
}

問題是解決了,但是這樣的處理方式不夠優雅。我們希望代碼這樣寫:

data() {
    return {
        loading: false,
        error: null,
        post: null
    }
},
created () {
    this.getPost(this.$route.params.id)
},
methods () {
    getPost(postId) {
        ...
    }
}

如何達到這樣的效果:給router-view添加一個唯一的key,這樣只要url變化了,就一定會重新創建這個組件。就避免了vue-rouer因爲複用組件導致created函數中的方法不執行的問題。

<router-view :key="$route.fullpath"></router-view>
注: 這個一般應用在子路由裏面,這樣纔可以避免大量重繪,假設App.vue根目錄添加這個屬性,那麼每次點擊改變地址都會重繪!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章