首页 > 其他分享 >手撕Vue-编译指令数据

手撕Vue-编译指令数据

时间:2023-10-15 17:45:22浏览次数:36  
标签:node Vue vm value 编译 指令 model data

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

所以本章节主要处理的方法则是 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

标签:node,Vue,vm,value,编译,指令,model,data
From: https://www.cnblogs.com/BNTang/p/17765874.html

相关文章

  • vue学习六
    <divid="app6"><divv-for="iteminlist">{{item}}</div></div><script>constapp6=newVue({el:'#app6',data:{list:["1&qu......
  • vue学习五
    <divid="app5"><button@click="exchange(-5)">点我减五</button><button@click="exchange(5)">点我加五</button></div><script>constapp5=newVue({......
  • [Vue]初始Vue
    Vue2,建议新人直接饮用vue.js文件 <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><metahttp-equiv=......
  • Error: Vue packages version mismatch: - [email protected] (D:\前端\vue01\node_module
    Error:Vuepackagesversionmismatch:[email protected](D:\\前端\vue01\node_modules\vue\dist\vue.runtime.common.js)[email protected](D:\前端\vue01\node_modules\vue-template-compiler\package.json)根据提示信息,是版本不匹配的问题,可以直接找到vu......
  • vue js获取当天日期
    <template><div><p>Todayis{{today}}</p></div></template><script>exportdefault{data(){return{today:''}},mounted(){this.today=this.getCurrentDate();......
  • 输入vue ui出现Failed to get response from /vue-cli-version-marker
      解决办法:找到 .vuerc文件,位置在C:\Users\当前用户.vuerc将packageManager修改如下:原因是本地hadoop环境变量回合vue项目有冲突,他们都要用到yarn集群 修改后再重新输入vueui,没有报错信息且自动打开Vue项目管理器的页面  ......
  • 一个vuepress配置问题,引发的js递归算法思考
    前言这两天在尝试用语雀+vuepress+github搭建个人博客。小破站地址:王天的web进阶之路语雀作为编辑器,发布文档推送github,再自动打包部署,大概流程如下。问题我使用的elog插件批量导出语雀文档。elog采用的配置是所有文章平铺导出,没有按照语雀知识库目录生成markdown,这导......
  • 手撕Vue-查找指令和模板
    接着上一篇文章,我们已经实现了提取元素到内存的过程,接下来我们要实现的是查找指令和模板。大致的思路是这样的:遍历所有的节点需要判断当前遍历到的节点是一个元素还是一个文本如果是一个元素,我们需要判断有没有v-model属性如果是一个文本,我们需要判断有没有{{}}的内容......
  • C# 编译过程分析及IL等概念梳理
    转载自:       本文作者:好Wu赖   本文链接:https://www.cnblogs.com/erlongxizhu-03/p/12900445.html   C#编译过程分析及IL等概念梳理-好Wu赖-博客园(cnblogs.com) ......
  • vc---cl编译器的选项
    VC(VisualC++)编译器是MicrosoftVisualStudio集成开发环境中的C++编译器,用于编译和构建C++应用程序。VC编译器有许多编译选项,用于控制编译过程和生成的可执行文件。以下是一些常见的VC编译器选项:编译选项:/c:只进行编译,不进行链接。/O1,/O2,/Ox:启用不同级别的优化。/Gm:生成函......