clickoutside是Element-ui實現的一個自定義指令,顧名思義,該指令用來處理目標節點之外的點擊事件,常用來處理下拉菜單等展開內容的關閉,在Element-ui的Select選擇器、Dropdown下拉菜單、Popover 彈出框等組件中都用到了該指令,所以這個指令在實現一些自定義組件的時候非常有用。
要分析該源碼,首先要了解一下Vue的自定義指令。自定義指令的定義方式如下:
// 注冊一個全局自定義指令 Vue.directive('directiveName', { bind: function(el, binding, vnode){ // 當指令第一次綁定到元素時調用,常用來進行一些初始化設置 ... }, inserted: function(el, binding, vnode){ // 當被綁定的元素插入到 DOM 中時…… ... }, update: function(el, binding, vnode, oldVnode){ // 所在組件的 VNode 更新時調用,但是可能發生在其子 VNode 更新之前 ... }, componentUpdated: function(el, binding, vnode, oldVnode){ // 指令所在組件的 VNode 及其子 VNode 全部更新后調用 ... }, unbind: function(el, binding, vnode){ // 只調用一次,指令與元素解綁時調用,類似于beforeDestroy的功能 ... }});可以看到在配置對象中只有5個可選的鉤子函數,他們的參數有4個,分別是 el、binding、vnode、oldVnode
update 和 componentUpdated 鉤子中可用。看完了自定義指令的內容,接下來我們就來分析clickoutside的具體實現。
import Vue from 'vue';import { on } from 'element-ui/src/utils/dom';const nodeList = [];const ctx = '@@clickoutsideContext';let startClick;let seed = 0;!Vue.prototype.$isServer && on(document, 'mousedown', e => (startClick = e));!Vue.prototype.$isServer && on(document, 'mouseup', e => { nodeList.forEach(node => node[ctx].documentHandler(e, startClick));});function createDocumentHandler(el, binding, vnode) { return function(mouseup = {}, mousedown = {}) { ... };}let startClick;let seed = 0;export default { bind(el, binding, vnode) { ... }, update(el, binding, vnode) { ... }, unbind(el) { ... }};上面是簡化后的源碼,可以看到首先引入Vue和一個用來進行事件綁定的工具函數on,然后定義了兩個全局常量 nodeList 和 ctx 。nodeList 是一個 元素搜集器 ,會將頁面中所有綁定了clickoutside指令的dom元素存儲起來,而ctx定義了一個命名空間(必須比較特殊,防止和其它特性重名), 后面會將它添加為元素el的properties ,具體后面會分析到。
新聞熱點
疑難解答
圖片精選