原文链接: 本人博客园文章
未优化版: 在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.context函数接收三个参数:
- 要搜索的文件夹目录
- 是否还应该搜索它的子目录
- 以及一个匹配文件的正则表达式
一、先把我的目录结构及文件组成贴出来 (这是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;
};
引入方式
二、这是vue3.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() 获取文件对象:
javascript版本typescript版本
react 版本不同的只是 模板文件不同,有需要的朋友可以留言我
有不对之处及有更好的方法欢迎留言指正