用插件的方式注入Vue组件

在写Vue的时候,我们总是会有很多组件,在页面需要的时候就引进了,这时候会有一个问题,就是不同的文件目录下引入文件的路径不同,虽说可以通过alias配置路径识别符,但是每次都这么频繁引入也是挺麻烦的,尤其是在Vue2里,引入了还要再components里再声明一次。 在Vue技术栈开发过程中,面对复杂项目中的组件复用场景,存在两个显著的工程化痛点:

其一,跨层级模块引用时的路径冗余问题,虽可通过Webpack别名(alias)进行路径映射优化,但在高频组件引用场景下仍存在编码冗余;

其二,在Vue2架构中基于Options API的显式组件注册机制,导致组件管理存在重复声明成本。

一、方法

这种双重约束在大型项目迭代中会显著增加维护复杂度,需通过模块化设计和工程化方案进行系统性优化。有一种比较好解决方法,利用插件的方式动态导入:

javascript 复制代码
// 直接引入所有的组件,相当于自己的组件库
import errorTip from './errorTip'
import emailTip from './emailTip'
import steps from './steps'
import confirmPw from './confirmPw'
import accountInput from './accountInput'
import aiInput from './input'
import validateInput from './validateInput'
import graphicalCode from './graphicalCode'
import inviteCode from './inviteCode'
import baValidateInput from './baValidateInput'
import aiButton from './aiButton'
import msgcode from './msgcode'
var Components = {
    errorTip,
    emailTip,
    steps,
    confirmPw,
    accountInput,
    aiInput,
    validateInput,
    graphicalCode,
    inviteCode,
    baValidateInput,
    aiButton,
    msgcode
}

// 插件
var Plugins = {}

export default function install(Vue) {
    var componentFlags = Vue.util.mergeOptions(flatObj(Components), flatObj(Plugins))
    Vue.mixin({
        beforeCreate(){
            aicomponentInit.call(this)
        }
    })
    function aicomponentInit() {
        var aicomponents = this.$options.aicomponents,
            components = [];

        if (aicomponents) {
            components = aicomponents.forEach((key) => {
                var component = componentFlags[key]
                if (component) {
                    inject.call(this, component, key)
                    return
                }
                console.warn(`未发现组件:${key}`)
            })
        }
        
        function inject(component, key) {
            key = key.split('_')[0]

            if (component.render) {
                this.$options.components[key] = Vue.extend(component)
                // console.log(component)
            } else if (component.install) {
                this['$' + key] = component.install(Vue)
                    // console.log(this['$'+key],'$'+key)
            } else {
                Object.keys(component).forEach((k) => {
                    inject.call(this, component[k], k)
                })
            }
        }
    }
}


function realComponent(data, k, version, type) {
    var temp,
        version = version || '',
        type = type || ''

    if (data[k].render || data[k].install) {
        temp = {
            name: k,
            val: data[k],
            version: version,
            type: type
        }
    } else {
        type = k.split('_')[0] || '',
        version = k.split('_')[1] || ''
        temp = Object.keys(data[k]).reduce((arr, key) => {
            return arr.concat(realComponent(data[k], key, version, type))
        }, [])
    }
    return temp
}

function flatObj(foldData) {
    var content = {}
    Object.keys(foldData).reduce(function(arr, k) {
        return arr.concat(realComponent(foldData, k))
    }, []).forEach(function(item) {
        // console.log(item)
        if (item.version) {
            content[item.type + '_' + item.version] = content[item.type + '_' + item.version] || {}
            content[item.type + '_' + item.version][item.name] = item.val
        } else {
            content[item.name] = item.val
        }
    })

    return content
}
javascript 复制代码
import components from './components'
import App from './pages/app.vue'

Vue.use(components)

export function render(store,router){
    const vue = new Vue({
        el:'#app',
        store:store,
        router:router,
        render: h => h(App)
    })
}

都做好准备了,看看怎么用:

  1. 在export中添加了一个aicomponents对象,把需要用到的组件名写进去,比如errorTip;
  2. 然后在页面中就可以正常使用了;
  3. 如果有新增一些通用性较小的组件,同样可以像vue原方法那样,写到components中。
xml 复制代码
<template>
  <div>
    <errorTip :visible="topError.show" :txt="topError.txt" type="error"></errorTip>
    <div class="">
      <account-input
        ref="account"
        fontClass=""
        autoComplete="off"
        :checkRepeat="false"
        @input="account_input"
        :account.sync="account"
        :valid.sync="accountValid"
      ></account-input>
    </div>
    <div class="pt15">
      <validateInput
        ref="pw"
        :isValid.sync="pwValid"
        :value.sync="passWord"
        :ruleList="pw_rule_list"
        autoComplete="off"
        placeholder="密码"
      ></validateInput>
    </div>
  </div>
</template>

<script>
import bindMobile from './bindMobile.vue';

export default {
  aicomponents: ['emailTip', 'errorTip', 'accountInput', 'aiInput', 'validateInput'],
  props: {
    topError: {
      type: Object,
      default: () => ({ show: false, txt: '' })
    }
  },
  created() {
    // 组件创建
  },
  data() {
    return {
      confirm_password_show: false, // 确认密码错误显示
      confirm_password_txt: '', // 确认密码错误提示
      // 其他数据属性可以在这里添加
    };
  },
  methods: {
    loadVerifyCode() {
      Service.$model.account.get_verify_code({
        captchaType: "RANDOM_LETTER"
      }).then((response) => {
        this.verify_img_url = "data:image/png;base64," + response.data.image;
        this.captchaKey = response.data.captchaKey;
      });
    },
    // 其他方法可以在这里添加
  },
  components: {
    bindMobile
    // 其他组件可以在这里添加
  }
};
</script>

二、插件式组件的好处

  • 无需重复导入 :插件可以一次性全局注册组件,避免在每个使用组件的文件中手动 import
  • 直接使用标签 :注册后,组件可像原生 HTML 标签一样使用(如 <my-component>),提升开发效率。
  • 统一配置:插件可以集中处理组件的依赖、默认属性或全局逻辑(如国际化、权限控制)
  • 注入全局功能:插件不仅能注册组件,还能添加全局方法、指令、混入(mixins)或原型属性。

三、适用场景

  • UI 库开发:如按需引入的组件库。
  • 功能模块:如全局的权限校验、埋点统计插件。
  • 复杂初始化:需要全局配置或依赖注入的组件。

原文连接:用插件的方式注入Vue组件 | 1Z5K

相关推荐
掘金安东尼6 小时前
Node.js 如何在 2025 年挤压 I/O 性能
前端·javascript·github
跟橙姐学代码6 小时前
Python异常处理:告别程序崩溃,让代码更优雅!
前端·python·ipython
niuhuahua6 小时前
大屏拖拽功能,配合ai组件使用,配合各个组件都可使用
前端
得物技术7 小时前
前端日志回捞系统的性能优化实践|得物技术
前端·javascript·性能优化
陶甜也7 小时前
threeJS 实现开花的效果
前端·vue·blender·threejs
用户7678797737327 小时前
后端转全栈之Next.js 路由系统App Router
前端·next.js
OEC小胖胖7 小时前
Next.js数据获取入门:`getStaticProps` 与 `getServerSideProps`
前端·前端框架·web·next.js
等什么君!7 小时前
如何 正确使用 nrm 工具 管理镜像源
vue.js
warder7 小时前
字典状态管理:基于 Vue3 + Pinia 的工程化实践
vue.js