插件通常用来为 Vue 添加全局功能,一般有下面几种:
- 添加全局方法或者属性。
- 添加全局资源:指令/过滤器/过渡等。
- 通过全局混入来添加一些组件选项。
- 添加 Vue 实例方法,通过把它们添加到
Vue.prototype
上实现。 - 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。
更加详细说明查看官网文档 https://cn.vuejs.org/v2/guide...
开发插件
1.简单的插件
创建一个countdown.vue
<template>
<div>封装一个最简单的插件</div>
</template>
<script>
export default {
name: 'count-down'
}
</script>
创建一个index.js
import countDown from './countdown';
//暴露一个 `install` 方法。这个方法的第一个参数是 `Vue` 构造器,第二个参数是一个可选的选项对象
countDown.install = function (Vue) {
Vue.component(countDown.name, countDown);
};
export default countDown;
目录结构为:
在main.js中引入,页面中<count-down></count-down>
就可以使用
import countDown from './components/global/index';
//通过全局方法 `Vue.use()` 使用插件
Vue.use(countDown);
2.添加全局方法或属性
countDown.install = function (Vue) {
Vue.prototype.$msg = '全局的属性';
Vue.prototype.$myMethod = function () {
console.log('全局定义的方法');
}
Vue.component(countDown.name, countDown);
};
3.添加全局资源
countDown.install = function (Vue) {
//全局自定义指令
Vue.directive('focus', {
//当节点插入的时候
inserted: function (el) {
el.focus();
}
})
Vue.component(countDown.name, countDown);
};
4.注入组件选项
countDown.install = function (Vue) {
//全局混入
Vue.mixin({
created() {
console.log('i am jello')
},
})
Vue.component(countDown.name, countDown);
};
开发插件进阶
创建一个VsButton.vue
<template>
<button class="vs-button" :class="type" @click="fn">
<slot></slot>
</button>
</template>
<script>
export default {
name: 'VsButton',
props: {
type: {
type: String,
default: 'warning'
}
},
methods: {
fn() {
this.$emit('click');
}
},
}
</script>
<style lang='less' scoped>
.vs-button {
width: 100px;
height: 40px;
background: #ccc;
border-radius: 4px;
}
.warning {
background: yellow
}
.danger {
background: red
}
.success {
background: green
}
</style>
创建VsMsg.vue
<template>
<transition name="fade">
<div class='vs-msg' v-show='visible'>
<img src='../../../assets/msg.png' class='pic' />
<span class='msg-text' @click='close'>
<slot></slot>
</span>
</div>
</transition>
</template>
<script>
export default {
name: 'VsMsg',
props: {
visible: {
type: Boolean,
default: false
}
},
methods: {
close() {
this.$emit('update:visible', false);
}
},
}
</script>
<style lang='less' scoped>
.vs-msg {
width: 330px;
min-height: 280px;
display: flex;
flex-direction: column;
padding: 30px;
background: #eee;
.pic {
width: 100%;
height: 200px;
}
.msg-text {
height: 80px;
line-height: 80px;
background: rgba(255, 255, 255, 1);
border-radius: 0px 0px 10px 10px;
font-size: 16px;
color: rgba(255, 162, 26, 1);
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .3s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
创建一个index.js
import VsMsg from '../plugins/msg/VsMsg';
import VsButton from '../plugins/button/VsButton';
let plugin = {};
plugin.install = function (Vue) {
Vue.component(VsMsg.name, VsMsg);
Vue.component(VsButton.name, VsButton);
}
export default plugin;
每次使用都需要import和Vue.component(),可采用webpack的require.context(),实现自动导入和注册组件。
1)require.context函数接受三个参数:
- directory {String} -读取文件的路径
- useSubdirectories {Boolean} -是否遍历文件的子目录
- regExp {RegExp} -匹配文件的正则
2)require.context函数执行后返回的是一个函数,并且这个函数有3个属性
- resolve {Function} -接受一个参数request,request为test文件夹下面匹配文件的相对路径,返回这个匹配文件相对于整个工程的相对路径
- keys {Function} -返回匹配成功模块的名字组成的数组
- id {String} -执行环境的id,返回的是一个字符串,主要用在module.hot.accept
const requireComponent = require.context('./', true, /\.vue$/); //获取一个特定的上下文,主要用来实现自动化导入模块
const install = (Vue) => {
if (install.installed) return;
install.installed;
requireComponent.keys().forEach(fileName => {
//第i个组件
const config = requireComponent(fileName);
//组件名
const componentName = config.default.name;
Vue.component(componentName, config.default || config);
})
}
//检测环境
if (typeof window !== undefined && window.Vue) {
install(Vue);
}
export default install;
在main.js中引入
import index from "./components/plugins/index.js";
Vue.use(index);
页面中使用插件
<template>
<VsButton type='warning' @click="open">默认按钮</VsButton>
<VsMsg :visible.sync="visible">我是一个消息</VsMsg>
</template>
<script>
export default {
data() {
return {
visible: false
},
methods: {
open() {
this.visible = true;
}
}
}
</script>
实现效果如下:
上传npm
1.vue-cli 3.x 提供了一个构建库文件打包命令
主要需要四个参数:
- target: 默认为构建应用,改为 lib 即可启用构建库模式
- name: 输出文件名
- dest: 输出目录,默认为 dist,这里我们改为 lib
- entry: 入口文件路径,默认为 src/App.vue
在 package.json 里的 scripts 添加一个 lib 命令
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lib": "vue-cli-service build --target lib --name vue-plugins-msg-jello --dest lib src/components/plugins/index.js"
},
然后执行 npm run lib 命令,编译组件
2.发布前需要在 package.json 添加组件信息:
- name: 包名,该名不能和已有的名称冲突
- version: 版本号,不能和历史版本号相同
- description: 简介
- main: 入口文件,应指向编译后的包文件
- keyword:关键字,以空格分割
- author:作者
- private:是否私有,需要修改为 false 才能发布到 npm
- license:开源协议
"name": "vue-plugins-msg-jello",
"version": "0.1.0",
"private": false,
"license": "MIT",
"main": "lib/vue-plugins-msg-jello.umd.min.js",
然后创建 .npmignore 文件,设置忽略文件,该文件的语法和 .gitignore 的语法一样,设置发布到 npm 时忽略哪些目录或文件
.DS_Store
node_modules/
examples/
packages/
public/
vue.config.js
babel.config.js
*.map
*.html
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
3.发布到npm
若以前改过 npm 的镜像地址,比如使用了淘宝镜像,就先改回来npm config set registry http://registry.npmjs.org
没有 npm 账户,可以通过 npm adduser 命令创建一个账户,或者到 npm 官网注册,具体流程可以参考官方文档
使用 npm login 命令登录,发布时遇到
去邮箱认证后,再继续npm publish
发布npm后插件使用
1)安装
npm i vue-plugins-msg-jello --save
2)main.js引入注册插件
import msg from 'vue-plugins-msg-jello'
import '../node_modules/vue-plugins-msg-jello/lib/vue-plugins-msg-jello.css'
Vue.use(msg)
3)页面使用
<template>
<div class="about">
<VsButton type="danger">危险按钮</VsButton>
<VsButton type="warning">警告按钮</VsButton>
</div>
</template>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。