Vue源码学习笔记-mustache模板引擎(六)-数据与模板结合

137 阅读2分钟
数据与模板生成dom

原有tokens

微信截图_20210805162815.png

// renderTp.js 数据模板结合
/**
 * 让tokens变为dom字符串
 */
export default function (tokens, data) {
  // 结果字符串
  let convertedStr = ''
  tokens.forEach(i => {
    console.log(tokens)
    // 看类型
    if (i[0] === 'text') { // 文本直接将内容直接 拼接
      convertedStr += i[1]
    } else if (i[0] === 'name') {
      convertedStr += data[i[1]] // name 则需要将模板与数据结合
    }
  })
  return convertedStr
}
// parseTp2Tokens.js 结合类
import Scanner from './scaner'
import NextTokens from './nextTokens'
import RenderTp  from './renderTp'
// 增加了数据data
export default function (tpStr, data) {
  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(['name', words])
      }
    }
    // 跳过大括号
    ScannerInit.scan('}}')
  }
   // 折叠token
  const nextTokens = NextTokens(tokens)
  // 调用模板数据结合方法
  return RenderTp(nextTokens, data)
}
// 程序入口 基础算法
const tmpStr = `我想{{doSth}},{{doSth}}使我快乐!`;
const data = {
    doSth: "painting",
};
TpEngine.render(tmpStr, data);
// 扫描类无变化

// 创建扫描类
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
  }
}