Vue源码学习笔记-mustache模板引擎(四)-拆分token

239 阅读1分钟

拆分token结果

tokens.png

// parseTp2Tokens.js 模板字符串转tokens
import Scanner from './scaner'
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('}}')
  }
  console.log(tokens)
}

// 创建扫描类
export default class Scanner {
  constructor(tpStr) {
    console.log('render函数里 调用Scanner')
    this.tpStr = tpStr
    // 建立指针
    this.pos = 0
    // 尾部字符串,默认为整个字符串
    this.tail = tpStr
  }
  scan(tag) {
    if (this.tail.indexOf(tag) === 0) {
      // tag 有多长,指针就往后移动几位
      this.pos += tag.length
      // tail1也要调整
      this.tail = this.tpStr.substring(this.pos)
    }
  }
  // 让指针扫描吗,直到内容结束,并返回之前查到的文字
  scanUtil(stopTag) {
    // 记录指针原始位置
    const pos_backup = this.pos
    // 当尾巴的开头不是 stopTag的时候,就说明没有扫描到stopTag
    // 写 && 很有必要,防止越界 
    while (this.tail.indexOf(stopTag) !== 0 && !this.eos()) {
      this.pos++
      //
      // console.log('pos--------------', this.pos)
      // 重新计算尾巴,从指针开始,到最后一位(第一个参数是启始,第二个是个数,如果省略了该参数)
      this.tail = this.tpStr.substr(this.pos)
    }
    // 返回位于 String 对象中指定位置的子字符串(两个指定下标之间的字符,如果省略该参数,那么返回的子串会一直到字符串的结尾)
    return this.tpStr.substring(pos_backup, this.pos)
  }
  // 指针防止越界
  eos() {
    return this.pos >= this.tpStr.length
  }
}
// UMD 封装
import parseTp2Tokens from './parseTp2Tokens'
window.TpEngine = {
  render(tpStr, data) {
    console.log('render函数被调用,命令Scanner工作')
    parseTp2Tokens(tpStr)
  }
}
// 程序数据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)