vue原理

您所在的位置:网站首页 vue表达式引擎 vue原理

vue原理

#vue原理| 来源: 网络整理| 查看: 265

1. mustache模板引擎

因为该库的模板语法采用的 {{}} 酷似胡子,所以起名mustache (从mustache的git仓库搬来的一张图) 在这里插入图片描述

1-1 what ?

模板引擎是什么? 模板引擎是将数据转换为视图的一种解决方案 至于转换成什么样的视图,完全由程序员自己写出来的模板决定,如下一套数据,就可以转换为很多不同的视图 在这里插入图片描述

1-2 why ?

为什么要学习模板引擎? mustache是最早的模板引擎库,它的底层实现机理在当时是非常有创造性的、轰动性的,为后续模板引擎的发展提供了崭新的思路。要想学会其他更丰富类库的模板引擎,学习好mustache的模板引擎是很有必要的。

1-3 how ?

怎样学习mustache模板引擎的底层原理呢?

1-3-1 学会使用mustache模板引擎库

该库的使用方法和vue很相似,简单的给大家总结一下该库的使用: templateStr中的模板字符串,要使用mustache的模板语法

简单数据的嵌入 //简单插入直接使用{{变量名}} var templateStr = `我买了一个{{thing}},好{{mood}}啊`; var data = { thing: '华为手机', mood: '开心' }; var domStr = mustache.render(templateStr, data); 循环数据 // {{#arr}}...{{/arr}} 表示循环该部分内容,只有一个点代表数组中是基本数据 var templateStr = ` {{#arr}} {{.}} {{/arr}} `; var data = { arr: ['A', 'B', 'C'] }; var domStr = Mustache.render(templateStr, data); 复杂循环嵌套数据的嵌入 // 不需要使用students.name let templateStr = ` {{#students}} 学生{{name}}的爱好是 {{#hobbies}} {{.}} {{/hobbies}} {{/students}} ` let data = { students:[ {name:'Tom',age:15,hobbies:['吃饭',"睡觉"]}, {name:'Alice',age:15,hobbies:['吃饭',"睡觉","学习"]} ] } var domStr = mustache.render(templateStr, data); 布尔值的使用: //该使用类似于vue中的v-if:当m的值为false是该结构不显示,也不存在于dom树上,为ture是显示该结构 var templateStr = ` {{#m}} 你好 {{/m}} `; var data = { m: false }; var domStr = Mustache.render(templateStr, data); 对象 var templateStr = `我买了一个{{a.thing}}`; var data = { a:{ thing:"华为手机" } }; var domStr = mustache.render(templateStr, data); 1-3-2 掌握模板引擎的核心机理

在这里插入图片描述

第一步:将模板字符串解析为tokens数组 tokens数组是什么? js的一个嵌套数组,用来表示模板字符串。 ”{{“ 和 ”}}“ 不会体现在tokens中,模板语法插入的数据为name,其余普通字符为text,循环为”#“,空格换行也会包含在其中 1.模板字符串: 我买了一个{{thing}},好{{mood}}啊 1.tokens: [ ["text", "我买了一个"], ["name", "thing"], ["text", "好"], ["name", "mood"], ["text", "啊"], ] 2.模板字符串 {{#arr}} {{.}} {{/arr}} 2.tokens [ ["text", ""], ["#", "arr", [ ["text", ""], ["name", "."], ["text", ""] ]], ["text", ""] ]

该部分会有两个核心部分:①得到平铺tokens ②得到nesttokens(最终的token形状) 在这里插入图片描述

1. 根据templateStr模板字符串,得出平铺的tokens数组

平铺的tokens数组,没有嵌套,还不能完全代表templateStr字符串

function parseTemplateToTokens(templateStr){ const scanner = new Scanner(templateStr) let tokens = [] while(scanner.tail != ""){ let word = scanner.scanUtil('{{') tokens.push(['text',word]) scanner.scan("{{") word = scanner.scanUtil('}}') // {{内容}} 这里面的内容可能不是name if(word[0] === "#"){ tokens.push(['#',word.substring(1)]) }else if(word[0] === '/'){ tokens.push(['/',word.substring(1)]) }else{ if(word != "") tokens.push(["name",word]) } scanner.scan('}}') } return tokens } //用于遍历templateStr的类 class Scanner{ constructor(templateStr){ this.templateStr = templateStr // 遍历需要的指针 this.pos = 0 // 未遍历的字符串 this.tail = templateStr } // 跳过指定标记 scan(stopTag){ this.pos += stopTag.length this.tail = this.templateStr.substring(this.pos) } // 遍历模板字符串,收集指定字符,并返回 scanUtil(stopTag){ let startPos = this.pos // 不断修改tail,使 {{ 变为最开始的字符 while(this.pos // 栈 let sections = [] // 结果token let nestedTokens = [] // 当前插入数组:当前正在栈顶的token的插入项token[2]或者nestedTokens let collector = nestedTokens for(let i=0;i case '#': collector.push(token) sections.push(token) collector = token[2] = [] break case '/': sections.pop() collector = sections.length > 0 ? sections[sections.length-1][2] : nestedTokens break default: collector.push(token) } } return nestedTokens } 第二步:将tokens数组与data数据整合,得出dom字符串 function renderTemplate(tokens,data){ let domStr = '' for(let i=0;i domStr += token[1] }else if(token[0] === 'name'){ if(token[1].includes(".")){ domStr += lookup(data,token[1]) }else{ domStr += data[token[1]] } }else if(token[0] === "#"){ domStr += parseArray(token,data) } } return domStr } //根据str,寻找并返回obj中对应的数据 function lookup(obj,str){ // ".".split(".") = [[],[]] if(str !== "."){ let strArr = str.split(".") for(let i=0;i let targetArr = lookup(data,tokens[1]) let resStr = '' for(let i=0;i{.}}这种情况 resStr += renderTemplate(tokens[2],{...targetArr[i],".":targetArr[i]}) } return resStr }

大功告成!!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3