当前位置: 首页 > news >正文

网站模板插件惠州seo报价

网站模板插件,惠州seo报价,wordpress 插件,dedecms学校网站模板免费下载个人简介 👀个人主页: 前端杂货铺 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

文章目录

    • 前言
    • 将数据变为视图
      • 纯DOM法
      • 数组的 join 方法
      • ES6 的反引号法
    • mustache 基本使用
    • mustache 核心理念
    • 手写 mustache
      • 搭建环境
      • 手撕 mustache
    • 总结

前言

知其然知其所以然,本篇文档我们来学习 Vue 源码之 mustache 模板引擎。

将数据变为视图

纯DOM法

纯 DOM 方法的关键点在于使用 createElement 创建节点和使用 appendChild 向节点的子节点列表的末尾添加新的子节点。

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Document</title>
</head>
<style>.hd {color: orange;}.bd {color: skyblue;}
</style>
<body>
<ul id="list">
</ul>
<script>// 定义人的基本信息const arr = [{"name": "小明", "age": 30, "gender": "male"},{"name": "小小", "age": 20, "gender": "female"},{"name": "小山", "age": 10, "gender": "male"},]// 获取 ulconst list = document.getElementById('list');// 循环人的基本信息数组,把信息构建至页面中for (let i = 0; i < arr.length; i++) {// 创建li标签let oLi = document.createElement("li");// 创建hd这个div,存放 “xx的基本信息”let hdDiv = document.createElement("div");hdDiv.className = 'hd';hdDiv.innerText = arr[i].name + '的基本信息';// 创建bd这个div,存放人的详细基本信息let bdDiv = document.createElement("div");bdDiv.className = 'bd';// 人的基本信息(姓名、年龄、性别)放入 p 标签中let p1 = document.createElement("p");p1.innerText = '姓名:' + arr[i].name;bdDiv.appendChild(p1);let p2 = document.createElement("p");p2.innerText = '年龄:' + arr[i].age;bdDiv.appendChild(p2);let p3 = document.createElement("p");p3.innerText = '性别:' + arr[i].gender;bdDiv.appendChild(p3);oLi.appendChild(hdDiv);hdDiv.appendChild(bdDiv);list.appendChild(oLi);}
</script>
</body>
</html>

在这里插入图片描述


数组的 join 方法

数组 join 方法关键在于字符串的拼接。

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Document</title>
</head>
<body>
<ul id="list">
</ul>
<script>// 定义人的基本信息const arr = [{"name": "小明", "age": 30, "gender": "male"},{"name": "小小", "age": 20, "gender": "female"},{"name": "小山", "age": 10, "gender": "male"},]const list = document.getElementById('list');for (let i = 0; i < arr.length; i++) {list.innerHTML += ['<li>','  <div class="hd"></div>' + arr[i].name + '的信息</div>','  <div class="bd">','    <p>姓名:' + arr[i].name + '</p>','    <p>年龄:' + arr[i].age + '</p>','    <p>性别:' + arr[i].gender + '</p>','  </div>','</li>'].join('')}
</script>
</body>
</html>

在这里插入图片描述


ES6 的反引号法

ES6 反引号法可以更优雅的把 html 标签写入字符串中。

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Document</title>
</head>
<body>
<ul id="list"></ul>
</body>
<script>// 定义人的基本信息const arr = [{"name": "小明", "age": 30, "gender": "male"},{"name": "小小", "age": 20, "gender": "female"},{"name": "小山", "age": 10, "gender": "male"},]const list = document.getElementById('list');for (let i = 0; i < arr.length; i++) {list.innerText += `<li><div class="hd">${arr[i].name}的基本信息</div><div class="bd"><p>姓名:${arr[i].name}</p><p>性别:${arr[i].gender}</p><p>年龄:${arr[i].age}</p></div></li>`}
</script>
</html>

在这里插入图片描述


mustache 基本使用

mustache.js 是一个简单强大的 JavaScript 模板引擎,使用它可以简化在 js 代码中的 html 编写。

基本使用

// 初始化
npm	init -y
// 安装 mastache
npm install mastache

mustache 的使用非常简单, 使用花括号 {{#xxx}} 开始,使用 花括号 {{/xxx}} 结束,中间包裹着 key 值,最后再使用 mustache.render(templateStr, data),完成数据的渲染。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>Document</title></head><body><div id="container"></div><!-- 模版 --><script type="text/template" id="myTemplate"><ul>{{#arr}}<li><div class="hd">{{name}}的基本信息</div><div class="bd"><p>姓名:{{name}}</p><p>性别:{{gender}}</p><p>年龄:{{age}}</p></div></li>{{/arr}}</ul></script><script type="module">import mustache from "./node_modules/mustache/mustache.mjs";// 获取模版const templateStr = document.getElementById("myTemplate").innerHTML;// 定义数据const data = {arr: [{ name: "小明", age: 30, gender: "male" },{ name: "小小", age: 20, gender: "female" },{ name: "小山", age: 10, gender: "male" },],};const domStr = mustache.render(templateStr, data);const container = document.getElementById("container");container.innerHTML = domStr;</script></body>
</html>

在这里插入图片描述


mustache 核心理念

tokens 是一个 JS 的嵌套数组,是模板字符串的 JS 表示。

对于一维模板字符串及对应 tokens,如下:

在这里插入图片描述

对于二维模板字符串及 tokens 如下:

在这里插入图片描述

mustache 库底层重点要做的两件事情

  1. 将模板字符串编译为 tokens 形式
  2. 将 tokens 结合数据,解析为 dom 字符串

在这里插入图片描述


手写 mustache

搭建环境

总体目录如下:

在这里插入图片描述

新建一个文件夹,打开终端,输入以下命令后回车以初始化项目。

npm init -y

安装依赖。

npm install

安装 webpack、webpack-dev-server、webpck-cli。

npm i webpack@4 webpack-dev-server@3 webpack-cli@3

修改 package.json 文件的 dev 内容如下,更换项目启动方式。

{"name": "templateengine","version": "1.0.0","main": "index.js","scripts": {"dev": "webpack-dev-server"},"keywords": [],"author": "","license": "ISC","description": "","devDependencies": {"webpack": "^4.47.0","webpack-cli": "^3.3.12","webpack-dev-server": "^3.11.3"}
}

手动创建 webpack.config.js 文件,并进行如下配置。

const path = require("path");module.exports = {// 模式,开发mode: "development",// 入口entry: "./src/index.js",// 打包到什么文件output: {filename: "bundle.js",},// 配置一下 webpack-dev-serverdevServer: {// 静态文件根目录contentBase: path.join(__dirname, "www"),// 压缩compress: false,// 端口号port: 8080,// 虚拟打包到路径,bundle.js文件没有真正的生成publicPath: "/xuni/",},
};

手动创建 www 文件及 www/index.html 文件,添加如下内容。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><h1>你好,这里是前端杂货铺!</h1><script src="/xuni/bundle.js"></script></body>
</html>

手动创建 src 文件及 src/index.js 文件,添加如下内容。

console.log('hello');

OK,此时基本配置已完成,接下来我们打开终端键入 npm run dev 命令回车,然后访问 8080 端口。

在这里插入图片描述


手撕 mustache

手撕 mustache 源码地址

接下来,我们来手写简易版的 mustache,体验一下模版引擎的设计巧妙之处。

代码文件结构如下:

在这里插入图片描述

index.html 文件中,我们编写 模版字符串数据,并使用 TemplateEngine.render(模板字符串, 数据) 来获取 dom 数据,之后添加到 div 容器中。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><div id="container"></div><script src="/xuni/bundle.js"></script><script>// 模板字符串const templateStr = `<div><ul>{{#students}}<li>学生{{name}}的爱好是<ol>{{#hobbies}}<li>{{.}}</li>{{/hobbies}}</ol></li>{{/students}}</ul></div>`;// 数据const data = {students: [{name: "张三",hobbies: ["敲代码", "乒乓球", "健身"],},{name: "李四",hobbies: ["游泳", "跑步"],},{name: "王五",hobbies: ["唱歌", "跳舞"],},],};// 获取 dom 数据const domStr = TemplateEngine.render(templateStr, data);const container = document.getElementById("container");container.innerHTML = domStr;</script></body>
</html>

src/index.js 文件中,全局提供模板引擎对象,渲染方法的入参为定义的 模板字符串数据,通过 parseTemplateToTokens 解析字符串为 tokens,通过 renderTemplate 渲染 tokens 数组为 dom 字符串。

import parseTemplateToTokens from "./parseTemplateToTokens";
import renderTemplate from "./renderTemplate";
// 全局提供模版引擎对象
window.TemplateEngine = {// 渲染方法render(templateStr, data) {// 模版字符串变为tokens数组const tokens = parseTemplateToTokens(templateStr);// 调用renderTemplate方法,渲染tokens数组为dom字符串const domStr = renderTemplate(tokens, data);// 返回组织好的 dom 字符串return domStr;},
};

通过上面两个核心方法,我们将获得如下的数据。

在这里插入图片描述

在这里插入图片描述

扫描器类 Scanner,用于扫描传入的模板字符串。当遇到 {{}} 内容时停止扫描,并返回停止扫描之前路过的内容。

/*** 扫描器类*/
export default class Scanner {constructor(templateStr) {this.templateStr = templateStr;// 指针this.pos = 0;// 尾巴,初始值为传入的字符串this.tail = templateStr;}// 走过指定的内容,没有返回值,用于过滤掉 {{ 和 }} 这样的内容scan(tag) {// 如果捕获到了tag,就让指针后移tag的长度,不会做任何处理,只是过滤掉if (this.tail.indexOf(tag) === 0) {// {{ 和 }} 的长度为2,就让指针后移2位this.pos += tag.length;// 改变尾巴this.tail = this.templateStr.substring(this.pos);}}// 让指针进行扫描,直到遇见指定内容结束,并且返回结束之前路过的文字scanUtil(stopTag) {// 记录执行本方法时pos的值const pos_backup = this.pos;// 当尾巴的开头不是stopTag的时候,就说明还没有扫描到stopTagwhile (!this.eos() && this.tail.indexOf(stopTag) !== 0) {this.pos++;// 改变尾巴为当前指针这个字符开始到最后的全部字符this.tail = this.templateStr.substring(this.pos);}// 返回扫描过的内容(不包括stopTag)return this.templateStr.substring(pos_backup, this.pos);}// 指针是否已经到头eos() {return this.pos >= this.templateStr.length;}
}

parseTemplateToTokens.js 文件用于将模板字符串变为初步的 tokens 数组。在 Scanner 的加持下,按照一定的规则 “制作” tokens。

import Scanner from "./Scanner";
import nestTokens from "./nestTokens";
/*** 将模板字符串变为tokens数组*/
export default function parseTemplateToTokens(templateStr) {// 存储 tokensconst tokens = [];// 创建扫描器,扫描模板字符串const scanner = new Scanner(templateStr);let words;// 让扫描器工作(当扫描器的指针没有到头时)while (!scanner.eos()) {// 扫描字符,直到遇到 {{ 时结束,因为 {{ 之前的内容是text类型words = scanner.scanUtil("{{");// 如果扫描的内容不为空,就作为text类型存入tokensif (words !== "") {tokens.push(["text", words]);}// 过滤 {{,指针后移2位,因为 {{ 并没有实质作用,过滤掉就好scanner.scan("{{");// 再次扫描字符,直到遇到 }} 时结束,因为 {{ 和 }} 之间的内容是需要处理的name类型words = scanner.scanUtil("}}");// 根据再次扫描的内容的第一个字符,判断应该 push 到 tokens 中的类型if (words !== "") {// 按照第一个字符组织tokens,# 为遍历的开始,/ 为遍历的结束if (words[0] === "#") {tokens.push(["#", words.substring(1)]);} else if (words[0] === "/") {tokens.push(["/", words.substring(1)]);} else {tokens.push(["name", words]);}}scanner.scan("}}");}// 返回折叠收集的tokensreturn nestTokens(tokens);
}

在这里插入图片描述

要进行进一步的 tokens 处理(多层级),就需要 nestTokens.js 来大显身手了。

/*** 折叠tokens,将#和/之间的tokens能够整合起来,作为它下标为2的项*/
export default function nestTokens(tokens) {// 结果数组,需要最后返回的const nestedTokens = [];// 栈结构,用于保存 # 的tokenconst sections = [];// 收集器引用,默认指向nestedTokenslet collector = nestedTokens;// 遍历在 parseTemplateToTokens 中组织好的 tokensfor (let i = 0; i < tokens.length; i++) {const token = tokens[i];switch (token[0]) {// 第一个字符如果为 #,就往收集器中放入这个token,并且入栈case "#":// 收集器中放入这个tokencollector.push(token);// 入栈sections.push(token);// 收集器此时要换位这个token的下标为2的项,因为之后需要push的是它的子项collector = token[2] = [];break;case "/":// 出栈sections.pop();// 改变收集器为栈结构末尾的数组collector =sections.length > 0 ? sections[sections.length - 1][2] : nestedTokens;break;default:// 收集器中放入这个tokencollector.push(token);}}return nestedTokens;
}

在这里插入图片描述

下面我们要做的就是把最终的 tokens 转为 dom 字符串了。

编写 lookUp.js 文件,用于在对象中查找 key 值。如 dataObj = {a: {b: {c: 100}}},keyName = 'a.b.c',那么调用该方法将返回100。

/*** 在 dataObj 对象中查找 keyName 的值* 如dataObj = {a: {b: {c: 100}}},keyName = 'a.b.c',返回100* @param {*} dataObj 对象* @param {*} keyName 要查找的key* @returns*/
export default function lookUp(dataObj, keyName) {// 查看 keyName 中是否有 ., 但不能是 .if (keyName !== "." && keyName.indexOf(".") !== -1) {// 以 . 分隔,例如 a.b.c,先拆分为 [a, b, c]const keys = keyName.split(".");// 临时变量,用于逐层查找let temp = dataObj;// 每找一层,就把它设置为新的临时变量for (let i = 0; i < keys.length; i++) {temp = temp[keys[i]];}return temp;}// 没有.直接返回return dataObj[keyName];
}

下面我们编写 parseArray.jsrenderTemplate.js 文件,分别用于处理数组和渲染模板字符串。

import lookUp from "./lookUp";
import renderTemplate from "./renderTemplate";
/*** 处理数组,结合 renderTemplate 方法实现递归* token:["#", "students", [xxx]]** 这个函数要递归调用 renderTemplate 方法* 调用次数取决于 data 中的数组长度*/
export default function parseArray(token, data) {// 得到数据整体data中这个数组要使用的数据const v = lookUp(data, token[1]);// 结果字符串let resultStr = "";// 遍历数据,而不是tokens。数组中的数据有几条就遍历几次for (let i = 0; i < v.length; i++) {// 拼接,在此处要补一个 “.” 属性resultStr += renderTemplate(token[2], {...v[i], // 简单数组,直接展开".": v[i], // 为了处理 {{.}} 的情况});}return resultStr;
}
import lookUp from "./lookUp";
import parseArray from "./parseArray";/*** 渲染模版* @param {*} tokens* @param {*} data* @returns*/
export default function renderTemplate(tokens, data) {let resultStr = "";for (let i = 0; i < tokens.length; i++) {const token = tokens[i];if (token[0] === "text") {resultStr += token[1];} else if (token[0] === "name") {// name类型,获取值resultStr += lookUp(data, token[1]);} else if (token[0] === "#") {// 递归处理下标为2·的数组resultStr += parseArray(token, data);}}return resultStr;
}

在这里插入图片描述

此时编码完毕,打开浏览器查看渲染内容如下,至此,手撕完毕!!

在这里插入图片描述


总结

本篇文章,我们首先认识了几种将模型变为视图的方法。

之后学习了Mustache 的基本使用和核心理念。

通过手写 Mustache 模板引擎,我们 深入理解 了其 工作原理和实现细节。虽然手写版本可能不如官方实现那么完善,但 这个过程让我对模板引擎的设计有了更深刻的认识。Mustache 的简洁性和无逻辑特性使其成为一种非常灵活的模板引擎,适用于各种场景。

如果你也对模板引擎的实现感兴趣,我建议你尝试手写一个简化版的 Mustache 或类似的模板引擎。这不仅能够加深你对前端技术的理解,还能提升你的编程能力。

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. mustache 百度百科
  2. Vue源码解析之mustache模板引擎(尚硅谷)

在这里插入图片描述


http://www.zhongyajixie.com/news/17140.html

相关文章:

  • 免费制作永久网站合作seo公司
  • 益阳建设网站公司淘宝店铺推广方式有哪些
  • 做日本外贸单是哪个网站在线生成网页网站
  • 白糖贸易怎么做网站网络视频营销平台
  • 红色网站主题腾讯企点账户中心
  • 网站上传小马后怎么做深圳信息公司做关键词
  • 建设网站的行业现状分析百度官网网站首页
  • 携程网站模板百度知道客服电话人工服务
  • 网站搭建报价表淘宝seo什么意思
  • 广州外贸营销型网站建设公司肇庆网站搜索排名
  • 软件网站建设基本流程图seo这个职位是干什么的
  • 做机械设备销售的那个网站好制作网页的代码
  • 如何选择丹阳网站建设seo网络营销的技术
  • 滴滴出行网站建设最新舆情信息网
  • 网站建设网络推广销售网站设计流程
  • e龙岩官网下载济南seo全网营销
  • 做网站的怎样找客户2345网址导航智能主板
  • 熊掌号网站改造绑定织梦网站国内真正的永久免费建站
  • 外贸网站怎么做效果好引擎搜索大全
  • 什么犁网站做淘宝门头域名查询 ip
  • 贵州省建设学校官方网站赚钱软件
  • 做网站需要哪些技术支持网络品牌营销
  • 网站建设公司企业文化广州seo全网营销
  • 延边州建设局网站百度一下百度首页官网
  • 博物馆网站建设策划书怎么在百度发广告
  • 烟台网站建设电话网络推广费用预算表
  • 门户 网站开发周期找营销推广团队
  • 网站界面设计基础深圳网站建设
  • ps网站制作教程上海百度seo
  • 廊坊建站无锡百度seo优化