Vue/React如何優雅的一勞永逸的注冊路由及組件


原文鏈接: 本人掘金文章  假如圖片看不清晰可前往掘金原文預覽

官方文檔: 組建注冊 路由注冊

未優化版: 在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函數接收三個參數:

  1. 要搜索的文件夾目錄
  2. 是否還應該搜索它的子目錄
  3. 以及一個匹配文件的正則表達式

一、先把我的目錄結構及文件組成貼出來 (這是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 版本不同的只是 模板文件不同,有需要的朋友可以留言我
有不對之處及有更好的方法歡迎留言指正

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM