一文读懂Vue插件使用
- 插件
- 使用插件Vue.use()
- 开发插件
- Vue项目中应用
- 配合require.context,动态导入全局组件
- Vue项目中引入elementUi组件(全局)
- 推荐阅读
插件
插件
通常用来为 Vue 添加全局功能
。插件的功能范围没有严格的限制——一般有下面几种:
添加全局方法或者 property
。如:vue-custom-element添加全局资源
:指令/过滤器/过渡等。如 vue-touch- 通过
全局混入
来添加一些组件选项。如 vue-router 添加 Vue 实例方法
,通过把它们添加到Vue.prototype
上实现。
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
使用插件Vue.use()
通过全局方法 Vue.use()
使用插件。它需要在你调用 new Vue() 启动应用之前完成
:
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...组件选项
})
也可以传入一个可选的选项对象
:
Vue.use(MyPlugin, { someOption: true })
Vue.use
会自动阻止多次注册相同插件
,届时即使多次调用也只会注册一次该插件。
Vue.js 官方
提供的一些插件 (例如vue-router
) 在检测到 Vue 是可访问的全局变量时会自动调用 Vue.use()
。
然而在像 CommonJS 这样的模块环境中,你应该始终显式地调用 Vue.use()
:
// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)
awesome-vue 集合了大量由社区贡献的插件和库。
开发插件
Vue.js 的插件应该暴露一个 install 方法
。这个方法的第一个参数
是 Vue 构造器
,第二个参数是一个可选的选项对象:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
Vue项目中应用
配合require.context,动态导入全局组件
目录结构如下
src\components\common\index.js
暴露install方法
export default {
install(Vue) {
const ctxRequire = require.context('@/components/common', false, /\.vue$/)
debugger
console.log('ctxRequire:', ctxRequire)
// console.log('ctxRequire.resolve():', ctxRequire.resolve())
console.log('ctxRequire.keys:', ctxRequire.keys())
console.log('ctxRequire.id:', ctxRequire.id)
ctxRequire.keys().forEach((filePath) => {
const fileName = filePath.replace(/(.*\/)*([^.]+).vue$/ig, '$2') // 获取Vue组件文件名
// "./breadcrumb.vue".replace(/(.*\/)*([^.]+).vue$/ig, '$2') 返回breadcrumb
Vue.component(fileName, ctxRequire(filePath).default || ctxRequire(filePath))
})
}
}
打印如下
控制台点击ctxRequire
打印的内容,会跳到源码页面,源码如下
var map = {
"./VTitle.vue": "./src/components/common/VTitle.vue",
"./breadcrumb.vue": "./src/components/common/breadcrumb.vue",
"./common-title.vue": "./src/components/common/common-title.vue",
"./custom-switch.vue": "./src/components/common/custom-switch.vue",
"./file-list.vue": "./src/components/common/file-list.vue",
"./more-button.vue": "./src/components/common/more-button.vue",
"./nodata.vue": "./src/components/common/nodata.vue",
"./pagination.vue": "./src/components/common/pagination.vue",
"./previewDialog.vue": "./src/components/common/previewDialog.vue",
"./server-type.vue": "./src/components/common/server-type.vue",
"./step-nav.vue": "./src/components/common/step-nav.vue",
"./svg-icon.vue": "./src/components/common/svg-icon.vue",
"./tags.vue": "./src/components/common/tags.vue",
"./upload-img.vue": "./src/components/common/upload-img.vue",
"./upload-imgs.vue": "./src/components/common/upload-imgs.vue"
};
function webpackContext(req) {
var id = webpackContextResolve(req);
return __webpack_require__(id);
}
function webpackContextResolve(req) {
if(!__webpack_require__.o(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return map[req];
}
webpackContext.keys = function webpackContextKeys() {
return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = "./src/components/common sync \\.vue$";
src\plugins\common.js
import Vue from 'vue'
import commonComps from '../components/common/index'
Vue.use(commonComps) // 会执行commonComps的install方法
src\main.js
import './plugins/common'
...
这样后,就可以在Vue任意地方用这些全局组件,不需要另外注册
PS:ctxRequire(filePath).default || ctxRequire(filePath)
相当于import
进来的模块,假如filePath
的值是"./breadcrumb.vue"
等同于import breadcrumb from './breadcrumb.vue'
import breadcrumb from './breadcrumb.vue'
export default {
install(Vue) {
const ctxRequire = require.context('@/components/common', false, /\.vue$/)
ctxRequire.keys().forEach((filePath) => {
const fileName = filePath.replace(/(.*\/)*([^.]+).vue$/ig, '$2') // 获取Vue组件文件名
if (fileName === 'breadcrumb') {
console.log('breadcrumb:', breadcrumb)
console.log(ctxRequire(filePath).default || ctxRequire(filePath))
console.log(breadcrumb === (ctxRequire(filePath).default || ctxRequire(filePath))) // true
}
console.log('ctxRequire(filePath):', ctxRequire(filePath))
Vue.component(fileName, ctxRequire(filePath).default || ctxRequire(filePath))
})
}
}
打印如下
Vue项目中引入elementUi组件(全局)
src\plugins\element-ui.js
import Vue from 'vue'
// https://element.eleme.cn/#/zh-CN/component/quickstart
import {
Input,
Button,
Form,
FormItem,
Cascader,
Dialog,
Menu,
MenuItem,
MenuItemGroup,
Submenu,
Upload,
Breadcrumb,
BreadcrumbItem,
Dropdown,
DropdownMenu,
DropdownItem,
DatePicker,
Message,
MessageBox,
Notification,
Badge,
Popover,
Select,
Option,
Carousel,
CarouselItem,
Loading,
Radio,
RadioGroup,
RadioButton,
Table,
TableColumn,
Pagination,
Row,
Col,
Card,
Switch,
Image,
InfiniteScroll,
Alert,
Tooltip,
Divider,
Tree,
Checkbox,
CheckboxGroup,
Step,
Steps,
Tabs,
TabPane
} from 'element-ui'
Vue.prototype.$ELEMENT = { size: 'small' }
Vue.use(Divider)
Vue.use(Input)
Vue.use(Button)
Vue.use(Cascader)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Dropdown)
Vue.use(DropdownMenu)
Vue.use(DropdownItem)
Vue.use(Dialog)
Vue.use(Menu)
Vue.use(MenuItem)
Vue.use(Submenu)
Vue.use(MenuItemGroup)
Vue.use(Upload)
Vue.use(Breadcrumb)
Vue.use(BreadcrumbItem)
Vue.use(DatePicker)
Vue.use(Badge)
Vue.use(Popover)
Vue.use(Select)
Vue.use(Option)
Vue.use(Carousel)
Vue.use(CarouselItem)
Vue.use(Radio)
Vue.use(RadioGroup)
Vue.use(RadioButton)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Pagination)
Vue.use(Row)
Vue.use(Col)
Vue.use(Card)
Vue.use(Switch)
Vue.use(Image)
Vue.use(Alert)
Vue.use(Tooltip)
Vue.use(Tree)
Vue.use(Checkbox)
Vue.use(CheckboxGroup)
Vue.use(InfiniteScroll)
Vue.use(Loading.directive)
Vue.use(Step)
Vue.use(Steps)
Vue.use(Tabs)
Vue.use(TabPane)
Vue.prototype.$message = Message
Vue.prototype.$notify = Notification
Vue.prototype.$confirm = MessageBox.confirm
src\main.js 引入该文件
// ...
import './plugins/element-ui'
启动项目后 就可以直接在Vue组件里使用element组件了