原文鏈接: 本人掘金文章 假如圖片看不清晰可前往掘金原文預覽
未優化版: 在Vue
官方文檔 中,我們通過 Vue.component('MyComponentName', { /* ... */ })
的方式來進行全局組件注冊,但如果需要全局注冊的組件很多,這時代碼就會變得比較臃腫,例如:
// 注冊組件 import Component1 from './components/Component1' import Component2 from './components/Component2' // 方式1 Vue.component('Component1', Component1) Vue.component('Component2', Component2) // 方式2 const components = { Component1, Component2 } Object.keys(components).forEach(key => { Vue.component(key, components[key]) }) // 注冊路由 export default new Router({ routes: [ { // 登錄頁 path: '/', name: 'Login', component: (resolve) => { require(['@/pages/Login'], resolve) } }] })
優化版: webpack
提供的API
神器 require.context()
可用來創建自己的(模塊)上下文,具體打印看末尾
require.contex t函數接收三個參數:
- 要搜索的文件夾目錄
- 是否還應該搜索它的子目錄
- 以及一個匹配文件的正則表達式
一、先把我的目錄結構及文件組成貼出來 (這是vue-cli3.0
未使用typescript
的版本)
接下來如何自動注冊組件呢: 全局新建一個 utils
目錄下新建一個 global.js
// 獲取所有vue文件 function getComponent() { return require.context('../views', true, /\.vue$/); } // 首字母轉換大寫 function viewToUpperCase(str) { return str.charAt(0).toUpperCase() + str.slice(1); } // 首字母轉換小寫 function viewToLowerCase(str) { return str.charAt(0).toLowerCase() + str.slice(1); } // 自動注冊組件方法 export const vueComponent = () => { // 獲取文件全局對象 const requireComponents = getComponent(); requireComponents.keys().forEach((fileSrc) => { const fileName = requireComponents(fileSrc); const file = fileName.default; const componentName = file.name; // 是否自動注冊組件依據每個文件里的 isComponent 屬性 避免注冊不用的組件 if (file.isComponent) Vue.component(componentName, fileName.default || fileName); }); }; // 自動注冊路由方法 export const vueRouters = () => { const routerList = []; const requireRouters = getComponent(); requireRouters.keys().forEach((fileSrc) => { // 獲取 components 文件下的文件名 const viewSrc = requireRouters(fileSrc); console.log(viewSrc); const file = viewSrc.default; // 首字母轉大寫 const vueRouterUpper = viewToUpperCase(file.name); // 首字母轉小寫 const vueRouterLower = viewToLowerCase(file.name); const fileNameSrc = fileSrc.replace(/^\.\//, ''); // 是否自動注冊路由依據每個文件里的 isRouter 屬性 避免注冊不用的路由 if (file.isRouter) { // 注冊路由 routerList.push({ path: `/${vueRouterLower}`, name: `${vueRouterUpper}`, component: () => import(`@/views/${fileNameSrc}`), }); } }); console.log(routerList); return routerList; };
引入方式

二、這是 vue-cli3.0 使用 typescript 的版本, 不同的是 下 global.ts
需要增加類型,及文件設置屬性的方法不用, 且獲取上下文的時候是在 options
里
global.ts
修改為
import Vue from 'vue'; // 獲取所有vue文件 function getComponent() { return require.context('../views', true, /\.vue$/); } // 首字母轉換大寫 function viewToUpperCase(str: string) { return str.charAt(0).toUpperCase() + str.slice(1); } // 首字母轉換小寫 function viewToLowerCase(str: string) { return str.charAt(0).toLowerCase() + str.slice(1); } export const vueComponent = () => { // 獲取文件全局對象 const requireComponents = getComponent(); requireComponents.keys().forEach((fileSrc: string) => { const fileName = requireComponents(fileSrc); const file = fileName.default.options; const componentName = file.name; if (fileName.default.isComponent) { Vue.component(componentName, fileName.default || fileName) }; }); }; // 獲取路由文件 export const vueRouters = () => { const routerList: any = []; const requireRouters = getComponent(); requireRouters.keys().forEach((fileSrc: string) => { // 獲取 components 文件下的文件名 const viewSrc = requireRouters(fileSrc); console.log(viewSrc); const file = viewSrc.default.options; // 首字母轉大寫 const vueRouterUpper = viewToUpperCase(file.name); // 首字母轉小寫 const vueRouterLower = viewToLowerCase(file.name); // 設置路由路勁 const fileNameSrc = fileSrc.replace(/^\.\//, ''); // 是否自動注冊路由依據每個文件里的 isRouter 屬性 避免注冊不用的路由 if (viewSrc.default.isRouter) { // 注冊路由 routerList.push({ path: `/${vueRouterLower}`, name: `${vueRouterUpper}`, component: () => import(`@/views/${fileNameSrc}`), }); } }); console.log(routerList); return routerList; };
vue 文件修改為

<script lang="ts"> import Button from '@/components/Button.vue'; import { Component, Prop, Vue } from 'vue-property-decorator'; @Component({ name: 'About', components: { Button }, }) export default class About extends Vue { static isRouter = true; // tslint:disable-line static isComponent = true; // tslint:disable-line private handleClick() { console.log('button'); } } </script>
require.context()
獲取文件對象:
1. javascript
2. typescript 版本
react 版本不同的只是 模板文件不同,有需要的朋友可以留言我
有不對之處及有更好的方法歡迎留言指正