zoukankan      html  css  js  c++  java
  • 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 版本不同的只是 模板文件不同,有需要的朋友可以留言我
    有不对之处及有更好的方法欢迎留言指正
  • 相关阅读:
    最实用的logback讲解(2)—appender
    深入理解lombok
    idea(三)最值得安装的几款插件
    idea(二)初次安装强烈建议修改的配置
    swagger2的使用和swagger2markup离线文档的生成(最简单的方式)
    maven(一) 基础知识
    maven(二)pom文件详解
    ubuntu下jdk的安装
    maven(三)最详细的profile的使用
    profile之springboot
  • 原文地址:https://www.cnblogs.com/ljx20180807/p/11720796.html
Copyright © 2011-2022 走看看