手撕Vue-查找指令和模板
接着上一篇文章,我们已经实现了提取元素到内存的过程,接下来我们要实现的是查找指令和模板。
大致的思路是这样的:
- 遍历所有的节点
- 需要判断当前遍历到的节点是一个元素还是一个文本
- 如果是一个元素, 我们需要判断有没有v-model属性
- 如果是一个文本, 我们需要判断有没有{{}}的内容
那么随着思路的展开,接下来我们就来实现这个功能。
首先我们编写一个 buildTemplate 方法,主要功能是利用指定的数据编译内存中的元素:
buildTemplate(fragment) {
let nodeList = [...fragment.childNodes];
// 1.遍历所有的节点
nodeList.forEach(node => {
});
}
buildTemplate 方法定义在 Compiler 类中,我们需要在 compile 方法中调用它:

// 2.利用指定的数据编译内存中的元素
this.buildTemplate(fragment);
然后我们在 buildTemplate 方法中完善我们的代码,这里我就先直接上完整的实现代码:
buildTemplate(fragment) {
let nodeList = [...fragment.childNodes];
// 1.遍历所有的节点
nodeList.forEach(node => {
// 2.需要判断当前遍历到的节点是一个元素还是一个文本
if (this.vm.isElement(node)) {
// 是一个元素
this.buildElement(node);
} else {
// 不是一个元素
this.buildText(node);
}
});
}
buildElement(node) {
// 可以通过 node.attributes 获取到当前元素上所有的属性
let attrs = [...node.attributes];
// 1.遍历所有的属性
attrs.forEach(attr => {
let {name, value} = attr;
if (name.startsWith('v-')) {
console.log('是Vue的指令, 需要我们处理', name);
}
});
}
buildText(node) {
// 可以通过 node.textContent 获取到当前文本节点的内容
let content = node.textContent;
// 编写一个正则表达式, 用来匹配 {{}}
// 如下正则表达式的含义是: 匹配 {{}} 中间的内容
// /: 正则表达式通常以斜杠 / 开始和结束,表示正则表达式的开始和结束。
// \{ 和 \}: 这些是转义字符,用于匹配实际的花括号 { 和 }。花括号在正则表达式中具有特殊意义,因此需要使用反斜杠进行转义。
// \{\{ 和 \}\}: 这是正则表达式的起始和结束部分,用于匹配双花括号 {{ 和 }}。
// .+?: 这部分用于匹配双花括号内的任意字符,. 表示匹配任意字符,+ 表示匹配一个或多个前面的字符,? 表示非贪婪匹配,即尽可能匹配最短的内容。这样确保匹配到最近的结束双花括号 }}。
// /g: g 是正则表达式的标志,表示全局匹配,即匹配字符串中的所有符合条件的部分。
// /i: i 也是正则表达式的标志,表示不区分大小写匹配,这意味着 {{...}} 和 {{...}} 都会被匹配到。
// 因此,这个正则表达式可以用于在字符串中找到并提取所有的 {{...}} 结构,不区分大小写,不贪婪匹配,且匹配所有出现的情况。
let reg = /\{\{.+?\}\}/gi;
if (reg.test(content)) {
console.log('是一个文本节点, 需要我们处理', content);
}
}
好了,我们来看一下效果,我们在浏览器中打开,然后打开控制台,可以看到如下的效果:

发现,只有 v-model 指令被处理, {{}} 没有被处理,如下图我框出了 <p>:

也就是说我们循环节点的时候,只循环了一层,没有循环到 <p> 标签中的文本节点,所以我们需要修改一下 buildTemplate 方法, 让它支持递归,处理子元素(处理后代):

// 处理子元素(处理后代)
this.buildTemplate(node);
改造后,我们再来看一下效果,可以看到 {{}} 也被处理了:

好了,到这里我们就实现了查找指令和模板的功能,下一篇我们来继续完善一下我们的不完整的代码,一步一步来慢慢撕。
手撕Vue-查找指令和模板的更多相关文章
- Vue自定义指令使用场景
当你第一次接触vue的时候,一定会使用到其中的几个指令,比如:v-if.v-for.v-bind...这些都是vue为我们写好的,用起来相当的爽.如果有些场景不满足,需要我们自己去自定义,那要怎么办呢 ...
- 编译原理--05 用C++手撕PL/0
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 05 用C++手撕PL/0 在之前 ...
- 剖析手写Vue,你也可以手写一个MVVM框架
剖析手写Vue,你也可以手写一个MVVM框架# 邮箱:563995050@qq.com github: https://github.com/xiaoqiuxiong 作者:肖秋雄(eddy) 温馨提 ...
- vue的指令
我之前学了学angular 发现angular和vue的指令有点类似 先说一下 new Vue({ el: "#box", // element(元素) 当前作 ...
- vue自定义指令用法总结及案例
1.vue中的指令有哪些?
- 第3章-Vue.js 指令扩展 和 todoList练习
一.学习目标 了解Vue.js指令的实现原理 理解v-model指令的高级用法 能够使用Vue.js 指令完成 todoList 练习(重点+难点) 二.todoList练习效果展示 2.1.效果图展 ...
- vue自定义指令clickoutside使用以及扩展用法
vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...
- vue自定义指令clickoutside扩展--多个元素的并集作为inside
都是个人理解,如果发现错误,恳请大家批评指正,谢谢.还有我说的会比较啰嗦,因为是以自身菜鸡水平的视角来记录学习理解的过程,见谅. 1.前言 产品使用vue+element作为前端框架.在功能开发过程中 ...
- 每个人都能实现的vue自定义指令
前文 先来bb一堆废话哈哈.. 用vue做项目也有一年多了.除了用别人的插件之外.自己也没尝试去封装指令插件之类的东西来用. 刚好最近在项目中遇到一个问题.(快速点击按钮多次触发多次绑定的方法),于是 ...
- Vue的指令以及组件化开发
一. 自定义指令 如何: 1. 创建指令 Vue.directive("指令名",{ inserted(elem){//指令所在的元素被加载到DOM树上后自动执行指令 //elem ...
随机推荐
- docker中的mysql中文乱码解决办法
博主最近在做谷粒商城,因为要使用docker安装mysql,但是由于安装的时候没有指定mysql的数据库的utf8格式,导致插入的时候就出现了中文是问号的情况,到处百度终于解决,于是打算记录一下自己的 ...
- Task Execution and Scheduling In SpringBoot
开天辟地 Task Execution and Scheduling In the absence of an Executor bean in the context, Spring Boot au ...
- Unity UGUI的Mask(遮罩)组件的介绍及使用
Unity UGUI的Mask(遮罩)组件的介绍及使用 1. 什么是Mask组件? Mask(遮罩)组件是Unity UGUI中的一个重要组件,用于限制子对象的可见区域.通过设置遮罩组件,可以实现一些 ...
- 【Shell】ps 命令
ps 命令 Linux ps (英文全拼:process status)命令用于显示当前进程的状态,类似于 windows 的任务管理器. 1. ps 常用的命令 ps -aux #显示所有进程信息 ...
- 【阅读笔记】低照度图像增强-《Adaptive and integrated neighborhood-dependent approach for nonlinear enhancement of
本文介绍改进INDANE算法的低照度图像增强改进算法(AINDANE算法),<Adaptive and integrated neighborhood-dependent approach fo ...
- 揭秘 .NET 中的 TimerQueue(上)
前言 TimerQueue 是.NET中实现定时任务的核心组件,它是一个定时任务的管理器,负责存储和调度定时任务.它被用于实现很多 .NET 中的定时任务,比如 System.Threading.Ti ...
- 实际上手体验maven面对冲突Jar包的加载规则
一.问题背景 相信大家在日常的开发过程中都遇到过Jar包冲突的问题,emm,在最近处理业务需求时我也遇到了不同版本jar包冲突导致项目加载出错的问题.主要是一个完整的项目会不可避免的使用第三方的Jar ...
- 【WebGL系列-02】创建program上下文
WebGL程序program对象的创建 program对象由顶点着色器对象和片元着色器对象构成,因此,创建program对象包含了两部分,一个是着色器对象的创建,一个是program对象的创建. 总体 ...
- 为什么 PostgreSQL 的适用性很强?
说起使用数量最大的数据库SQLite 它是全球最广泛部署的数据库引擎.它存在于你的手机中,存在于你的浏览器中,如果你搜索你的电脑,你也会在其中找到它的 .db 文件.SQLite 受到 Postgre ...
- 2021-7-6 new tcpip
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...