很差意思通過了這麼久時間纔開始繼續寫文章,確實懶散了好久。廢話很少說,開始本文吧。css
本篇是在閱讀v-loading時產生的部分感悟,所以獨立出來做爲一篇文章講解一下。 本篇主要給你們介紹一下vue的自定義指令directive
,以及咱們如何經過directive
將一個組件插入到代碼當中,並控制顯隱。html
官網連接。官網中已經介紹了directive
。咱們能夠發現, 註冊一個自定義指令的時候,它會包含如下幾個鉤子函數。bind
、inserted
、update
、componentUpdated
。 其中vue
bind
只執行一次,即在指令綁定到元素的時候執行node
inserted
會在元素插入到父元素的時候執行api
update
會在所插入的組件發生變化的時候發生改變bash
componentUpdated
所在組件的 VNode 更新時調用app
注意注意 dom
這裏的update
的執行並非只在綁定的值發生改變的時候執行, 好比說在一個div
中插入v-loading=change
。 當div
所在的模板<template>
中有元素髮生改變的時候,此時不管是否涉及到咱們的綁定元素update
都會執行。 而且componentUpdated
也會執行。ide
每一個鉤子函數都會傳入如下幾個參數 el
、bind
、vnode
、oldVnode
。函數
el
是綁定的dom元素,能夠直接操做dom
bind
則包含指令的多個元素:name
,value
,oldValue
。。。(先了解這三個便可,咱們能夠經過value和oldValue的對比來判斷綁定指令是否發生改變,以此判斷是否要執行update
。
vnode
,vue的虛擬節點
oldVnode
,上一個虛擬節點。
如今咱們來講一說如何插入組件,在這裏咱們要用到如下幾個api, extend
、$mount
, extend
: 接收一個組件選項做爲參數,建立一個子類。 好比咱們有一個loading
的模板
<template>
<div class="loading" v-show="showLoading">
。。。
</div>
</template>
<script>
export default {
name: 'loading',
data () {
return {
showLoading: false,
}
}
}
</script>
<style lang="scss" scoped>
@import '@/components/scss/mixins.scss';
@import './style.scss';
</style>
複製代碼
咱們能夠建立一個index.js
文件,並在其中實例化一個loading
對象
import Vue from 'vue'
import loading from './app.vue';
const LoadingConstructor = Vue.extend(loading);
複製代碼
那麼咱們如何將loading
組件實例化並插入到指定元素下面呢?
export default {
install (Vue) {
// extend vue基礎構造器, 建立一個包含組件的對象
const LoadingConstructor = Vue.extend(loading);
// 建立自定義指令 v-loading
Vue.directive('v-loading', {
bind: function(el) {
console.warn('執行bind');
// 實例化一個loading對象
el.loading = new LoadingConstructor();
// 將loading的掛載實例加載在el下
el.appendChild(el.loading.$mount().$el);
},
inserted: function() {
console.warn('執行insterted');
},
// 發生在所綁定的模版更新的時候, 即<template>的更新時候發生
update: function(el, bind) {
console.warn(el);
if (bind.value !== bind.oldValue) {
el.loading.showLoading = bind.value;
}
console.warn('執行update');
},
componentUpdated: function() {
console.warn('執行componentUpdated');
},
})
}
}
複製代碼
關於這段代碼,其中可能有疑問應該是這一句 el.appendChild(el.loading.$mount().$el);
,這句是將loading
的實例掛載在父元素el
之下, 若是咱們這樣寫
const loading = new LoadingConstructor();
loading.$mount(el);
複製代碼
那麼元素el將會被loading實例所取代, 所以咱們要將loading實例掛載在el之下,就須要el.appendChild(loading組件)。 loading.el便是loading組件。
(果真,長久時間不寫,生疏了很多,各位看官見諒)。