Skip to content

模板语法解析

写在前面

编写这部分文档时一直报错:[plugin:vite:vue] Error parsing JavaScript expression: Expecting Unicode escape sequence \uXXXX. (1:2),但又找不到哪里写的有问题,最后通过搜索发现是这部分的模板语法被转义了

解决方案:https://github.com/vuejs/vitepress/discussions/3724

在配置文件添加以下内容:

import { defineConfig } from 'vitepress'

export default defineConfig({
  markdown: {
    config(md) {
      const defaultCodeInline = md.renderer.rules.code_inline!
      md.renderer.rules.code_inline = (tokens, idx, options, env, self) => {
        tokens[idx].attrSet('v-pre', '')
        return defaultCodeInline(tokens, idx, options, env, self)
      }
    }
  }
})

问题描述

假设模板字符串使用双大括号 {{key}} 作为占位符。例如:

js
const template="Hello, {{name}}! You have {{count}} new messages."

给出数据,替换模板中的内容

基本模板解析器代码

js
function parseTemplate(template, data){
  return template.replace(/{{\s*(\w+)\s*}}/g,(match, key)=> {
    return key in data ? data[key] : match; // Replace if key exists, otherwise keep original
  });
}

const template = "Hello, {{name}}! You have {{count}} new messages.";
const data = { name: "Alice", count: 5 };

const result = parseTemplate(template, data);
console.log(result); // Output: "Hello, Alice! You have 5 new messages."

/{{\s*(\w+)\s*}}/g

  • {{}}:匹配占位符的边界。

  • \s*:允许边界内外有空格。

  • (\w+):匹配占位符中的键名。

嵌套模板解析

如果需要支持嵌套模板(例如模板中替换后的值再次包含模板语法),可以递归调用:

js
function parseTemplate(template, data){
  let result = template;
  let matches;
  const regex = /{{\s*(\w+)\s*}}/g;

  while((matches = regex.exec(result))!== null){
    const [placeholder, key] = matches;
    if(key in data){
      result = result.replace(placeholder, data[key]);
    }
  }

  return result;
}

const template = "Hello, {{name}}! Your role is {{role}}.";
const data = { name: "Alice", role: "{{title}}", title: "Engineer" };

const result = parseTemplate(template, data);
console.log(result); // Output: "Hello, Alice! Your role is Engineer."

高级功能扩展

支持默认值

允许在占位符中定义默认值,例如 {{key:defaultValue}}

js
function parseTemplate(template, data){
  return template.replace(
    /{{\s*(\w+)(?::([^}]*))?\s*}}/g,
  (match, key, defaultValue)=> {
      return key in data ? data[key] : defaultValue || match;
    }
  );
}

const template = "Hello, {{name:Guest}}! You have {{count:0}} new messages.";
const data = { count: 5 };

const result = parseTemplate(template, data);
console.log(result); // Output: "Hello, Guest! You have 5 new messages."

支持函数值

允许 data 中的值为函数,通过调用函数动态生成值

js
function parseTemplate(template, data){
  return template.replace(/{{\s*(\w+)\s*}}/g,(match, key)=> {
    const value = data[key];
    return typeof value === "function" ? value(): value || match;
  });
}

const template = "Hello, {{name}}! The time is {{time}}.";
const data = { name: "Alice", time:()=> new Date().toLocaleTimeString()};

const result = parseTemplate(template, data);
console.log(result); // Output: "Hello, Alice! The time is 10:23:45 AM."

参考

chatgpt4o