mustache学习笔记

mustache基本使用

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>mustache基本使用</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/mustache.js/4.1.0/mustache.js"></script>
  </head>
  <body>
    <div id="container"></div>
    <script>
      let templateStr = `
        <div>
          <h1>{{title}}</h1>
          {{#user}}
            <p>姓名:{{name}}</p>
            <p>性别:{{sex}}</p>
            <p>爱好:
              {{#hobby}}
                <span>{{.}}</span>
              {{/hobby}}
            <p>
          {{/user}}
          {{#isShow}}
            <p>卷不动啦,好烦啊</p>
          {{/isShow}}
        </div>
      `;
      let data = {
        title: "名单",
        user: [
          {
            name: "www",
            sex: "男",
            hobby: ["1", "2", "3"],
          },
          {
            name: "qqq",
            sex: "女",
            hobby: ["1", "2", "3"],
          },
        ],
        isShow: false,
      };
      let domStr = Mustache.render(templateStr, data);
      let container = document.getElementById("container");
      container.innerHTML = domStr;
    </script>
  </body>
</html>

mustache源码仿写

index.js

import getTokens from './getTokens.js'
import renderTemplate from './renderTemplate.js'

window.mustache = {
  render(templateStr, data) {
    // 将模板字符串转换成tokens
    let tokens = getTokens(templateStr)
    // 将tokens转换成dom字符串
    let domStr = renderTemplate(tokens, data)
    return domStr
  }
}

scanner.js

// 创建扫描器类
export default class Scanner {
  constructor(str) {
    this.templateStr = str
    this.pos = 0
    this.tail = str
  }

  // 扫描模板字符串,返回扫描内容(源码中scanUtil方法)
  scan(stopTag) {
    let startPos = this.pos
    while (this.pos < this.templateStr.length && this.tail.indexOf(stopTag) !== 0) {
      this.pos++
      this.tail = this.templateStr.substr(this.pos)
    }
    return this.templateStr.slice(startPos, this.pos)
  }

  // 跳过大括号(源码中scan方法)
  jump(tag) {
    if (this.tail.indexOf(tag) === 0) {
      this.pos = this.pos + tag.length
      this.tail = this.templateStr.substr(this.pos)
    }
  }
}

getTokens.js

import Scanner from './scanner.js';

export default function getTokens(templateStr) {
  let lastTokens = []
  let scanner = new Scanner(templateStr)
  let str = ""
  while (scanner.pos < templateStr.length) {
    str = scanner.scan("{{")
    if (str !== "") {
      lastTokens.push(['text', str])
    }
    scanner.jump("{{")
    str = scanner.scan("}}")
    if (str !== "") {
      if (str[0] === "#") {
        lastTokens.push(['#', str.substr(1)])
      } else if (str[0] === "/") {
        lastTokens.push(['/', str.substr(1)])
      } else {
        lastTokens.push(['name', str])
      }
    }
    scanner.jump("}}")
  }
  let nextTonkens = []
  let sections = []
  let collector = nextTonkens
  for (let i in lastTokens) {
    let token = lastTokens[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] : nextTonkens
        break
      default:
        collector.push(token)
    }
  }
  return nextTonkens
}

renderTemplate.js

function handleLoop(token, data) {
  let result = ""
  let arr = data[token[1]]
  for (let i in arr) {
    result = result + renderTemplate(token[2], {
      ...arr[i],
      ".":arr[i]
    })
  }
  return result
}

export default function renderTemplate(tokens, data) {
  let result = ""
  for (let i in tokens) {
    let token = tokens[i]
    if (token[0] == "text") {
      result = result + token[1]
    } else if (token[0] == "name") {
      result = result + data[token[1]]
    } else if (token[0] == "#") {
      result = result + handleLoop(token, data)
    }
  }
  return result
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值