VUE源码分析4 -- Mustache简介 和重写Scanner

2024-05-13 06:38

本文主要是介绍VUE源码分析4 -- Mustache简介 和重写Scanner,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面我们说Vue Dom实现,vue dom 兼容mustache项目。这个链接是mustache官方工程 mustache github地址

请看官方mustahce语法文档,变量前后添加两个大括号{{}},代表要侦测的数据。Vue官方也是兼容改特性。

下面我们要重零开始写Mustache,为什么要重零开始写mustache呢,因为我们追踪vue dom底层,mustache是跑不了的。

 

熟悉Mustache项目

首先我们先看看Mustache 案例,

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="https://unpkg.com/mustache@latest"></script>//引用mustache项目</head><body><div id="app"></div><div id="app1"></div></body><script type="text/javascript">console.log("here");var templateStr = `<ul>{{#arr}}<li>{{name}}的基本信息<div><p>姓名:{{name}}</p><p>性别:{{sex}}</p><p>年龄:{{age}}</p></div></li>{{/arr}}</ul>`;var data = {arr: [{"name": "小明","age": 12,"sex": "男"}, {"name": "小明","age": 12,"sex": "男"}, {"name": "小明","age": 12,"sex": "男"}]};var domStr = Mustache.render(templateStr, data);console.log(domStr);var container = document.getElementById('app');container.innerHTML=domStr;var templateStr1 = `		<ul>{{#arr}}<li>{{.}}</li>{{/arr}}</ul>`;var data1 ={arr:['A','B','C']}var domstr1 = Mustache.render(templateStr1, data1);console.log(domstr1);container.innerHTML +=domstr1;</script>
</html>

以上代码执行结果是

从上面给可以知道,{{name}},{{sex}},{{age}}是变量。并且{{#arr}}...{{/arr}}是否跟vue v-for相似。

 

Scanner类

下面分析mustache scanner类,为什么要先说scanner类呢,因为mustache把 模板字符串转成token,将tokens借和数据,解析为dom字符串。

例如,以下模板字符串是

<div><ol>{{#students}}<li>学生{{name}}的爱好是<ol>{{#hobbies}}<li>{{.}}</li>{{/hobbies}}</ol></li>{{/students}}</ol>
</div>

mustache内部先转成

[ ["text", "<div><ol>"],
["#", "students", [ ["text", "<li>学生"],
["name", "name"],
["text", "的爱好是<ol>"],
["#", "hobbies", [ ["text", "<li>"],
["name", "."],
["text", "</li>"],
]],
["text", "</ol></li>"],
]],
["text", "</ol></div>"] ]

为了验证以上步骤,我们修改官方mustache源码,把254代码改为

修改前:

修改后

然后网页输出信息为,可以看出此时模板字符串输出信息为tokens信息。

上面mustache源码在github链接下,请自行下载查看代码下载

 

下面我们开始重写Scanner类,

先创建Scanner.js文件,然后创建Scanner类,然后创建scan()和scanUtil()函数,scan函数是用于跳过某个字符,在mustache源码是跳过 {{ 和 }} 字符串。

export default class Scanner{constructor(templateStr){}scan(tag){//跳过 {{ 和 }}}scanUtil(stopTag){ //把字符串转成tokens}
}

scanUtil()函数功能用于把模板字符串转成tokens。

scan()是用于跳过某些字符串。

接下来我们继续写这两个函数代码,先看所有源码

Scanner.js

export default class Scanner{constructor(templateStr) {console.log(templateStr);this.templateStr = templateStr;//将模板字符串写道实例身上this.pos = 0;//当前位置this.tail = templateStr;}scan(tag){if(this.tail.indexOf(tag)==0){//第一位就是0this.pos += tag.length;this.tail = this.templateStr.substring(this.pos);}}scanUtil(stopTag){// console.log("scanUtil",stopTag);const pos_backup = this.pos;//当尾巴开头不是stopTag时候,说明没有扫描到到stopTag//写eos很必要,因为防止找不到,最后也要停止下来while(this.tail.indexOf(stopTag)!=0 && !this.eos()){this.pos++;//把尾巴改为当前扫描剩余字符串this.tail = this.templateStr.substring(this.pos);// console.log(this.tail);}return this.templateStr.substring(pos_backup,this.pos);}eos(){return this.pos >= this.templateStr.length;}
}

上面这个代码没什么好说的,都是基本截取字符串算法,自行手敲一次理解就行。

index.js

import Scanner from './Scanner.js'
//提供window全局方法
window.TemplateEngine = {render(templateStr,data){var scanner = new Scanner(templateStr);var word ;while(scanner.pos!=scanner.templateStr.length)// while(counter --){word = scanner.scanUtil("{{");console.log("word:",word);scanner.scan("{{");// console.log("word:",word);word = scanner.scanUtil("}}");console.log("word:",word);scanner.scan("}}");// console.log("word:",word);}}
}

在上面代码注意,在这里创建一个全局的对象TemplateEngine。然后一直循环截取字符串。

 

index.js

<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="/xuni/bundle.js" type="text/javascript" charset="utf-8"></script></head><body>213123</body><script type="text/javascript">var Str = "<h1>我买了一个{{thing}},好{{mood}}</h1>;"var data = {}TemplateEngine.render(Str)</script>
</html>

上面代码是创建一个模板字符串Str,把Str放到TemplateEngine.render()函数转换成tokens,然后查看浏览器console输出。

以上是mustache scanner类源码,其实很简单,就是把模板字符串转为tokens一些算法。感兴趣的小伙伴可以自行尝试,重写Scanner类源码地址在这里下载 点我下载

这篇关于VUE源码分析4 -- Mustache简介 和重写Scanner的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/984958

相关文章

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

vite搭建vue3项目的搭建步骤

《vite搭建vue3项目的搭建步骤》本文主要介绍了vite搭建vue3项目的搭建步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1.确保Nodejs环境2.使用vite-cli工具3.进入项目安装依赖1.确保Nodejs环境

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

前端缓存策略的自解方案全解析

《前端缓存策略的自解方案全解析》缓存从来都是前端的一个痛点,很多前端搞不清楚缓存到底是何物,:本文主要介绍前端缓存的自解方案,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、为什么“清缓存”成了技术圈的梗二、先给缓存“把个脉”:浏览器到底缓存了谁?三、设计思路:把“发版”做成“自愈”四、代码

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Vue3视频播放组件 vue3-video-play使用方式

《Vue3视频播放组件vue3-video-play使用方式》vue3-video-play是Vue3的视频播放组件,基于原生video标签开发,支持MP4和HLS流,提供全局/局部引入方式,可监听... 目录一、安装二、全局引入三、局部引入四、基本使用五、事件监听六、播放 HLS 流七、更多功能总结在 v

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

vue监听属性watch的用法及使用场景详解

《vue监听属性watch的用法及使用场景详解》watch是vue中常用的监听器,它主要用于侦听数据的变化,在数据发生变化的时候执行一些操作,:本文主要介绍vue监听属性watch的用法及使用场景... 目录1. 监听属性 watch2. 常规用法3. 监听对象和route变化4. 使用场景附Watch 的