• 手撕Vue-查找指令和模板


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

    大致的思路是这样的:

    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 指令被处理, {{}} 没有被处理,如下图我框出了

    image-20231015104624387

    也就是说我们循环节点的时候,只循环了一层,没有循环到

    标签中的文本节点,所以我们需要修改一下 buildTemplate 方法, 让它支持递归,处理子元素(处理后代):

    image-20231015104809104

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

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

    image-20231015104833637

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


    __EOF__

  • 本文作者: BNTang
  • 本文链接: https://www.cnblogs.com/BNTang/p/17765373.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    老司机带带你,教你学会Java中又骚又暴力的“反射”技术
    JQuery系列之事件
    腾讯视频跟爱奇艺视频共享设备ip会不会出现错误
    Lwip之TCP协议实现(一)
    Node.js-express框架-cookie设置参数详解和举例
    基于Tensorflow搭建卷积神经网络CNN(水果识别)保姆及级教程
    springboot-kafka
    刷刷笔试题--贪心算法
    深度学习记录
    双十一怎么入手最划算,盘点几款不踩雷的好物推荐
  • 原文地址:https://www.cnblogs.com/BNTang/p/17765373.html