探究Vue源码:mustache模板引擎(6) 编写Scanner扫描类处理字符串按格式分割

上文探究Vue源码:mustache模板引擎(5) 对比rollup与webpack,在本地搭建webpack环境中 我们搭建了一个基本的webpack开发环境
那么 本文开始 我们就要写这方面的开发代码了
我们在 src下的index.js
代码如下

window.GrManagData = {
    render() {
        console.log(111);
    }
}

然后 www下的 index.html 编写代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src = "/xuni/bundle.js"></script>
    <script>
        GrManagData.render();
    </script>
</body>
</html>

我们js中 在 window对象上挂一个GrManagData对象
然后 里面写一个render函数

然后 html中 引入js 再调用GrManagData下的render
我们在浏览器中访问
控制台输出如下
在这里插入图片描述
也是没有任何问题

然后 我们将 www 下的 index.html中 script 部分改成这样

let templateStr = "你家好,我是{{ name }},我今年{{ age }}岁啦";
let data = {
   name: "小猫猫",
   age: 2
}
GrManagData.render(templateStr,data);

在这里插入图片描述
这里 我们定义了模板字符串和data对象数据 然后传入我们的render
是不是和我们之前的mustache有点像啊 所以 其实很多时候难的只是一个开始
然后 我们在src下的 index.js中的GrManagData对象中将render改一下
在这里插入图片描述
这里 接一下这两个参数 然后 控制台输出一下
在这里插入图片描述
可以看到 我们输出的内容就在这里了

那么 我们要进行的就是 如何将模板字符串转成tokens
在这里插入图片描述
那么 我们之前也看过 tokens是根据 花括号去分割的
那么 我们就得有个机制去寻找花括号的位置

这里 我们先打开mustache.js 开开源码是怎么写的
这里面有一个类 叫 Scanner
在这里插入图片描述
顾名思义 扫描器
在这里插入图片描述
它通过这个来实现一个扫描字符串的功能

我们在src下创建一个 Scanner.js
在这里插入图片描述
编写代码如下

export default class Scanner{
    constructor(templateStr) {
        console.log("这是 Scanner 类",templateStr);
    }
}

这里 我们还是定义了一个类对象

然后 我们改写 src下的index.js代码如下

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
    }
}

我们先利用ES6的方法 import方式导入了Scanner
然后 通过new Scanner实例化了这个类
将templateStr作为参数

我们运行结果如下
在这里插入图片描述
可以看到 我们的constructor中输出的内容就正常展示了

说明我们的类对象已经实例化成功了 但官方代码中还有两个函数 scan和scanUtil
我们也是声明一下
在这里插入图片描述
然后 我们来写一下scanUtil
这个函数的作用在于 拿到指定符号的下标

编写 Scanner 代码如下

export default class Scanner{
    constructor(templateStr) {
        this.templateStr = templateStr;
        this.pos = 0;
        this.tail = templateStr;
    }
    //路过指定内容  没有返回值
    scan() {

    }

    //通过指针进行扫描 直到拆解 并返回扫描过程中的字符串
    scanUtil(endIndex) {
        while (this.tail.indexOf(endIndex) != 0) {
            this.pos++;
            this.tail = this.templateStr.substr(this.pos);
        }
    }
}

我们这里判断 如果 tail 中包含有指定的符号 就继续往下循环
while 循环只要条件成立 就会一直执行
然后 将pos加1
然后 通过 substr 从this.templateStr中取出对应下标的字符串
例如 第一次 是 pos 0 加一之后 去掉的就是 家好,我是{{ name }},我今年{{ age }}岁啦
然后 第二次 又pos加1 取到 好,我是{{ name }},我今年{{ age }}岁啦
一直向下转移

然后 我们在index.js中调用看看效果
index.js编写代码如下

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
        Scannerdom.scanUtil("{{");
        console.log(Scannerdom.pos);
    }
}

运行结果如下
在这里插入图片描述
最后 console.log(Scannerdom.pos); 输出了 6
那么 我们来看一下这个字符串
在这里插入图片描述
字符串是从零开始的 第六个 正好是 {{ 符号开始的地方

好用是好用 但是 这个函数还没完成 我们要将这个函数寻找时路过的函数收藏起来
我们将 scanUtil 函数改成这样

//通过指针进行扫描 直到拆解 并返回扫描过程中的字符串
scanUtil(endIndex) {
    const PosBackups = this.pos;
    while (this.tail.indexOf(endIndex) != 0) {
        this.pos++;
        this.tail = this.templateStr.substr(this.pos);
    }
    return this.templateStr.substring(PosBackups,this.pos);
}

这里 我们定义了一个常量 PosBackups 用来存住字符串开始的位置
然后 最后返回 调用 substring 获取指定的内容 指定的就是 从PosBackups到this.pos下标中间的内容
然后 我们尝试调用并输出一下返回值
index.js代码修改如下

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
        const str = Scannerdom.scanUtil("{{");
        console.log(str);
    }
}

运行结果如下
在这里插入图片描述
这里 我们 经过的内容就呈现出来了

然后呢 我们就需要看这个 scan 函数 这个函数其实功能比较弱
我们将 Scanner 中的scan代码编写如下

//路过指定内容  没有返回值
scan(tog) {
    if(this.tail.indexOf(tog) == 0) {
        this.pos += tog.length;
        this.tail = this.templateStr.substring(this.pos);
    }
}

判断 如果tail中没有包含指定符号了 然后就让pos加上特殊符号的长度
我们在index.js中这样写

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
        const str = Scannerdom.scanUtil("{{");
        Scannerdom.scan("{{");
        console.log(Scannerdom.pos);
    }
}

运行结果如下
在这里插入图片描述
输出的结果如下 就是 字符串的 {{ 自然是两个字符串 所以 它的长度是2 原本上次处理的pos是6 加上2 等于8 我们要在这个 8位置继续处理
所以 我们的逻辑就是 scanUtil和scan 反复调用 直到处理完为止

但首先 要将 scanUtil 的循环条件改一下
加一个

this.pos < this.templateStr.length

在这里插入图片描述
不然后面你就会发现它死循环了

然后 这个时候 我们将 src下的 index.js代码改成这样

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
        while(Scannerdom.pos != templateStr.length) {
            let sTr = Scannerdom.scanUtil("{{");
            console.log(sTr);
            Scannerdom.scan("{{");
        }
    }
}

运行结果如下
在这里插入图片描述
可以看到 他将我们读取的内容都分开了
但现在只读了 {{
没有读 }}
这里我们还是要切开一下
这样写
index.js

import Scanner from "./Scanner";
window.GrManagData = {
    render(templateStr,data) {
        console.log(templateStr,data);
        //实例化一个Scanner类对象
        let Scannerdom = new Scanner(templateStr);
        let sTr;
        while(Scannerdom.pos != templateStr.length) {
            sTr = Scannerdom.scanUtil("{{");
            console.log("文本",sTr);
            Scannerdom.scan("{{");
            sTr = Scannerdom.scanUtil("}}");
            console.log("变量",sTr);
            Scannerdom.scan("}}");
        }
    }
}

运行结果如下
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值