A05-批量注册组件

🧑‍🎓 个人主页Silence Lamb
📖 本章内容:【批量注册组件


Silence-Vue v1.0.0

基于VUE前端快速开发框架

在这里插入图片描述

🍎平台简介

star star star star star star


一、批量注册组件

在这里插入图片描述

1.1🍁【批量注册组件】

  • 🍁批量注册组件src/components/index.js
/**
 * 方法从指定目录(@/components)和其子目录中加载所有 Vue.js 组件(因为第二个参数设置为 true)
 * require.context 方法来创建一个文件上下文
 * 第三个参数 (/\.vue$/) 指定我们只想加载具有 .vue 扩展名的文件
 */
const componentFiles = require.context('@/components', true, /\.vue$/)
/**
 * 注册组件
 * @param app
 */
export default (app) => {
    /*遍历componentFiles的组件*/
    componentFiles.keys().forEach(e => {
        /*.keys() 方法迭代每个文件,并使用 .default 获取从每个文件导出的默认组件*/
        const component = componentFiles(e).default
        app.component(component.name, component)
    })
}

  • 🍁全局引入src/main.js
import components from '@/components/index' // components
const app = createApp(App)
//全局批量注册组件
components(app)

1.2🍁【回到顶部组件】

  • 🍁回到顶部组件src/components/scrollToTop/index.vue
<template>
    <div class="components-container">
        <button @click="scrollToTop" v-if="showScrollTopBtn" class="scroll-top">
            <svg-icon icon-class="guide"/>
        </button>
    </div>
</template>
  
<script>
export default {
    name: 'scrollToTop',
    data() {
        return {
            showScrollTopBtn: false
        }
    },
    methods: {
        scrollToTop() {
            let scrollTopDuration = 500;
            let scrollStep = -window.scrollY / (scrollTopDuration / 15);
            let scrollInterval = setInterval(function () {
                if (window.scrollY != 0) {
                    window.scrollBy(0, scrollStep);
                } else clearInterval(scrollInterval);
            }, 15);
        }
    },
    mounted() {
        let vm = this;
        window.addEventListener("scroll", function () {
            if (window.pageYOffset > 100) {
                vm.showScrollTopBtn = true;
            } else {
                vm.showScrollTopBtn = false;
            }
        });
    }
}
</script>
  
<style lang= "scss" scoped>
.scroll-top {
    position: fixed;
    bottom: 80px;
    right: 10px;
    background-color: #799ba12e;
    color: #ffffff;
    border: none;
    padding: 16px;
    border-radius: 50%;
    z-index: 9999;
    animation: swing 2s ease-in-out 1s infinite;
    transform-origin: bottom center;
    display: flex;
}

@keyframes swing {
    0% {
        transform: rotate(0);
    }

    10% {
        transform: rotate(15deg);
    }

    20% {
        transform: rotate(-10deg);
    }

    30% {
        transform: rotate(10deg);
    }

    40% {
        transform: rotate(-5deg);
    }

    50% {
        transform: rotate(5deg);
    }

    60% {
        transform: rotate(-5deg);
    }

    70% {
        transform: rotate(0);
    }

    90% {
        transform: rotate(0);
    }

    100% {
        transform: rotate(0);
    }
}

.scroll-top:hover {
    background-color: #7fa19b;
    animation: none;
}
</style>

1.3🍁【页面使用组件】

  • 🍁页面使用组件src/views/index.vue
<template>
  <div :class="classObj" class="app-wrapper">
    <!-- 回到顶部小组件-->
    <scrollToTop/>
  </div>
</template>

🌟其他页面就无需引入组件

import scrollToTop from './components/scrollToTop/index'
components: {scrollToTop }

二、批量安装插件

  • 🌍 自定义插件src\utils\tools\token\validate.js
export default {
    /**
     * 判断是否为外部图标
     * @param {string} path
     * @returns {Boolean}
     */
    isExternal(path) {
        return /^(https?:|mailto:|tel:)/.test(path)
    },
}
  • 🌍 安装插件src\utils\plugins\index.js
const methods = require.context('./modules/', true, /\.js$/)

/**
 * 安装插件
 */
export default {
    install(app) {
        // 加载在某个目录中动态注册的所有全局方法
        methods.keys().forEach((filePath) => {
            const method = methods(filePath).default
            const fileName = getFileName(filePath)
            // 将该方法注册为 $fileName 的全局方法
            Object.keys(method).forEach((key) => {
                app.config.globalProperties['$' + fileName] = method
            })
        })
    },
}
/**
 * 获取最后一个文件夹
 * @param {string} filePath
 * @returns 子文件夹名
 */
function getFileName(filePath) {
    const matches = filePath.substring(0, filePath.lastIndexOf('/')).split('/').pop()
    return matches
}
  • 🌍 全局引入src\main.js
import { createApp } from 'vue'
import App from './App.vue'
import plugins from '@/utils/plugins/index.js' // plugins
const app = createApp(App)
app.use(plugins)
app.mount('#app')
  • 🌍 组件使用注册的方法src\views\index\index.vue
methods: {
        getMessage(event) {
            console.log(this.$validate.isExternal('http://localhost/index'))
        },
    },

三、批量引入方法

  • 🛞 方法定义格式src\utils\tools\token\index.js
import Cookies from 'js-cookie'

const TokenKey = 'Admin-Token'

/**
 * 获取Token
 * @returns  token
 */
export function getToken() {
    return Cookies.get(TokenKey)
}

/**
 * 设置Token
 * @param {*} token
 */
export function setToken(token) {
    return Cookies.set(TokenKey, token)
}

/**
 * 移除Token
 */
export function removeToken() {
    return Cookies.remove(TokenKey)
}
  • 🛞 全局引入src\utils\tools\token\index.js
const tools = require.context('./tools/', true, /\.js$/)

/**
 * 动态引入方法
 */
export default {
    install(app) {
        console.log(tools)
        var methods=tools.concat(plugins)
        // 加载在某个目录中动态注册的所有全局方法
        methods.keys().forEach((filePath) => {
            const method = methods(filePath)
            const fileName = getLastFileName(filePath)
            // 将该方法注册为 $fileName 的全局方法
            app.config.globalProperties['$' + fileName] = method
        })
    },
}
/**
 * 获取最后一个文件夹
 * @param {string} filePath
 * @returns 子文件夹名
 */
function getLastFileName(filePath) {
    const matches = filePath.substring(0, filePath.lastIndexOf('/')).split('/').pop()
    return matches
}
  • 🛞 全局引入src\main.js
import { createApp } from 'vue'
import App from './App.vue'
import utils from '@/utils/index' // utils
const app = createApp(App)
app.use(utils)
app.mount('#app')
  • 🛞 组件中使用src\main.js
methods: {
        getMessage(event) {
            console.log(this.$getToken())
        },
    }

四、组件按需导入

  • 🍜组件按需导入vue.config.js
npm install -D unplugin-vue-components
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
     configureWebpack: { 
        plugins: [
 			/* 组件按需自动导入*/
            Components({
                //引入自己的组件
                dirs: ['src/components'],
                //引入ElementPlus官方组件
                resolvers: [ElementPlusResolver()],
                dts: 'src/auto/components.d.ts',
                // 自定义规则
                libs: [
                    {
                        libraryName: 'element-plus',
                        esModule: true,
                        resolveStyle: (name) => {
                            return `element-plus/lib/theme-chalk/${name}.scss`
                        },
                    },
                ],
            }),
        ]
     }
  • 🍜 会自动生成:src\auto\components.d.ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'

export {}

declare module '@vue/runtime-core' {
  export interface GlobalComponents {
    ....
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
  }
}


五、依赖自动导入

  • 🍖可自动导入使用到的vue、vue-router等依赖
  • 🍖依赖自动导入vue.config.js
npm install -D unplugin-auto-import
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  // ...
  plugins: [
    /* 依赖自动按需导入*/
    AutoImport({
      //解决ElemenPlus消息提示框导入问题
      resolvers: [ElementPlusResolver()],
      imports: ['vue', 'vue-router', 'vuex', '@vueuse/head'],
      // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
      dts: 'src/auto/auto-import.d.ts',
   }),
  ]
})
  • 🍖会自动生成:src\auto\auto-import.d.ts
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-auto-import
export {}
declare global {
  const EffectScope: typeof import('vue')['EffectScope']
  const ElLoading: typeof import('element-plus/es')['ElLoading']
  const ElMessage: typeof import('element-plus/es')['ElMessage']
  const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
  const ElNotification: typeof import('element-plus/es')['ElNotification']
  const computed: typeof import('vue')['computed']
  const createApp: typeof import('vue')['createApp']
  const createLogger: typeof import('vuex')['createLogger']
  const createNamespacedHelpers: typeof import('vuex')['createNamespacedHelpers']
  const createStore: typeof import('vuex')['createStore']
  const customRef: typeof import('vue')['customRef']
  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
  const defineComponent: typeof import('vue')['defineComponent']
  const effectScope: typeof import('vue')['effectScope']
  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
  const getCurrentScope: typeof import('vue')['getCurrentScope']
  const h: typeof import('vue')['h']
  const inject: typeof import('vue')['inject']
  const isProxy: typeof import('vue')['isProxy']
  const isReactive: typeof import('vue')['isReactive']
  const isReadonly: typeof import('vue')['isReadonly']
  const isRef: typeof import('vue')['isRef']
  const mapActions: typeof import('vuex')['mapActions']
  const mapGetters: typeof import('vuex')['mapGetters']
  const mapMutations: typeof import('vuex')['mapMutations']
  const mapState: typeof import('vuex')['mapState']
  const markRaw: typeof import('vue')['markRaw']
  const nextTick: typeof import('vue')['nextTick']
  const onActivated: typeof import('vue')['onActivated']
  const onBeforeMount: typeof import('vue')['onBeforeMount']
  const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
  const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
  const onDeactivated: typeof import('vue')['onDeactivated']
  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
  const onMounted: typeof import('vue')['onMounted']
  const onRenderTracked: typeof import('vue')['onRenderTracked']
  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
  const onScopeDispose: typeof import('vue')['onScopeDispose']
  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
  const onUnmounted: typeof import('vue')['onUnmounted']
  const onUpdated: typeof import('vue')['onUpdated']
  const provide: typeof import('vue')['provide']
  const reactive: typeof import('vue')['reactive']
  const readonly: typeof import('vue')['readonly']
  const ref: typeof import('vue')['ref']
  const resolveComponent: typeof import('vue')['resolveComponent']
  const shallowReactive: typeof import('vue')['shallowReactive']
  const shallowReadonly: typeof import('vue')['shallowReadonly']
  const shallowRef: typeof import('vue')['shallowRef']
  const toRaw: typeof import('vue')['toRaw']
  const toRef: typeof import('vue')['toRef']
  const toRefs: typeof import('vue')['toRefs']
  const triggerRef: typeof import('vue')['triggerRef']
  const unref: typeof import('vue')['unref']
  const useAttrs: typeof import('vue')['useAttrs']
  const useCssModule: typeof import('vue')['useCssModule']
  const useCssVars: typeof import('vue')['useCssVars']
  const useHead: typeof import('@vueuse/head')['useHead']
  const useLink: typeof import('vue-router')['useLink']
  const useRoute: typeof import('vue-router')['useRoute']
  const useRouter: typeof import('vue-router')['useRouter']
  const useSlots: typeof import('vue')['useSlots']
  const useStore: typeof import('vuex')['useStore']
  const watch: typeof import('vue')['watch']
  const watchEffect: typeof import('vue')['watchEffect']
  const watchPostEffect: typeof import('vue')['watchPostEffect']
  const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
  // @ts-ignore
  export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue'
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Silence Lamb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值