1. 程式人生 > >Vue元件的自動化全域性註冊

Vue元件的自動化全域性註冊

如果使用了Webpck進行了檔案的組織、編譯,就可以使用require.context令元件實現自動化註冊。

這個過程需要在建立Vue例項之前(new Vue({}))之前完成,例如src/main.js

require.context

Webpack解析帶有表示式的require語句時,會建立一個上下文(context),因為在編譯時(compile time)並不清楚具體是哪一個模組被匯入。

上下文模組還包含一些執行時(runtime)邏輯來訪問這個 map 物件。

這意味著webpack能夠支援動態require,但會導致所有可能用到的模組都包含在bundle中。

還可以使用equire.context()方法來建立自己的(模組)上下文。

你可以給這個方法傳3個引數:要搜尋的資料夾目錄,是否還應該搜尋它的子目錄,以及一個匹配檔案的正則表示式。

語法如下:

require.context(directory, useSubdirectories = false, regExp = /^\.\//);

例項:

require.context('./test', false, /\.test\.js$/);
// (建立了)一個包含了 test 資料夾(不包含子目錄)下面的、所有檔名以 `.test.js` 結尾的、能被 require 請求到的檔案的上下文。
require.context('../', true, /\.stories\.js$/); // (建立了)一個包含了父級資料夾(包含子目錄)下面,所有檔名以 `.stories.js` 結尾的檔案的上下文。

傳遞給 require.context 的引數必須是字面量(literal)!

匯出的上下文有是三個屬性:

  • resolve是一個函式,它返回請求被解析後得到的模組id。
  • keys也是一個函式,它返回一個數組,由所有可能被上下文模組處理的請求組成
  • id是上下文模組裡面所包含的模組id

用自己創建出的上下文,去引入要引入的檔案,這是關鍵

const
context = require.context('.', false, /.*\.(jpg|png)$/); const images = context.keys().map(v => context(v));

利用require.context註冊元件

main.js

const requireComponent = require.context(
  // 其元件目錄的相對路徑
  './components',
  // 是否查詢其子目錄
  false,
  // 匹配基礎元件檔名的正則表示式
  /Base[A-Z]\w+\.(vue|js)$/
)


requireComponent.keys().forEach(fileName => {
  // 獲取元件配置
  const componentConfig = requireComponent(fileName)

  // 獲取元件的 PascalCase 命名
  const componentName = upperFirst(
    camelCase(
      // 剝去檔名開頭的 `./` 和結尾的副檔名
      fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
    )
  )

  // 全域性註冊元件
  Vue.component(
    componentName,
    // 如果這個元件選項是通過 `export default` 匯出的,
    // 那麼就會優先使用 `.default`,
    // 否則回退到使用模組的根。
    componentConfig.default || componentConfig
  )
})

動態註冊路由

實現元件的自動註冊後就可以實現路由的自動註冊,在router/index.js

import Vue from 'vue';
import Router from 'vue-router';

const requireComponent  = require.context('../components/demos', true, /demo[1-9][0-9]?\.vue$/);
const routes = requireComponent.keys().map(fileName => {
  // 獲取元件配置
  const componentConfig = requireComponent(fileName);

  // 剝去檔名開頭的 `./` 和結尾的副檔名
  const componentName = fileName.replace(/^\.\/(demo[1-9][0-9]?).*\.\w+$/, '$1');

  // 全域性註冊元件
  const component = Vue.component(
    componentName,
    // 如果這個元件選項是通過 `export default` 匯出的,
    // 那麼就會優先使用 `.default`,
    // 否則回退到使用模組的根。
    componentConfig.default || componentConfig
  );
  
  return {
    path: `/${componentName}` ,
    name: componentName,
    component,
  }
});

Vue.use(Router);

export default new Router({
  routes,
})

其他應用

還可以使用require.context實現一些其他目錄的操作,例如讀取目錄下的圖片:

<template>
  <div>
    <img v-for="img in images" :src="img" :key="img" class="insert">
  </div>
</template>


<script>
  const context = require.context('.', false, /.*\.(jpg|png)$/);
  const images = context.keys().map(v => context(v));
  
  export default {
    data() {
      return {
        images,
      }
    }
  }
</script>

參考