在vue2的环境下封装自己的组件库
a、初始化项目
vue环境的安装
npm i @vue/cli -g
vue create yutest-ui --也可以通过vue ui创建,创建一个默认的vue2库即可
因为需要开发组件库,那么就需要对原有的目录结构作些调整
---将src目录变更为examples文件夹
---在examples的同级目录下新建文件夹packages文件夹
---添加vue.config.js文件,需要对原有的配置作一些调整具体调整如下
vue.config.js的内容如下
module.exports = { pages: { index: { entry: 'examples/main.js', template: 'public/index.html', filename: 'index.html' } }, // 扩展 webpack 配置,使 packages 加入编译 chainWebpack: config => { config.module .rule('js') .include .add('/packages') .end() .use('babel') .loader('babel-loader') .tap(options => options) } }
注意:以上内容把编译的入口作了调整,由原来的src变为examples,声明template的路径,同时把packages加入编译
b、编写组件
packages/Button/src/index.vue
<template> <div class="x-button"> <slot></slot> </div> </template> <script> export default { name: 'XButton', //注意,这里需要用的驼峰命名,尽量不要使用-拼接,方便后面组件的调用 props: { type: String } } </script> <style scoped> .x-button { display: inline-block; padding: 3px 6px; background: #000; color: #fff; } </style>
packages/Button/index.js
// 导入组件,组件必须声明 name import XButton from './src' // 为组件提供 install 安装方法,供按需引入 XButton.install = function (Vue) { Vue.component(XButton.name, XButton) } // 导出组件 export default XButton
注意:在组件中packages/Button/index.js可以省略,如果是组件库,直接是Button / index.vue即可, 这样一个简单的组件就开发完成了
c、实现组件的入口文件
package/index.js
// 导入button组件 import XButton from './Button' // 组件列表 const components = [ XButton ] // 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,那么所有的组件都会被注册 const install = function (Vue) { // 判断是否安装 if (install.installed) return // 遍历注册全局组件 components.forEach(component => Vue.component(component.name, component)) install.installed = true; } // 判断是否是直接引入文件 if (typeof window !== 'undefined' && window.Vue) { install(window.Vue) } export { XButton //局部引用 } export default install //全局引用
d、测试代码
在examples/main.js
import Vue from 'vue' import App from './App.vue' import yutest_ui from '../packages' Vue.config.productionTip = false Vue.use(yutest_ui) new Vue({ render: h => h(App), }).$mount('#app')
进行全局引入后就可以进行使用测试了,也可以不用全局引入进行局部引入 import { XButton } from '../../packages' 然后组件注册后进行使用
e、配置package.json文件
vue-cli-service build --target lib --name myLib [entry]
注意:需要添加main字段
f、添加.npmignore文件
这个文件相当是忽略指定的文件,不上传到npm上,写法类似.gitignore
examples/ node_modules/ packages/ public/ .gitignore babel.config.js vue.config.js *.map
g、后续工作
npm run lib //进行构建项目 npm login npm publish
注意:在npm login的时候需要的源从淘宝镜像切换到npm上,并且使用已有的npm账号,这个账号是已经用邮箱验证过了的,否则发布会失败
vue3环境下的插件的编写
在vue3环境下的插件编写与vue2的插件编写大体一致,但是vue3对use这个方法做了一些微调整,所以上面插件的写法只需要调整packages里的index.js的入口文件即可
<script> const myPlugin = { install(app, options) { // 这样就可以通过这个方法进行组件的注册 console.log(app, options) app.provide('info', options) //可以对所有的组件注入对象 // app.directive('focus') //可以进行扩展指令 // app.mixin() //可以对全局进行混入 app.config.globalProperties.$say = () => { // 对vue的全局属性进行扩展 console.log('say') } } } //当然myPlugin也可以是一个函数 // const myPlugin = (app, options) => { // // ...以上的方法 // } const app = Vue.createApp({ template: `<div>name---{{info.name}}, age---{{info.age}}</div>`, // inject: ['info'], inject: { 'info': { from: 'info', default: () => ({}) } }, created() { console.log(this) this.$say() } }) app.use(myPlugin, {name: 'bill', age: 30}) //第二个参数将会以option的形式传递给install这个方法,以第二个参数的形式存在 app.mount('#root') </script>
应用示例,利用以上方法实现一个较验器
const myPlugin = (app, options) => { app.mixin({ created() { this.ruleValidate() }, methods: { ruleValidate() { if(!this.$options.rules) return; Object.keys(this.$options.rules).forEach((val) => { this.$watch(val, current => { let result = this.$options.rules[val].validate(current); !result && console.log(this.$options.rules[val].message) }) }) } } }) } const app = Vue.createApp({ template: `<div>name---{{name}}, age---{{age}}</div>`, data() { return { name: 'bill', age: 30 } }, rules: { age: { validate: age => age < 20, message: "年龄不能超过20" }, name: { validate: name => name.length > 3, message: '名字太短' } } }) app.use(myPlugin) //第二个参数将会以option的形式传递给install这个方法,以第二个参数的形式存在 const vm = app.mount('#root')