手撕Vue-实现事件相关指令

经过上一篇文章的学习,实现了界面驱动数据更新,接下来实现一下其它相关的指令,比如事件相关的指令,v-on 这个指令的使用频率还是很高的,所以我们先来实现这个指令。

v-on 的作用是什么,是不是可以给某一个元素绑定一个事件。

紧接着了解了 v-on 的作用之后,我在 example.html 的结构代码当中添加了一个 div 用 v-on 绑定了一个点击事件,然后在 methods 当中添加了一个 myFn 的方法,然后在点击事件触发的时候调用了 myFn 方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue基本模板</title>
    <script src="js/nue.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="name"/>
    <div v-on:click="myFn">我是div</div>
</div>

<script>
    let vue = new Nue({
        el: document.querySelector('#app'),
        data: {
            name: "BNTang"
        },
        methods: {
            myFn() {
                alert('myFn被执行了');
            },
        }
    });
</script>
</body>
</html>

如上已经将基本的结构搭建完毕了,现在需要做的事情就是需要处理一下 v-on 这个指令。

首先来看我们自己编写的 Nue 源码,在创建 Nue 实例的时候, 调用了 new Compiler(this);,进入 Compiler,constructor 方法继续往下看, 在进入 this.buildTemplate(fragment);,遍历所有的节点,判断是否是一个元素时,调用了 this.buildElement(node);, 进入 buildElement 方法,可以看到之前就是在这里处理了 v-model 这个指令,现在我们需要在这里处理 v-on 这个指令。

我先将 name, value 打印到控制台,输出结果如下:

type text
v-model name
v-on:click myFn

可以得出如果我们编写的是 v-model,那么 name 就是 v-model,value 就是 name,如果编写的是 v-on:click,那么 name 就是 v-on:click,value 就是 myFn。

知道了这些信息之后就可以开展下一步了,我在将 name 按照 : 进行分割一次就会拿到的是 v-on 与 click,click 就是待会我们要注册的事件类型,在用解构的方式将 name, value 取出来,代码如下:

let [directiveName, directiveType] = name.split(':');

directiveName 就是 v-on,directiveType 就是 click。

然后再将之前的代码 name.split('-'); 改写为 directiveName.split('-');, 这个时候我们将解构出来的结果如下:

model
on

这个时候就可以在之前的工具类当中添加一个 on 方法, 来用处理 v-on,在添加 on 方法之前,改造一下根据指令名称, 调用不同的处理函数的代码,将之前的代码改写为如下:

CompilerUtil[directive](node, value, this.vm, directiveType);

多了一个 directiveType 参数,这个参数就是指令的类型,比如 v-on:click,那么 directiveType 就是 click,这个时候就可以在工具类当中添加一个 on 方法了,代码如下:

on: function (node, value, vm, type) {
    node.addEventListener(type, (e) => {
        alert('事件注册成功了');
    });
}

这个时候我们在页面上点击 div 的时候,就会弹出一个提示框,说明事件注册成功了。

image-20231021102245038

事件注册成功了是没问题,但是这个事件执行的内容,是自己的,并不是通过 v-on 绑定的,所以我们需要将这个事件执行的内容改为通过 v-on 绑定的,这个时候就需要用到之前的 methods 对象了,我们需要通过 methods 对象来获取到对应的方法,然后将这个方法执行。

接下来要改造一下创建 Nue 实例的时候,将 methods 保存起来,改造一下 Nue 的构造函数,以后在根据对应的方法名称,获取到对应的方法, 再执行即可,代码如下:

this.$methods = options.methods;

image-20231021103538146

改造完毕之后,我们就可以在工具类当中的 on 方法当中,通过 methods 对象获取到对应的方法,然后执行即可,代码如下:

on: function (node, value, vm, type) {
    node.addEventListener(type, (e) => {
        vm.$methods[value](e);
    });
}

这个时候我们在页面上点击 div 的时候,就会弹出一个提示框,说明事件注册成功了,并且事件执行的内容也是通过 v-on 绑定的。

image-20231021163138741

在 myFn 方法中打印一下 this,发现并不是 Nue 的实例,而是 myFn 本身:

image-20231021164157119

这个时候就需要将 myFn 的 this 改为 Nue 的实例,这个时候就需要用到 call 方法了,代码如下:

node.addEventListener(type, (e) => {
    vm.$methods[value].call(vm, e);
});

call 方法的第一个参数是改变 this 的指向,第二个参数是传递的参数,这个时候我们在 myFn 方法中打印一下 this,发现已经是 Nue 的实例了。

image-20231021164018995

到此为止,v-on 指令的实现已经完成了。

posted @   BNTang  阅读(305)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
  1. 1 总会有人离开 王巨星
  2. 2 月亮 孟凡明
  3. 3 迟里乌布
  4. 4 我只能离开 颜人中
  5. 5 达尔文 蔡健雅
  6. 6 夜色滚烫 叶明净
  7. 7 你的星环 路飞文
  8. 8 不再说话 三块木头
  9. 9 黄昏 粥粥和小伙/粥粥
  10. 10 爱不单行 刘大拿
  11. 11 心动贩卖机 PIggy
  12. 12 别来无恙 苏星婕
  13. 13 我们的歌 刘大拿
  14. 14 一直很安静 王贰浪
  15. 15 去有风的地方 清音
  16. 16 雪 Distance Capper/罗言
  17. 17 坏女孩 徐良/小凌
  18. 18 乐园 沧桑Cang333/虎皮蛋/曲甲
  19. 19 Ayo(Explicit) Chris Brown/Tyga
  20. 20 我的美丽feat.海洋Bo 海洋Bo/高睿
  21. 21 世事可爱 粥粥和小伙/粥粥
  22. 22 我记得 赵雷
  23. 23 我想牵着你的手 许嵩
  24. 24 人们都不懂 刘诺然
  25. 25 寻一个你(电视剧《苍兰诀》温情主题曲) TTTTTeehom
  26. 26 子莫格尼 杉和
  27. 27 Cat Cafe Shoffy
  28. 28 风停了雨停了我们还拥抱着 Superluckyqi
  29. 29 寂寞沙洲冷 于潼
  30. 30 三国恋 王巨星
  31. 31 达尔文 林俊杰
  32. 32 有些 颜人中
  33. 33 小模样 张小只ya
  34. 34 是否 程响
  35. 35 楼顶上的小斑鸠 队长
  36. 36 笑场 薛之谦
  37. 37 还是分开 张叶蕾
  38. 38 修炼爱情 林俊杰
  39. 39 二零三 毛不易
  40. 40 雅俗共赏 许嵩
  41. 41 Serendipity 古瑞斯Graps/Zakiya晴子
  42. 42 就让这大雨全都落下·2023 刘大拿
  43. 43 老男孩 筷子兄弟
  44. 44 有何不可 许嵩
  45. 45 缓缓 杜宣达
  46. 46 好久不见 陈奕迅
  47. 47 爱的魔法(Cover 金莎) 封茗囧菌
  48. 48 在你的身边 盛哲
  49. 49 带我去找夜生活 告五人
  50. 50 假面舞会 很美味
  51. 51 STAY The Kid LAROI/Justin Bieber
  52. 52 我好想睡觉的 无敌西红柿
  53. 53 日不落(温柔版)
  54. 54 恋爱画板 锦零
  55. 55 7710 好乐无荒/尹露浠
  56. 56 给你呀(又名:for ya) 蒋小呢
  57. 57 Love Story Taylor Swift
  58. 58 Plain Jane(Remix 13z) 鱼幼微
  59. 59 晚风 7opy/BT07
  60. 60 拜托 孙晨
  61. 61 乌梅子酱 李荣浩
  62. 62 南半球与北海道 范倪Liu
  63. 63 星河万里 Rom邢锐
有何不可 - 许嵩
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 许嵩

作曲 : 许嵩

编曲 : 许嵩

制作人 : 许嵩

天空好想下雨

我好想住你隔壁

傻站在你家楼下

抬起头数乌云

如果场景里出现一架钢琴

我会唱歌给你听

哪怕好多盆水往下淋

夏天快要过去

请你少买冰淇淋

天凉就别穿短裙

别再那么淘气

如果有时不那么开心

我愿意将格洛米借给你

你其实明白我心意

为你唱这首歌没有什么风格

它仅仅代表着我想给你快乐

为你解冻冰河为你做一只扑火的飞蛾

没有什么事情是不值得

为你唱这首歌没有什么风格

它仅仅代表着我希望你快乐

为你辗转反侧为你放弃世界有何不可

夏末秋凉里带一点温热有换季的颜色

天空好想下雨

我好想住你隔壁

傻站在你家楼下

抬起头数乌云

如果场景里出现一架钢琴

我会唱歌给你听

哪怕好多盆水往下淋

夏天快要过去

请你少买冰淇淋

天凉就别穿短裙

别再那么淘气

如果有时不那么开心

我愿意将格洛米借给你

你其实明白我心意

为你唱这首歌没有什么风格

它仅仅代表着我想给你快乐

为你解冻冰河为你做一只扑火的飞蛾

没有什么事情是不值得

为你唱这首歌没有什么风格

它仅仅代表着我希望你快乐

为你辗转反侧为你放弃世界有何不可

夏末秋凉里带一点温热

为你解冻冰河为你做一只扑火的飞蛾

没有什么事情是不值得

为你唱这首歌没有什么风格

它仅仅代表着我希望你快乐

为你辗转反侧为你放弃世界有何不可

夏末秋凉里带一点温热有换季的颜色

点击右上角即可分享
微信分享提示