JS模板编译的实现详情

目录
  • 前言
  • 模板编译的简单实现
  • 模板编译
    • 1、构建模板生成函数
    • 2、正则替换

前言

编译是一种格式变成另一种格式的过程。编译会导致好的结果,比如书写简单的代码,编译出来复杂的代码;或者提高代码的使用性能

这里只聊聊模板编译。

模板编译的简单实现

写一个最简单的模板

<p>Hello, {{name}}!</p>

这个模板用数据{name: "world"}渲染后的结果是:

<p>Hello, world!</p>

解决方法:最简单的方案,正则替换就行了

const compile = function(template, data) {
  return template.replace(/{{(.+?)}}/g, (match, key) => data[key])
}

const template = "<p>Hello, I'm {{name}}! {{age}} years old!</p>"
const data = {
  name: "hayes",
  age: 18
}
const result = compile(template, data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

缺点很明显,除了正则替换字段,其他啥都干不了,

来看看简单的嵌套需求:

模板:

<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>

渲染数据;

const data = {
  user: {
    name: "hayes",
    age: 18
  }
}

现在再使用上面的方法,就失效了。还用正则的话,会很难做。因为需要做语法/词法分析,来看看大括号内写的是什么了。

模板编译

其实对于上述的模板,也可以使用如下方式来写:

const compile = function(data) {
  return `<p>Hello, I'm ${data.name}! ${data.age} years old!</p>`
}

好处:只需一次编译,之后再使用就只需要直接填充数据即可。而且也方便支持data.user.name这种形式。

工具:使用new Function生成函数

生成一个函数,传入x和 y,执行return x + y来获得求和的功能

const fn = new Function("x", "y", "return x + y");

打印fn可以看到输出的内容如下:

ƒ anonymous(x,y) {
return x + y
}

1、构建模板生成函数

传入模板字符串,通过new Function方式返回一个新函数。新函数接收一个obj对象

const compile = function(template) {
  // 模板字符串
  let result = "";
  // ...
  return new Function("obj", result);
}

2、正则替换

{{xxx}}找出来,替换为obj.xxx

const compile2 = function(template) {
  // 模板字符串
  let result = template.replace(/{{(.+?)}}/g, (match, key) => {
    return `obj.${key}`
  });
  result = `return "${result}"`;
  return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);

此时,函数打印如下:

ƒ anonymous(obj
) {
return "<p>Hello, I'm obj.user.name! obj.user.age years old!</p>"
}

我们需要把字符串中的obj.user.nameobj.user.age变成动态的。

修改一下正则

const compile2 = function(template) {
  // 模板字符串
  let result = template.replace(/{{(.+?)}}/g, (match, key) => {
    return `" + obj.${key} + "`  // 前后添上加号
  });
  result = `return "${result}"`;
  return new Function("obj", result);
}
const template2 = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render2 = compile2(template2)
console.log(render2);

再来看看函数的打印:

ƒ anonymous(obj
) {
return "<p>Hello, I'm " + obj.user.name + "! " + obj.user.age + " years old!</p>"
}

最终代码:

const compile = function(template) {
  // 模板字符串
  let result = template.replace(/{{(.+?)}}/g, (match, key) => {
    return `" + obj.${key} + "`
  });
  result = `return "${result}"`;
  return new Function("obj", result);
}
const template = "<p>Hello, I'm {{user.name}}! {{user.age}} years old!</p>"
const render = compile(template)

const data = {
  user: {
    name: "hayes",
    age: 18
  }
}
const result = render(data)
console.log(result); // <p>Hello, I'm hayes! 18 years old!</p>

渲染结果:

"<p>Hello, I'm hayes! 18 years old!</p>"

到此这篇关于JS模板编译的实现详情的文章就介绍到这了,更多相关JS模板编译 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JS ES新特性 模板字符串

    目录 1.模板字符串是什么 2.多行模板字符串 2.1带表达式的模板字符串 3.带标签的模板字符串 4.原始字符串 5.判断是否包含某字符串 5.1includes()方法 5.2startsWith()方法 5.3endsWith()方法 1.模板字符串是什么 模板字符串( Template String )是增强版的字符串,使用反引号(```)来代替谱通字符串中的用双引号和单引号.它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量. 普通用法如下所示: // 使用 `

  • Node.js的路由、EJS模板引擎、GET和POST请求讲解

    1.路由 官方解释: 路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET.POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问. 非官方解释 : 路由指的就是针对不同请求的 URL,处理不同的业务逻辑. Get 请求路由示例图 2.初识 EJS 模块引擎 我们学的 EJS 是后台模板,可以把我们数据库和文件读取的数据显示到 Html页面上面.它是一个第三方模块,需要通过 npm 安装 https://www.npmjs.com/package/

  • JS模板编译的实现详情

    目录 前言 模板编译的简单实现 模板编译 1.构建模板生成函数 2.正则替换 前言 编译是一种格式变成另一种格式的过程.编译会导致好的结果,比如书写简单的代码,编译出来复杂的代码:或者提高代码的使用性能. 这里只聊聊模板编译. 模板编译的简单实现 写一个最简单的模板 <p>Hello, {{name}}!</p> 这个模板用数据{name: "world"}渲染后的结果是: <p>Hello, world!</p> 解决方法:最简单的方案

  • 使用JavaScript获取Django模板指定键值数据

    Django中利用js来操作数据的常规操作一般为点(.)操作符来获取字典或列表的数据,一般如{{data.0}},{{data.arg}} 但有时如果数据是嵌套类型的数据时,直接获取某个值就变得困难了,比如下面的格式要获取 correct中qxl的值 startArgsSet={"correct":{"qxl":0,"kkx":0},"reliable":{"qxl":0,"kkx":0

  • 基于JS正则表达式实现模板数据动态渲染(实现思路详解)

    最近业务上需要动态渲染模板数据,好久没写前端代码了,有点生疏,将思路简单写下来,防老: 一.业务需求: 1.前端后端定义好模板以及变量名,保存数据库 2.订单数据是前端根据支付结果获取的,最终渲染完的数据模板需要调用打印机打印出来 3.模板相对商家来说比较固定,但是每个商家需要的模板都有可能不一样,所以需要每次登录后,查询一次模板缓存前端,后续每次支付后,动态渲染数据即可 二.考点: 1.正则表达式 2.精简代码量,尽量减少前端的工作量​ 三.实现思路: 1.需要渲染数据的模板,以${变量名}区

  • 浅谈laytpl 模板空值显示null的解决方法及简单的js表达式

    laytpl 模板语法 {{ d.field }} 输出一个普通字段,不转义html 官方的说明 但d.field 为空时会显示null laytpl 模板 空值显示null的解决方法 {{d.giftName}} 模板中当giftName为空是 页面上会显示 null 字符串 1可以在模板中直接使用三目表达式来判断字符串是否为空. 如下: {{!d.giftName?" ":d.giftName}} 2还有一种方法,用到一个 || 运算符 {{d.giftName||" &

  • Spring boot整合jsp和tiles模板示例

    目录 首先贴上我的pox.xml文件,有详细的支持注释说明 <strong><?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation

  • 基于Node.js模板引擎教程-jade速学与实战1

    环境准备: 全局安装jade: npm install jade -g 初始化项目package.json: npm init --yes 安装完成之后,可以使用 jade --help 查看jade的命令行用法 一.在项目目录下新建index.jade文件 inde.jade代码: doctype html html head meta(charset='utf-8') title body h3 欢迎学习jade 1,标签按照html的缩进格式写 2,标签的属性可以采用圆括号 3,如果标签有

  • 详解Node.js模板引擎Jade入门

    Jade是Node.js的一个模板引擎,它借鉴了Haml的很多地方,所以语法上和Haml比较相近.并且,Jade也支持空格. 1.标签 在Jade里,一行开头的任何文本都被默认解释成HTML标签.并且你只需要你写开始标签--注意:不需要加"<>".因为Jade会帮我们渲染闭合和开始标签.例如: body div h1 Jade是Node.js的一个模板引擎 p 它借鉴了Haml的很多地方,所以语法上和Haml比较相近. div footer © Pandora 上面的Jad

  • vue中template模板编译的过程全面剖析

    目录 简述过程 vue的渲染过程 parse parse过程总结 generate生成render函数 简述过程 vue template模板编译的过程经过parse()生成ast(抽象语法树),optimize对静态节点优化,generate()生成render字符串 之后调用new Watcher()函数,用来监听数据的变化,render 函数就是数据监听的回调所调用的,其结果便是重新生成 vnode. 当这个 render 函数字符串在第一次 mount.或者绑定的数据更新的时候,都会被调

  • vue2从template到render模板编译入口详解

    目录 正文 1.template:模板获取 2.createCompiler:核心参数 3.createCompileToFunctionFn:缓存处理 4.compile:参数合并 小结 正文 在vue的渲染过程中,渲染核心逻辑是vm._update(vm._render(), hydrating),通过vm._render的执行获取到vNode,再通过vm._update的执行来将vNode渲染成真实视图. 其中,render函数的来源是: (1)用户手写: (2)通过vue-loader引

  • C#执行js动态编译的方法

    本文实例讲述了C#执行js动态编译的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: using System;  using System.CodeDom.Compiler;  using System.Collections.Generic;  using System.Linq;  using System.Reflection;  using System.Text;  using System.Threading.Tasks;    namespace webpro

  • 快速解决vue.js 模板和jinja 模板冲突的问题

    jinjia和vue.js默认的模板转义符都是{{}} 目前的解决办法是修改vue.js的转义符,将原来的{{}}替换为其他标签,我改为{[]} 版本1.x和2.x方法如下 // 1.x Vue.config.delimiters = ['{[', ']}'] // 2.x new Vue({ delimiters: ['{[', ']}'] }) 以上这篇快速解决vue.js 模板和jinja 模板冲突的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 深入了解Vue3模板编译原理

    目录 Parse Transform cacheHandlers hoistStatic prefixIdentifiers PatchFlags hoists type 变化 Codegen 代码生成模式 静态节点 帮助函数 helpers helpers 是怎么使用的呢? 如何生成代码? Vue 的编译模块包含 4 个目录: compiler-core compiler-dom // 浏览器 compiler-sfc // 单文件组件 compiler-ssr // 服务端渲染 其中 com

  • js 实现拖拽排序详情

    目录 1.前言 2.实现 3.为何不使用HTML拖放API实现? 4.总结 1.前言 拖拽排序对于小伙伴们来说应该不陌生,平时工作的时候,可能会选择使用类似Sortable.js这样的开源库来实现需求.但在完成需求后,大家有没有没想过拖拽排序是如何实现的呢?我花了点时间研究了一下,今天分享给大家. 2.实现 { margin: 0; padding: 0; box-sizing: border-box; } .grid { display: flex; flex-wrap: wrap; marg

  • Vue.js 模板语法和数据绑定

    目录 模板语法 数据绑定 el的两种写法 data的两种写法 模板语法 Vue 模板语法有两大类 插值语法: 功能:用于解析标签体内容 写法:{{xxx}},xxx是js表达式,可以读取到 data 中属性 指令语法: 功能:用于解析标签(标签属性.标签体内容.绑定事件...) 写法:v-bind:href="xxx" 或简写为 :href="xxx",xxx是js表达式,可以读取到 data 中属性 <!DOCTYPE html> <html l

随机推荐