菜鳥讀element源碼7

說明

很差意思通過了這麼久時間纔開始繼續寫文章,確實懶散了好久。廢話很少說,開始本文吧。css

正文

本篇是在閱讀v-loading時產生的部分感悟,所以獨立出來做爲一篇文章講解一下。 本篇主要給你們介紹一下vue的自定義指令directive,以及咱們如何經過directive將一個組件插入到代碼當中,並控制顯隱。html

directive

官網連接。官網中已經介紹了directive。咱們能夠發現, 註冊一個自定義指令的時候,它會包含如下幾個鉤子函數。bindinsertedupdatecomponentUpdated。 其中vue

bind只執行一次,即在指令綁定到元素的時候執行node

inserted會在元素插入到父元素的時候執行api

update會在所插入的組件發生變化的時候發生改變bash

componentUpdated所在組件的 VNode 更新時調用app

注意注意 dom

這裏的update的執行並非只在綁定的值發生改變的時候執行, 好比說在一個div中插入v-loading=change 。 當div所在的模板<template>中有元素髮生改變的時候,此時不管是否涉及到咱們的綁定元素update都會執行。 而且componentUpdated也會執行。ide

每一個鉤子函數都會傳入如下幾個參數 elbindvnodeoldVnode函數

el是綁定的dom元素,能夠直接操做dom

bind則包含指令的多個元素:namevalueoldValue。。。(先了解這三個便可,咱們能夠經過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.mount().el便是loading組件。

(果真,長久時間不寫,生疏了很多,各位看官見諒)。

相關文章
相關標籤/搜索