手撕Vue-编译指令数据

经过上一篇的分析,完成了查找指令和模板的功能,接下来就是编译指令的数据了。

所以本章节主要处理的方法则是 buildElement 方法,我们先分析一下我们所拿到的数据在进行编码,这样会更加清晰一些。

我将 name, value 打印出来,分别对应的值是 name: v-model, value: name,在今后我们的命令中可不止只有 v-model,还有 v-text、v-html、v-on 等等,所以我们需要对这些指令进行分类,然后再进行编译。

所以我这里特意定义了一个工具类叫 CompilerUtil,用来处理指令的分类,代码如下:

let CompilerUtil = {
    /**
     * 处理 v-model 指令
     * @param node 当前元素
     * @param value 指令的值
     * @param vm Nue 的实例对象
     */
    model: function (node, value, vm) {
    },
    html: function (node, value, vm) {
    },
    text: function (node, value, vm) {
    }
}

然后我们在 buildElement 方法中调用这个方法,代码如下:

// 解构 name
let [, directive] = name.split('-');
// v-model -> [v, model]

// 2.根据指令名称, 调用不同的处理函数
CompilerUtil[directive](node, value, this.vm);

这样我们就可以根据指令的名称,调用不同的处理函数了。

接下来我们就来处理 v-model 指令,代码如下:

/**
 * 处理 model 指令
 * @param node 当前元素
 * @param value 指令的值
 * @param vm Nue 的实例对象
 */
model: function (node, value, vm) {
    node.value = vm.$data[value];
},

这样我们就可以将数据渲染到页面上了,打开浏览器,可以看到效果如下:

image-20231015171034901

v-model 指令已经可以正常使用了,但是还有问题,就是我们的数据结构目前是比较简单的,那么如果我们的数据是一个对象呢,例如:

image-20231015172334067

time: {
    h: 10,
    m: 10,
    s: 10
}

在用 input 绑定 v-model 进行渲染发现,只有第一个 input 能够正常渲染,其他的 input 都是 undefined,这是为什么呢?

<input type="text" v-model="time.h">
<input type="text" v-model="time.m">
<input type="text" v-model="time.s">

那么这里就要去看一下我们 model 方法的实现了,如果是 time.h,value 等于的值为 time.h, 然后我们在执行 vm.$data[value] 就变为了 vm.$data[time.h], 正常的获取这种数据结构的方式应该是先 vm.$data[time] 拿到 time 对象,然后再 time[h] 拿到 h 的值,所以我们需要对这种数据结构进行处理,为了已维护,我这里单独抽离了一个方法出来进行处理获取 value,方法名字叫做 getValue,代码如下:

getValue(vm, value) {
    // time.h --> [time, h]
    return value.split('.').reduce((data, currentKey) => {
        // 第一次执行: data=$data, currentKey=time
        // 第二次执行: data=time, currentKey=h
        return data[currentKey];
    }, vm.$data);
},

reduce 方法被用于迭代这个字符串数组。它接受一个回调函数,这个回调函数在每次迭代中被调用。在这个回调函数中,data 是上一次迭代的结果,而 currentKey 是当前迭代的数组元素(键路径中的一个部分)在每次迭代中,回调函数通过 data[currentKey] 的方式访问嵌套对象的属性,然后将这个属性的值作为下一次迭代的 data, 最终,reduce 方法将遍历整个键路径,直到达到最深层的属性,然后返回该属性的值。这样我们就可以正常的获取到数据了,最后在改造一下之前 model 方法获取值的地方,调用下刚刚编写的 getValue 方法即可:

model: function (node, value, vm) {
    node.value = this.getValue(vm, value);
},

再次打开浏览器,可以看到效果如下:

image-20231015172812038

这个搞定之后,我们紧接着把 v-html 和 v-text 也搞定,代码基本上都是一样的,只是渲染的方式不一样,代码如下:

/**
 * 处理 html 指令
 * @param node 当前元素
 * @param value 指令的值
 * @param vm Nue 的实例对象
 */
html: function (node, value, vm) {
    node.innerHTML = this.getValue(vm, value);
},
/**
 * 处理 text 指令
 * @param node 当前元素
 * @param value 指令的值
 * @param vm Nue 的实例对象
 */
text: function (node, value, vm) {
    node.innerText = this.getValue(vm, value);
}

编写测试代码:

image-20231015173151943

html: `<div>我是div</div>`,
text: `<div>我是div</div>`

编写HTML代码:

<div v-html="html">abc</div>
<div v-text="text">123</div>

打开浏览器,可以看到效果如下:

image-20231015173252270

posted @   BNTang  阅读(326)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源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邢锐
就让这大雨全都落下·2023 - 刘大拿
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

Loading

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