vue源码分析(二十三)Vue之指令(v-show)
2020-04-22 本文已影响0人
vue爱好者
我们打开文件 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'
}
}