vue源码分析(二十三)Vue之指令(v-show)

我们打开文件 src/platforms/web/runtime/directives/show.js

/* @flow */

import { enter, leave } from '../modules/transition'

// recursively search for possible transition defined inside the component root
function locateNode (vnode: VNode): VNodeWithData {
  return vnode.componentInstance && (!vnode.data || !vnode.data.transition)
    ? locateNode(vnode.componentInstance._vnode)
    : vnode
}

export default {
  bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    const originalDisplay = el.__vOriginalDisplay =
      el.style.display === 'none' ? '' : el.style.display
    if (value && transition) {
      vnode.data.show = true
      enter(vnode, () => {
        el.style.display = originalDisplay
      })
    } else {
      el.style.display = value ? originalDisplay : 'none'
    }
  },

  update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
    /* istanbul ignore if */
    if (!value === !oldValue) return
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    if (transition) {
      vnode.data.show = true
      if (value) {
        enter(vnode, () => {
          el.style.display = el.__vOriginalDisplay
        })
      } else {
        leave(vnode, () => {
          el.style.display = 'none'
        })
      }
    } else {
      el.style.display = value ? el.__vOriginalDisplay : 'none'
    }
  },

  unbind (
    el: any,
    binding: VNodeDirective,
    vnode: VNodeWithData,
    oldVnode: VNodeWithData,
    isDestroy: boolean
  ) {
    if (!isDestroy) {
      el.style.display = el.__vOriginalDisplay
    }
  }
}

可以看到有3个方法:
1、bind // 生成DOM节点是时候会调用
2、update // 数据更新的时候触发
3、unbind // 组件销毁的时候,调用$destory函数

bind

 bind (el: any, { value }: VNodeDirective, vnode: VNodeWithData) {
   // 递归搜索组件内存在是 'transition'属性
    vnode = locateNode(vnode)
    // vnode 虚拟节点是否存在 'transition'属性
    const transition = vnode.data && vnode.data.transition
    // 当前节点是'node'隐藏状态,就改为‘’空
    const originalDisplay = el.__vOriginalDisplay = el.style.display === 'none' ? '' : el.style.display
    // value和'transition'属性同时存在,那就是显示出来
    if (value && transition) {
      vnode.data.show = true
      enter(vnode, () => {
        el.style.display = originalDisplay
      })
    } else {
      // value 存在那就display 为‘’空否则就是'none'隐藏
      el.style.display = value ? originalDisplay : 'none'
    }
  },

update

update (el: any, { value, oldValue }: VNodeDirective, vnode: VNodeWithData) {
    /* istanbul ignore if */
   // 先转换成布尔值,然后再进行对比,如果值相等就return
  // 下面的逻辑就和'bind'差不多了
    if (!value === !oldValue) return
    vnode = locateNode(vnode)
    const transition = vnode.data && vnode.data.transition
    if (transition) {
      vnode.data.show = true
      if (value) {
        enter(vnode, () => {
          el.style.display = el.__vOriginalDisplay
        })
      } else {
        leave(vnode, () => {
          el.style.display = 'none'
        })
      }
    } else {
      el.style.display = value ? el.__vOriginalDisplay : 'none'
    }
  }

你可能感兴趣的:(vue源码分析(二十三)Vue之指令(v-show))