首页 > 其他分享 >手撕Vue-查找指令和模板

手撕Vue-查找指令和模板

时间:2023-10-15 11:01:09浏览次数:41  
标签:node Vue 匹配 正则表达式 元素 查找 buildTemplate 节点 模板

接着上一篇文章,我们已经实现了提取元素到内存的过程,接下来我们要实现的是查找指令和模板。

大致的思路是这样的:

  1. 遍历所有的节点
  2. 需要判断当前遍历到的节点是一个元素还是一个文本
  3. 如果是一个元素, 我们需要判断有没有v-model属性
  4. 如果是一个文本, 我们需要判断有没有{{}}的内容

那么随着思路的展开,接下来我们就来实现这个功能。

首先我们编写一个 buildTemplate 方法,主要功能是利用指定的数据编译内存中的元素:

buildTemplate(fragment) {
    let nodeList = [...fragment.childNodes];

    // 1.遍历所有的节点
    nodeList.forEach(node => {

    });
}

buildTemplate 方法定义在 Compiler 类中,我们需要在 compile 方法中调用它:

image-20231015103931327

// 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);
    }
}

好了,我们来看一下效果,我们在浏览器中打开,然后打开控制台,可以看到如下的效果:

image-20231015104503123

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

image-20231015104624387

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

image-20231015104809104

// 处理子元素(处理后代)
this.buildTemplate(node);

改造后,我们再来看一下效果,可以看到 {{}} 也被处理了:

image-20231015104833637

好了,到这里我们就实现了查找指令和模板的功能,下一篇我们来继续完善一下我们的不完整的代码,一步一步来慢慢撕。

标签:node,Vue,匹配,正则表达式,元素,查找,buildTemplate,节点,模板
From: https://www.cnblogs.com/BNTang/p/17765373.html

相关文章

  • c++ 线段树模板
    洛谷模板:P3372【线段树1】 #include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e5+10;inta[N],d[N<<2],b[N<<2];intn,q;inlinevoidbuild(intl,intr,intp){if(l==r){d[p]=a[l];......
  • vue style 原理
    vuestyle的实现主要通过css的属性选择器什么是属性选择器?答:用于判断标签属性的一种选择器<style>.a[self_attribute]{...}</style><!--生效--><divself_attributeclass="a"></div><!--不生效--><divclass="a"></div&......
  • 23-Vue组件化编程-非单文件组件和单文件组件
    非单文件组件一个文件中包含有n个组件 Vue中使用组件的三大步骤1.定义组件(也就是创建组件)2.注册组件(这里有局部注册和全局注册)3.使用组件(编写组件标签) 注册组件(局部注册)靠newVue的时候传入components选项<!DOCTYPEhtml><htmllang="en"><head><meta......
  • Javascript、axios、vue基础命令快速学习
    1.js:JavaScript基础学习JavaScript基础学习简单案例1.点击img1,则展示img1图片默认,点击img2则展示img2图片2.输入框鼠标聚焦onfocus后,显示小写toLowerCase(),失去焦点onblur后显示大写toUpperCase()3.点击全选按钮,所有复选框为被选中状态,点击反选则取消勾选状态JavaScrip......
  • Vue3 + Quasar系列-代码配置以及报错汇总记录(不断更新中)
    1.Vue3+Quasar系列-代码配置打包去掉hash后缀去掉hashhttps://quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa2.Vue3+Quasar改变主题背景quasar的样式和其他的框架修改不太一样,需要我们使用动态的方式来进行变更,一般来说有两种方案进行主题修改方案一:......
  • Vue3| Pinia 持久化插件
    对vuex或Pinia里面的内容做本地持久化1.安装插件:npmipinia-plugin-persistedstate2.将插件添加到pinia实例上①main.js里导入持久化插件:importpiniaPluginPersistedstatefrom'pinia-plugin-persistedstate'② app.use(pinia.use(piniaPluginPersistedstate))......
  • 手撕Vue-提取元素到内存
    接着上一篇文章,我们已经实现了构建Vue实例的过程,接下来我们要实现的是提取元素到内存。主要是通过文档碎片来实现,文档碎片是一个轻量级的文档,可以包含和控制节点,但是不会像真实的DOM那样占用内存,所以我们可以通过文档碎片来提高性能。大致的思路是这样的:创建一个空的文档碎片......
  • Vue3| Pinia 的 action 异步写法
    import{defineStore}from'pinia'import{ref}from'vue'importaxiosfrom'axios'exportconstuseChannelStore=defineStore('channel',()=>{  constchannelList=ref([])  constgetList=()=>......
  • Vue3| Pinia 的语法
    Pinia是Vue的最新状态管理工具,是Vuex的替代品Pinia的优势:1.提供更简单的API(去掉了mutation)2.提供符合组合式风格的API(和Vue3新语法统一)3.去掉了modules的概念,每一个store都是一个独立的模块4.配合TypeScript更加友好,提供可靠的类型推断 Pinia基本......
  • vue webpack 报错处理
    1.vue-cli3中console.log报错:ModuleWarning(from./node_modules/eslint-loader/index.js):error:Unexpectedconsolestatement(no-console)at(1).原因:使用ESLint检查代码质量是进行提示的.(2).解决:window.console.log(res);2.图片引入:{id:1,src:require(......