菜鸟读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组件。

(果真,长久时间不写,生疏了很多,各位看官见谅)。

相关文章
相关标签/搜索