1. 程式人生 > 實用技巧 >Vue專案實用技巧整理

Vue專案實用技巧整理

1,css篇: 全域性引入公共的scss或者其他預編譯檔案 ,主要依賴:sass-resources-loader, 詳見我上一篇部落格
2. js篇:
2.1:props和$emit

巧用修飾符語法糖sync來優雅的更新props ,父子元件的傳值prop是很常用的業務,需要在子元件去更新prop的場景也很常見,但是prop是個只讀屬性,在子元件中直接修改其值因不符合單向資料流的設計,所以我們一般結合$emit來觸發父元件的方法, 但是有些場景
只是簡單的修改prop中的簡單的值, 比如切換顯示隱藏,更新type等等, 這時候就可以考慮使用sync修飾符了, 子元件更新prop的值也是必須要通過$emit來觸發, 這並沒有改變其單向資料流的設計的, 只是觸發的方法名前面多了一個 update: ,說白了就是你在父元件中使用了sync, Vue會幫你宣告一個method 名字就叫做 update:xxx 所以才免去你的手動新增這麼一個方法, 開始就說了這不過是個語法糖 , 具體程式碼如下:

parent.vue:

<child :title.sync="title"></child>

child.vue:

export defalut {
    props: {
        title: String  
    },
    methods: {
        changeTitle(){
            this.$emit('update:title', 'hello')
        }
    }

2.2:provide和inject(主要在開發高階外掛/元件庫時使用。並不推薦用於普通應用程式程式碼中。但是某些時候,或許它能幫助到我們)


  這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,並在其上下游關係成立的時間裡始終生效。

  簡單來說,一個元件將自己的屬性通過provide暴露出去,其下面的子孫元件inject即可接收到暴露的屬性

  程式碼如下:

App.vue:

export default {
    provide() {
        return {
            app: this
        }
    } 
}

child.vue:

export default {
    inject: ['app'],
    created() {
        console
.log(this.app) // App.vue例項 } }

ps:在 2.5.0+ 版本可以通過設定預設值使其變成可選項:

export default {
    inject: {
        app: {
            default: () => ({})
        }
    },
    created() {
        console.log(this.app) 
    }
}

如果你想為inject的屬性變更名稱,可以使用from來表示其來源:

export default {
    inject: {
        myApp: {
            // from的值和provide的屬性名保持一致
            from: 'app',
            default: () => ({})
        }
    },
    created() {
        console.log(this.myApp) 
    }
}

2.3:巧用template

相信v-if在開發中是用得最多的指令,那麼你一定遇到過這樣的場景,多個元素需要切換,而且切換條件都一樣,一般都會使用一個元素包裹起來,在這個元素上做切換。

<div v-if="status==='ok'">
    <h1>Title</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
</div>

如果像上面的 div 只是為了切換條件而存在,還導致元素層級巢狀多一層,那麼它沒有“存在的意義”。

我們都知道在宣告頁面模板時,所有元素需要放在<template>元素內。除此之外,它還能在模板內使用,<template>元素作為不可見的包裹元素,只是在執行時做處理,最終的渲染結果並不包含它。

<template>
    <div>
        <template v-if="status==='ok'">
          <h1>Title</h1>
          <p>Paragraph 1</p>
          <p>Paragraph 2</p>
        </template>
    </div>
</template>
我們也可以在<template>上使用v-for指令,  這也不失為解決v-if和v-for同時使用報出警告的問題的方法之一了,(之前是通過過濾資料後渲染解決的)
<template v-for="item in 10">
<div v-if="item % 2 == 0" :key="item">{{item}}</div> </template>
2.4:
require.context (自動註冊全域性元件功能在之前的部落格,請移步)
  這個並不是Vue提供的功能, 而是強大的Webpack提供的, 他還有另外一個妙用就是自動引入模組
像 api 檔案一般按功能劃分模組,在組合時可以使用require.context一次引入資料夾所有的模組檔案,而不需要逐個模組檔案去引入。每當新增模組檔案時,就只需要關注邏輯的編寫和模組暴露,require.context會幫助我們自動引入

程式碼如下: (可以做成外掛形式 具體請檢視vue外掛機制 )  import Request from '../service/request'

let importAll = require.context('./modules', false, /\.js$/) class Api extends Request{ constructor(){ super() //importAll.keys()為模組路徑陣列 importAll.keys().map(path =>{ //相容處理:.default獲取ES6規範暴露的內容; 後者獲取commonJS規範暴露的內容 let api = importAll(path).default || importAll(path) Object.keys(api).forEach(key => this[key] = api[key]) }) } } export default new Api()

路由懶載入(動態chunkName)

路由懶載入作為效能優化的一種手段,它能讓路由元件延遲載入。通常我們還會為延遲載入的路由新增“魔法註釋”(webpackChunkName),在打包時,該路由元件會被單獨打包出來。

let router = new Router({
  routes: [
    {
      path:'/login',
      name:'login',
      component: import(/* webpackChunkName: "login" */ `@/views/login.vue`)
    },
    {
      path:'/index',
      name:'index',
      component: import(/* webpackChunkName: "index" */ `@/views/index.vue`)
    },
    {
      path:'/detail',
      name:'detail',
      component: import(/* webpackChunkName: "detail" */ `@/views/detail.vue`)
    }
  ]
})

上面這種寫法沒問題,但仔細一看它們結構都是相似的,作為一名出色的開發者,我們可以使用map迴圈來解決這種重複性的工作。

const routeOptions = [
  {
    path:'/login',
    name:'login',
  },
  {
    path:'/index',
    name:'index',
  },
  {
    path:'/detail',
    name:'detail',
  },
]

const routes = routeOptions.map(route => {
  if (!route.component) {
    route = {
      ...route,
      component: () => import(`@/views/${route.name}.vue`)
    }
  }
  return route
})

let router = new Router({
  routes
})

在書寫更少程式碼的同時,我們也把“魔法註釋”給犧牲掉了。總所周知,程式碼中沒辦法編寫動態註釋。這個問題很尷尬,難道就沒有兩全其美的辦法了嗎?

強大的webpack來救場了,從 webpack 2.6.0 開始,佔位符 [index] 和 [request] 被支援為遞增的數字或實際解析的檔名。我們可以這樣使用“魔法註釋”:

const routes = routeOptions.map(route => {
  if (!route.component) {
    route = {
      ...route,
      component: () => import(/* webpackChunkName: "[request]" */ `@/views/${route.name}.vue`)
    }
  }
  return route
})