虽然,相比于React、angular、Knockout等框架,Vue.js起步较晚,但是,它集成了大量其他框架的优点,目前已经成为目前广泛应用的一个前端框架。在他的社区,也活跃着大量的第三方插件。
不过,偶尔我们也会用到原生的javascript库或者插件。如何在Vue.js框架中引入这些非Vue库或插件呢?笔者认为主要有以下两种方式:
第一种,利用Vue提供的生命周期钩子函数,在不同时期引入原生js代码。Vue实例生命周期如图:
第二种,将第三方库或插件封装为Vue插件。具体如何实现呢?当你了解了Vue插件的编写方式之后,自然会明白。
这里,官网给出了很全面的介绍以及代码框架。
插件通常会为 Vue 添加全局功能。插件的范围没有限制——一般有下面几种:
1. 添加全局方法或者属性,如: vue-custom-element
2. 添加全局资源:指令/过滤器/过渡等,如 vue-touch
3. 通过全局 mixin 方法添加一些组件选项,如: vue-router
4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能,如 vue-router
官网给的代码框架如下:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
官网给出了4种编写插件的方式。接下来,我们来尝试编写插件。
在我看来,Vue插件只是对原生javascript代码或Vue组件的简单封装,从而用以替换利用Vue实例生命周期钩子函数调用原生javascript代码的方式。以下是几种编写Vue插件的方式的实例。
编写一个Vue单页组件。
<template>
<div class="Hello-box" v-show="show">
<p>Hello<p>
<h1>{{text}}h1>
div>
template>
<script>
export default {
props: {
show: Boolean,
text: {
type: String,
default: 'Wait a time...'
}
}
}
script>
<style>
p{
font-size: 28px;
text-align: center;
}
h1 {
text-align: center;
}
style>
对组件进行封装,并添加全局属性:
// sayhello.js
import SayHello from './sayhello.vue'
let $vm
export default {
install (Vue, options) {
if (!$vm) {
const SayHelloPlugin = Vue.extend(SayHello)
$vm = new SayHelloPlugin({
el: document.createElement('div')
})
document.body.appendChild($vm.$el)
}
$vm.show = false
let sayhello = {
show (text) {
$vm.show = true
$vm.text = text
},
hide () {
$vm.show = false
}
}
if (!Vue.$sayhello) {
Vue.$sayhello = sayhello
}
}
}
在这个这个插件种,我们为组件增加了设置和隐藏text
的功能。通过show
和hide
函数完成,他们被封装在sayhello
中。通过下面这句语句设置全局属性:
Vue.$sayhello = sayhello
我们来测试这个以下这个插件。由于.vue文件需要编译,我们使用vue-cli脚手架工具来测试:
//App.vue
<template>
<div id="app">
- A Smiple Demo -
div>
template>
<script>
import SayHello from './components/plugin/sayhello.js'
import Vue from 'vue'
Vue.use(SayHello)
export default {
name: 'App',
mounted () {
Vue.$sayhello.show('Friend')
}
}
script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
style>
//main.js
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: ' '
})
添加全局资源包含了添加全局的指令/过滤器/过渡等,这种方式通过Vue.directive实现。假如我们有一个focus插件,它获取某个元素的焦点,则可以通过以下方式实现:
//focus.js
export default {
install(Vue, options) {
Vue.directive('focus', {
bind: function() {},
// 当绑定元素插入到 DOM 中。
inserted: function(el, binding, vnode, oldVnode) {
// 聚焦元素
el.focus();
},
update: function() {},
componentUpdated: function() {},
unbind: function() {}
});
},
}
调用方式:
<template>
<input v-focus>
template>
<script>
import Focus from './components/plugin/focus.js'
Vue.use(Focus)
这样,在input挂载在DOM中时,便会自动获取焦点。
Vue.directive包括5个函数,分别在不同的生命周期阶段调用。具体可以查看:自定义指令
附:说说VNode节点(Vue.js实现)
这一种方式的实现可以通过调用Vue.mixin。混合 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混合对象可以包含任意组件选项。当组件使用混合对象时,所有混合对象的选项将被混入该组件本身的选项。
也就是说,假设定义一个混合对象example,当一个组件test使用混合对象example时,test将拥有example的所有选项。
修改1. 添加全局方法或属性
中sayhello.js
中的代码,修改结果如下:
// sayhello.js
import SayHello from './sayhello.vue'
let $vm
export default {
install (Vue, options) {
if (!$vm) {
const SayHelloPlugin = Vue.extend(SayHello)
$vm = new SayHelloPlugin({
el: document.createElement('div')
})
document.body.appendChild($vm.$el)
}
$vm.show = false
let sayhello = {
show (text) {
$vm.show = true
$vm.text = text
},
hide () {
$vm.show = false
}
}
// 以下为修改部分
// if (!Vue.$sayhello) {
// Vue.$sayhello = sayhello
// }
Vue.mixin({
created () {
this.$sayhello = sayhello
}
})
}
}
调用方式同样改变:
//App.vue
//将
Vue.$sayhello.show()
//修改为
this.$sayhello.show()
在混合(mixin)中,你可使用的选项基本上包括Vue创建实例时的所有选项。
这种方式,只需要把你要暴露的方法、变量等添加到Vue.prototype上即可。
具体可以修改demo如下:
// sayhello.js
import SayHello from './sayhello.vue'
let $vm
export default {
install (Vue, options) {
if (!$vm) {
const SayHelloPlugin = Vue.extend(SayHello)
$vm = new SayHelloPlugin({
el: document.createElement('div')
})
document.body.appendChild($vm.$el)
}
$vm.show = false
let sayhello = {
show (text) {
$vm.show = true
$vm.text = text
},
hide () {
$vm.show = false
}
}
// 以下为修改部分
// if (!Vue.$sayhello) {
// Vue.$sayhello = sayhello
// }
// Vue.mixin({
// created () {
// this.$sayhello = sayhello
// }
// })
Vue.prototype.$sayhello = sayhello
}
}
至此,4种编写插件的方式都已经介绍完毕。当然,正如官网所述的那样,每种方式并非独立的,需要根据自己的需求,选择一种或多种方式编写插件。
demo网址:https://github.com/kangbb/plugin-demo