这篇文章的由来,其实是朋友在群里好奇@click绑定方式的种类,大家七嘴八舌讨论出来的,觉得过程还是比较有意义,就记录下来:

1、原生js绑定点击事件

好久不用原生js绑定事件,基本都已经忘了怎么绑定。还把括号给搞丢了,实际应该是在html绑定的时候需要(),在js中绑定不需要

// html  不加括号会导致函数不执行
	<div onclick="test()">点我</div>

	<div id="testDom"></div>
// js
	functiontest() {
		console.log('立即执行了')
		return () => {
			console.log('这里是点击踩执行')
		}
	}
	function test2() {
		console.log('立即执行了')
		return () => {
			console.log('这里是点击踩执行')
		}
	}

	let dom = document.querySelector("#testDom")
	console.log('dom',dom)
	let child = document.createElement('div')
	child.innerHTML = `<div οnclick="test2()">点我</div>`
	dom.appendChild(child)

附参考链接:为什么html里面的onclick函数后面要加(),而js里面不需要?

2、vue中绑定点击事件

思考

基于上边第1点,抛出问题:为什么vue绑定函数,已下两种方式都行?

<button @click="testClick">点我</button>
<button @click="testClick(123)">点我2</button>

其实开始讨论到这个问题的时候,还没有确定给出上边原生的结论,所以先去做了下测试,确定了原生html中onclick是不支持函数名称不带括号的绑定方式的。

做完测试,开始思考会有什么方式实现。先屡一下vue的编译过程:
在这里插入图片描述
初步怀疑在tem=>ast=>render(fun)之间,因为觉得这种小事情,链路应该不会拉的很长。于是重点排查这两个阶段,这部分涉及vue源码部分,我的源码版本是2.6.0,同时推荐这篇博主的这两vue源码解析,对应需要排查的两个阶段:

template转ast:https://chenjianhong.blog.csdn.net/article/details/114731266
ast转render(fun):https://blog.csdn.net/weixin_42752574/article/details/114766191

有了源码分析,找到入口debug就行了,但是注意看命名,vue名称还是很清晰的,根据名称很容易就看明白函数大概意思,无关函数跳过就行了。接下来放一下调试demo:

本地调试vue源码demo: https://github.com/yummyo/vueClickDemo

    <div id="app">
        <button @click="testClick">点我</button>
        <button @click="testClick(123)">点我2</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
            },
            methods: {
                testClick(){
                    console.log(123)
                }
            }
        })
    </script>

在本地新建html,然后将以上内容拷入并运行,同时打开控制台找到source标签页,根据源码解析,找到createCompilerCreator(源码位置:vue-2.6\src\compiler\index.js)函数
在这里插入图片描述
如图箭头所标注,对应我们要排查的两个阶段

查看ast,此时只是将tem转为了对应的ast,事件并没有做处理,接下来查看下一阶段
在这里插入图片描述

查看code变量对应值
在这里插入图片描述

此时发现了问题,按钮对应函数,已经被包裹了一层函数(蓝色框),可以对比下前边不加括号的按钮事件(红色框)

此时,基本就有了大概的思路,前边提到,js中绑定函数不需要加括号,如:

dom.onclick = testClick

有了上边的render字符串的数据接口,我们自己也可以循环绑定对应事件。

结论

vue在ast=》render(fun)阶段,做了处理,对于不带括号的函数绑定,不做处理,对于带括号的函数绑定,实际包括了一层函数在外边。

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐