基于栈的概念
栈FIlO 先进后出
折叠结果
// nextTokens.js 利用收集器方式 最终版本
/**
* 折叠tokens
* 栈底数组第一位,栈顶-数组尾
*/
export default function nextTokens(tokens) {
// console.log(tokens)
// 结果数组
let nestedTokens = []
// 栈数字组,存放小token,栈顶(靠近端口的,最新进入的)tokens数组中当前操作的这个tokens小数组
let sections = []
// 收集器,初始指向结果数组,引用类型值,所以指向同一个数组
// 收集器指向会变化,当遇见#的时候,收集器会指向这个token的下表为2的新数组
let collector = nestedTokens
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i]
switch (token[0]) {
case '#':
// console.log(token, '------------')
// 收集器里放入token,由于是引用类型,所以同时可以push到nestedTokens最终结果中
collector.push(token)
// 入栈
sections.push(token)
// console.log('collector', collector,' nestedTokens', nestedTokens, '-----#---0----')
// 收集器更换, 给token添加下标为2的数组,并更换收集器指向,改变了collector的引用指向,切断了collector,与最终结果的关系
// 下面等同于 token[2] = []; collector = token[2]
collector = token[2] = []
// console.log('collector', collector,' nestedTokens', nestedTokens, '-----#----1---')
// console.log(nestedTokens)
break;
case '/':
// console.log(sections, '-------------')
// 出栈,pop()会返回弹出的项目
sections.pop()
// 改变收集器为栈结构队尾(队尾为栈顶),那项的下标为2的数组
collector = sections.length > 0 ? sections[sections.length -1][2] : nestedTokens
break;
default:
console.log('collector', collector,' nestedTokens', nestedTokens, '-----default-------')
// 如果 没进入栈,则直接结果里存,如果如栈了 就要往栈里 也就是 栈的 【2】数组里存
collector.push(token)
}
}
return nestedTokens
}
// nextTokens.js 同上 比较好理解的方式
/**
* 折叠tokens
* 栈底数组第一位,栈顶-数组尾
*/
export default function nextTokens(tokens) {
// 结果数组
let nestedTokens = []
// 栈数字组,存放小token,栈顶(靠近端口的,最新进入的)tokens数组中当前操作的这个tokens小数组
let sections = []
// 收集器
nestedTokens
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i]
switch (token[0]) {
case '#':
// 给这个下标项目为2的项创建一个数组,以收集元素
// 因为 ["#", "students", 此位置为2是数组]
token[2] = []
console.log(token[1],'入栈拉')
// 压栈(入栈)
sections.push(token)
break;
case '/':
// 出栈,pop()会返回弹出的项目
let section = sections.pop()
console.log(section[1],'出栈拉')
// 刚刚弹出的项还没加入到结果数组中
nestedTokens.push(section)
break;
default:
// 判断,栈队列当前情况
if (sections.length === 0) {
// 没有就返回到结果里
nestedTokens.push(token)
} else {
// 栈里已经有内容了,就在下表为2项目里放token
sections[sections.length - 1][2].push(token)
}
}
}
return nestedTokens
}
复制代码
// parseTp2Tokens.js 模板字符串转tokens
import Scanner from './scaner'
// 折叠token
import nextTokens from './nextTokens'
export default function (tpStr) {
const tokens = []
// 创建扫描器
const ScannerInit = new Scanner(tpStr)
let words;
// 扫描器
while (!ScannerInit.eos()) {
// 收集开始出现前的文字
words = ScannerInit.scanUtil('{{')
if (words !== '') {
// 存储
tokens.push(['text', words])
}
// 跳过大括号
ScannerInit.scan('{{')
words = ScannerInit.scanUtil('}}')
// 收集标记之间的
if (words !== '') {
// 存储
if (words[0] === '#') {
// 从下标为1 跳过#号开始存
tokens.push(['#', words.substring(1)])
} else if (words[0] === '/') {
tokens.push(['/', words.substring(1)])
} else {
tokens.push(['text', words])
}
}
// 跳过大括号
ScannerInit.scan('}}')
}
// 折叠token
return nextTokens(tokens)
}
复制代码
// UMD模块改进 nextTokens.js
import parseTp2Tokens from './parseTp2Tokens'
window.TpEngine = {
render(tpStr, data) {
console.log('render函数被调用,命令Scanner工作')
console.log(parseTp2Tokens(tpStr))
}
}
复制代码
// 首页tokens index.html
const tmpStr = `<div>
<ol>
{{#students}}
<li>
学生{{item.name}}的爱好<ol>
{{#item.hobbies}}
<li>
{{.}}
</li>
{{/item.hobbies}}
</ol>
</li>
{{/students}}
</ol>
</div>`
TpEngine.render(tmpStr)
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END