VUE的點(diǎn)擊事件我們都用過聂使,我們來看一下最簡單的click底層是如何實(shí)現(xiàn)的盐欺。
<div id="test1" @click="click1">click1</div>
vue初始化的時(shí)候泊柬,將method中的方法代理到vue[key]的同時(shí)修飾了事件的回調(diào)函數(shù)。綁定了作用域杂曲。
function initState (vm) {
vm._watchers = [];
var opts = vm.$options;
if (opts.props) { initProps(vm, opts.props); }
if (opts.methods) { initMethods(vm, opts.methods); }//1.在此初始化
if (opts.data) {
initData(vm);
} else {
observe(vm._data = {}, true /* asRootData */);
}
if (opts.computed) { initComputed(vm, opts.computed); }
if (opts.watch) { initWatch(vm, opts.watch); }
}
我們再去看一下initMethods方法
function initMethods (vm, methods) {
var props = vm.$options.props;
for (var key in methods) {
vm[key] = methods[key] == null ? noop : bind(methods[key], vm);
{
if (methods[key] == null) {
warn(
"method \"" + key + "\" has an undefined value in the component definition. " +
"Did you reference the function correctly?",
vm
);
}
if (props && hasOwn(props, key)) {
warn(
("method \"" + key + "\" has already been defined as a prop."),
vm
);
}
}
}
}
看一下bind方法通過返回函數(shù)修飾了事件的回調(diào)函數(shù)庶艾。綁定了事件回調(diào)函數(shù)的this。并且讓參數(shù)自定義
function bind (fn, ctx) {
function boundFn (a) {
var l = arguments.length;
return l
? l > 1
? fn.apply(ctx, arguments)
: fn.call(ctx, a)
: fn.call(ctx)
}
boundFn._length = fn.length;
return boundFn
}
當(dāng)VUE運(yùn)行編譯時(shí)會把div等原始元素變成ast并通過函數(shù)genHandler進(jìn)行處理
當(dāng) 事件函數(shù)有修飾符解阅,處理修飾符并添加修飾符對應(yīng)的函數(shù)語句
function genHandler (
name,
handler
) {
if (!handler) {
return 'function(){}'
}
if (Array.isArray(handler)) {
return ("[" + (handler.map(function (handler) { return genHandler(name, handler); }).join(',')) + "]")
}
var isMethodPath = simplePathRE.test(handler.value);
var isFunctionExpression = fnExpRE.test(handler.value);
if (!handler.modifiers) {
//返回沒有修飾符的回調(diào)函數(shù)
return isMethodPath || isFunctionExpression
? handler.value
: ("function($event){" + (handler.value) + "}") // inline statement
} else {
//含有修飾符
var code = '';
var genModifierCode = '';
var keys = [];
for (var key in handler.modifiers) {
if (modifierCode[key]) {
//處理修飾符數(shù)組
genModifierCode += modifierCode[key];
if (keyCodes[key]) {
keys.push(key);
}
} else {
keys.push(key);
}
}
if (keys.length) {
code += genKeyFilter(keys);
}
// Make sure modifiers like prevent and stop get executed after key filtering
if (genModifierCode) {
code += genModifierCode;
}
var handlerCode = isMethodPath
? handler.value + '($event)'
: isFunctionExpression
? ("(" + (handler.value) + ")($event)")
: handler.value;
return ("function($event){" + code + handlerCode + "}")
}
}
我們看看render函數(shù)div的代碼
_c('div',{attrs:{"id":"test1"},on:{"click":click1}},[_v("click1")]),_v(" ")
在瀏覽器渲染成最終dom時(shí)會調(diào)用核心函數(shù)
function add$1 (
event,
handler,
once$$1,
capture,
passive
) {
if (once$$1) {
var oldHandler = handler;
var _target = target$1; // save current target element in closure
handler = function (ev) {
var res = arguments.length === 1
? oldHandler(ev)
: oldHandler.apply(null, arguments);
if (res !== null) {
remove$2(event, handler, capture, _target);
}
};
}
target$1.addEventListener(
event,
handler,
supportsPassive
? { capture: capture, passive: passive }//此處綁定點(diǎn)擊事件
: capture
);
}
總結(jié):div元素元素添加了.native修飾符的事件落竹。最終EventTarget.addEventListener() 掛載事件
知行辦公,專業(yè)移動辦公平臺 https://zx.naton.cn/
【總監(jiān)】十二春秋之货抄,3483099@qq.com;
【Master】zelo朱转,616701261@qq.com蟹地;
【運(yùn)營】狼行天下,897221533@qq.com藤为;
【產(chǎn)品設(shè)計(jì)】流浪貓怪与,364994559@qq.com;
【體驗(yàn)設(shè)計(jì)】兜兜缅疟,2435632247@qq.com分别;
【iOS】淘碼小工,492395860@qq.com存淫;iMcG33K耘斩,imcg33k@gmail.com;
【Android】人猿居士桅咆,1059604515@qq.com括授;思路的頓悟,1217022114@qq.com;
【java】首席工程師MR_W荚虚,feixue300@qq.com薛夜;
【測試】土鏡問道,847071279@qq.com版述;
【數(shù)據(jù)】喜樂多梯澜,42151960@qq.com;
【安全】保密渴析,你懂的晚伙。