UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

175 lines (145 loc) • 4.62 kB
const CLICK = 'click'; // 捕获实例 const captureInstances = Object.create(null); // 不捕获实例 const nonCaptureInstances = Object.create(null); // 实例列表 const instancesList = [captureInstances, nonCaptureInstances]; /** * The common event handler for bot capture and non-capture events. * * @param {!Object} context - The event context. * @param {!Object} instances - The capture or non-capture registered instances. * @param {Event} event - The event object. * @returns {undefined} Default. */ const commonHandler = function _onCommonHandler(context, instances, event) { const { target } = event; const item = function _item(item) { const { el } = item; if (el !== target && !el.contains(target)) { const { binding } = item; if (binding.modifiers.stop) { event.stopPropagation(); } if (binding.modifiers.prevent) { event.preventDefault(); } binding.value.call(context, event); } }; const key = function _key(eventName: string) { return instances[eventName].forEach(item); }; Object.keys(instances).forEach(key); }; // 捕获事件处理程序 const captureEventHandler = function onCaptureEvent(event) { commonHandler(this, captureInstances, event); }; // 非捕获事件处理程序 const nonCaptureEventHandler = function onNonCaptureEvent(event) { commonHandler(this, nonCaptureInstances, event); }; // 获取事件处理程序 const getEventHandler = function _getEventHandler(useCapture: boolean) { return useCapture ? captureEventHandler : nonCaptureEventHandler; }; // 指令定义 function inserted(el: Element, binding: Record<string, any>): void { // 判断参数 if (typeof binding.value !== 'function') { throw new TypeError('Binding value must be a function'); } // 事件名称 let eventType; const modifiers = binding.modifiers; if (modifiers.click) { eventType = 'click'; } else if (modifiers.mousedown) { eventType = 'mousedown'; } else if (modifiers.touchstart) { eventType = 'touchstart'; } else { eventType = CLICK; } // 是否开启外部点击的 capture 模式,可通过全局配置 const useCapture = binding.arg; // 归并事件绑定 const normalisedBinding = { ...binding, ...{ // 一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true } modifiers: { ...{ // 添加事件侦听器时使用 capture 模式 capture: false, // 阻止默认行为 prevent: false, // 调用 event.stopPropagation() 停止冒泡 stop: false, }, ...binding.modifiers, }, }, }; // 实例化事件 const instances = useCapture ? captureInstances : nonCaptureInstances; // 判断事件中是否有对应的指令参数 初始化指令 if (!Array.isArray(instances[eventType])) { instances[eventType] = []; } if ( instances[eventType].push({ el, binding: normalisedBinding, }) === 1 ) { if (typeof document === 'object' && document) { document.addEventListener( eventType, getEventHandler(useCapture), useCapture ); } } } // 指令与元素解绑时调用 function unbind(el: Element): void { // 比较元素 const compareElements = function _compareElements(item) { return item.el !== el; }; const instances = function _instances(instances) { // 实例key const instancesKeys = Object.keys(instances); // 判断是否有实例 if (instancesKeys.length) { // 判断是否使用事件捕获 const useCapture = instances === captureInstances; const keys = function _keys(eventName: string) { // 查找元素实例 const newInstance = instances[eventName].filter(compareElements); if (newInstance.length) { instances[eventName] = newInstance; } else { if (typeof document === 'object' && document) { // 移除事件 document.removeEventListener( eventName, getEventHandler(useCapture), useCapture ); } delete instances[eventName]; } }; instancesKeys.forEach(keys); } }; instancesList.forEach(instances); } export default { beforeMount: inserted, unmounted: unbind, };