IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue源码-mustache模板引擎分析(四)-手写实现mustache库 -> 正文阅读

[JavaScript知识库]vue源码-mustache模板引擎分析(四)-手写实现mustache库

一.构建环境

(1)新建名为TemplateEngine的文件夹,然后
? ? ??

npm init??

npm i

npm i webpack@4 -D

npm i webpack-cli@3?-D

npm i webpack-dev-server@3?-D

使用webpack和webpack-dev-server构建?

-webpack侧重开发体验,结合webpack-dev-server实时更新

-nodeis调试控制台不太好用

-rollup更擅长于最终把几个js文件打包一起

-生成库UMD,同时在nodejs.js环境和浏览器环境中使用,实现UMD,只需一个“通用头”

?新建一个webpack.config.js文件

const path = require('path')
module.exports = {
    //模式,开发
    mode:'development',
    //入口
    entry:'./src/index.js',
    //打包到什么文件
    output:{
        filename:'bundle.js'
    },
    //配置一下webpack-dev-server
    devServer:{
        //静态文件根目录
        contentBase:path.join(__dirname,'www'),
        //不压缩
        compress:false,
        //端口号
        port:8080,
        //虚拟打包的路径,bundle.js文件没有真正的生成
        publicPath:'/xuni/'
    }
}

接着在package.json文件改动:

 "scripts": {
    "dev": "webpack-dev-server"
  },

刚刚看到关于学习源码的建议:

(1)源码思想要借鉴,而不要抄袭,要能够发现源码中书写的精彩的地方。

(2)将独立的功能拆写为独立的js文件中完成,通常是一个独立的类,每个单独的功能必须能独立的“单元测试”。

(3)应该围绕中心功能,先把主干完成,然后修剪枝叶

(4)功能并不需要一步到位,功能的扩展要一步步完成,有的非核心功能甚至不需要实现


二.将模板字符串变成tokens

?举个简单的例子~

我买了一个{{thing}},好{{mood}}啊

主要思想:

设置一个指针,从下标为0开始扫描,碰到 {{ 则停止扫描并返回之前经过的文字【“我买了一个”】,接着又继续扫描碰到 }}?则停止扫描并返回之前经过的文字【“thing”】,又继续干活碰到 {{?停止扫描并返回之前经过的文字【“,好”】,接着又继续扫描碰到 }}?则停止扫描并返回之前经过的文字【“mood”】,接下来以此类推。

新建一个Scanner.js文件,实现一个Scanner类【扫描器类】,类里实现两个方法:

一个是scanUtils方法,主要功能:让指针进行扫描,直到遇见指定内容结束,并且能够返回结束之前路过的文字;

另一个是scan方法,主要功能:走过指定内容,没有返回值

三个属性:

?templateStr 接收过来的模板字符串

?pos 起始位置(可以理解为指针)

tail 扫描过后的字符串,一开始设置为templateStr

export default class Scanner{
   constructor(templateStr){
     this.templateStr = templateStr;
     this.pos = 0;
     this.tail = this.templateStr
   }
   //功能弱,就是走过指定内容,没有返回值
   scan(tag){
        if(this.tail.indexOf(tag)==0){
            this.pos+=tag.length
            this.tail = this.templateStr.substring(this.pos)

        }
   }
   //让指针进行扫描,直到遇见指定内容结束,并且能够返回结束之前路过的文字
   scanUtils(stopTag){
    let pos_backup = this.pos   
    //当尾巴的开头不是stopTag的时候,就说明还没有扫描stopTag
    while(this.tail.indexOf(stopTag)!=0 && !this.eos()){
        this.pos++
        //改变尾巴为从当前指针这个字符开始,到后面全部字符
        this.tail = this.templateStr.substring(this.pos)
    }
    return this.templateStr.substring(pos_backup,this.pos)
   }
   //判断指针是否到头,返回布尔值
   eos(){
     return this.pos>=this.templateStr.length
   }
}


三.生成tokens数组

新建一个parseTemplateToTokens.js文件,向外暴露一个函数,函数名为parseTemplateToTokens,接收的参数为templateStr

var tokens = []

var words;

扫描器类已经准备好,接下来就让扫描器干活!

var scanner = new Scanner(templateStr)

思想:

当this.pos<this.templateStr.length时,先执行scanner.scanUtils('{{'),返回一个word用于收集开始标记出现之前的文字;接着判断文字内容不为空的话就push到tokens数组里,push的内容为['text',words],然后过双大括号scanner.scan("{{"),执行到这一步,意味着咱们进入到了 {{ 里,接着?words?=?scanner.scanUtils('}}'),这里的words就是{{}}中间的东西;接着判断一下首字符words[0],如果为#,tokens.push(['#',words.substring(1)]);如果为/,tokens.push(['/',words.substring(1)]);否则就返回tokens.push(['name',words]),接着过掉双大括号scanner.scan('}}'),最后就返回token。

import Scanner from './Scanner'
import nestTokens from './nestTokens'
export  default function parseTemplateToTokens(templateStr){
    var tokens = [];
    var words ;
    //创建扫描器
    var scanner = new Scanner(templateStr)
    //让扫描器工作
    while(!scanner.eos()){
        //收集开始标记出现之前的文字
        words = scanner.scanUtils('{{')
        //存起来
        if(words!=''){
            tokens.push(['text',words])
        }
        //过双大括号
        scanner.scan("{{")

        //收集开始标记出现之前的文字
        words = scanner.scanUtils('}}')
        //这里的words就是{{}}中间的东西,接着判断一下首字符
        if(words!=""){
            if(words[0]=='#'){
                //存起来,从下标为1的项开始存,因为下标为0的项是#
                tokens.push(['#',words.substring(1)])
            }else if(words[0]=='/'){
                //存起来,从下标为1的项开始存,因为下标为0的项是/
                tokens.push(['/',words.substring(1)])
            }else{
                tokens.push(['name',words])
            }
        }
        //过双大括号
        scanner.scan('}}')
    }

     return tokens;
    //return nestTokens(tokens);
}

四.将零散的tokens嵌套起来

新建一个nestTokens.js,向外暴露一个函数,函数名为nestTokens,接收的参数为tokens

?var?nestTokens?=?[];

??var?sections?=?[];

??var?collector?=?nestTokens;//这一步是关键,利用引用类型传递

思想:

利用栈(sections)先进后出的特点,遍历所有的tokens,

遇到一个 #,就把当前 token 放入这个栈中,让 collector 指向这个 token 的第三个元素。遇到下一个 # 就把新的 token 放入栈中,collector 指向新的 token 的第三个元素。遇到 / 就把栈顶的 token 移出栈,collector 指向移出完后的栈顶 token。

利用了栈的先进后出的特点,保证了遍历的每个 token 都能放在正确的地方,也就是 collector 都能指向正确的地址。

export default function nestTokens(tokens){
   var nestTokens = [];
   var sections = [];
   var collector = nestTokens;
   var token;
   for(let i=0;i<tokens.length;i++){
       token = tokens[i];
       switch(token[0]){
           case '#':
               collector.push(token);
               sections.push(token);
               collector = token[2] = []; 
               break;
           case '/':
              sections.pop();
              collector = sections.length>0?sections[sections.length-1][2]:nestTokens
               break;
            default:
              collector.push(token)
              break;    
       }
    }
    return nestTokens
}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-25 12:06:48  更:2021-08-25 12:06:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:12:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码