上文探究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>Documenttitle>
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
顾名思义 扫描器
它通过这个来实现一个扫描字符串的功能
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("}}");
}
}
}