Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

web-template.js 是一款基于 ES6 模板字符串解析的模板引擎。

Notifications You must be signed in to change notification settings

atdow/web-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

3 Commits

Repository files navigation

web-template

web-template.js 是一款基于 ES6 模板字符串解析的模板引擎。

特点

  1. 纯原生浏览器解析,无任何依赖,无需编译,不拖泥带水
  2. 类 vue 模板语法,上手快,几乎可以不用看文档
  3. 代码量极少,包含注释不到 100 行,方便学习和扩展

demo

适用场景

适用于原生开发,又希望有一定模板渲染的场景,比如一大堆列表循环渲染

在使用之前

var html = '';
arrData.forEach(function (obj, index) {
 html = html + '\
 <tr>\
 <td><input type="checkbox" value="' + obj.id + '"></td>\
 <td><div class="ell">' + obj.title + '</div></td>\
 <td>' + obj.time + '</td>\
 <td align="right">' + obj.comment + '</td>\
 </tr>';
});
console.log(html);

使用 ES6 模板字符串

let html = `${data.map(function (obj, index) {
 return `<tr>
 <td><input type="checkbox" value="${obj.id}"></td>
 <td><div class="ell">${obj.title}</div></td>
 <td>${obj.time}</td>
 <td align="right">${obj.comment}</td>
 </tr>`;
}).join('')}`;
console.log(html);

使用 template.js 之后

<template id="template" rule="v-">
 <tr v-for="obj in data">
 <td><input type="checkbox" value="${obj.id}"></td>
 <td><div class="ell">${obj.title}</div></td>
 <td>${obj.time}</td>
 <td align="right">${obj.comment}</td>
 </tr>
</template>
console.log(template.render(data).content); // dom节点
console.log(template.render(data).innerTHML); // dom字符串

是不是清爽了许多,可读性也更强了

使用方式

直接引用 web-template.js

<script src="web-template.js"></script>

在 HTML 页面上添加 template 标签,放入模板

<ul id="list">
</ul>
<template id="template">
 <li $for="(item,index) in list">${ index + 1} - ${ item }</li>
</template>

假设有如下数据

const data = {
 list : [ 'Apple', 'Banana', 'Cat']
}
list.appendChild(template.render(data).content)

最终,页面上 ul 会被渲染成

<ul id="list">
 <li>1 - Apple</li>
 <li>2 - Banana</li>
 <li>3 - Cat</li>
</ul>

更多用法,可参考下面的详细介绍

模板语法

模板必须放在 <template></template> 标签中

<template>
 <!-- 你的模板 -->
</template>

以下所有规则都在这个标签中

1.插值

数据绑定采用的是 ES6 模板字符串的语法, ${ }:

<span>Message: ${ msg }</span>
const data = {
 msg: 'hello'
}

返回

<span>Message: hello</span>

各种属性,或者说只要出现插值语法的地方都会被替换成普通文本

<span data-type="${type}">Message: ${ msg }</span>
const data = {
 msg: 'hello',
 type: 'normal',
}

返回

<span data-type="normal">Message: hello</span>

一些特殊的表单属性,比如 disabledhiddenrequiredcheckedselectedopen(欢迎补充~),如果设置值为 false ,那么将会移除该属性

<button disabled="${disabled}">button</button>
<button hidden="${hidden}">button</button>
const data = {
 disabled: true,
 hidden: false,
}

返回

<button disabled="true">button</button>
<button>button</button> <!-- hidden属性被移除 -->

2.JavaScript 表达式

JavaScript 表达式也可以用到模板中的任意地方

<span>${ number + 1 }</span>
${ ok ? 'YES' : 'NO' }
const data = {
 number: 10,
 ok: true,
}

返回

<span>11</span>
YES

注意,这里是单个表达式,推荐使用三元表达式,vue 和 react 也是同样的规定

JavaScript 函数也可以直接访问,可以是全局函数,也可以是自己定义的函数

<span>${ new Date() }</span>
<span>${ add(1,2) }</span>
// 定义在全局的函数
function add(m,n){
 return m + n
}

返回

<span>Tue Nov 17 2020 11:13:44 GMT+0800 (中国标准时间)</span>
<span>3</span>

更极端的是,可以直接嵌套函数,但是必须是立即执行函数

<span>${
 (()=>{
 return 'hello';
 })() 
}</span>

返回

<span>hello</span>

当然强烈不推荐这么做,把一段 js 放在 html 中实在不怎么优雅

3.指令

指令是带有特殊前缀的属性,默认是 $,当然你也可以更换成你喜欢的,比如 v-,通过修改 template 标签的 rule 属性

<template rule="v-">
 <!-- 模板 -->
</template>

以下就以 v- 为例

目前有两个指令,分别是条件渲染列表渲染

条件渲染

v-if 用来条件性地渲染一块内容,当值为 false 时,内容会被完全移除

<h1 v-if="show">Template is awesome!</h1>
<h1 v-if="!show">Oh no 😢</h1>
const data = {
 show: true
}

返回

<h1>Template is awesome!</h1>
<!-- $if H1 -->

注意,指令的属性值不需要包裹 ${ }

这里没有实现另外一个显示隐藏的指令 v-show ,可以用属性 hidden 来代替

<h1 hidden="${!show}">Template is awesome!</h1>
<h1 hidden="${show}">Oh no 😢</h1>
const data = {
 show: true
}

返回

<h1>Template is awesome!</h1>
<h1 hidden="true">Oh no 😢</h1> <!--样式上被隐藏-->

注意,这里是普通的属性,所以需要包裹 ${ }

列表渲染

别名

v-for 用来循环渲染一个列表,格式形如 item in items,其中 items 是数据源,item 是被循环的数组元素的别名

<template>
 <li v-for="item in items">
 ${ item.message }
 </li>
</template>
const data = {
 items: [
 { message: 'Foo' },
 { message: 'Bar' }
 ]
}

返回

<li>Foo</li>
<li>Bar</li>
索引

此外,还支持第二个可选参数,表示索引(默认为 index ),形如 (item,index) in items

<template>
 <li v-for="(item,index) in items">
 ${ index } - ${ item.message }
 </li>
</template>

返回

<li>0 - Foo</li>
<li>1 - Bar</li>
作用域

每个循环都有自己的作用域,这在多重循环中特别有用,如下可以轻易的实现一个 9*9 乘法表

<template>
 <div v-for="i in [1,2,3,4,5,6,7,8,9]">
 <span v-for="j in [1,2,3,4,5,6,7,8,9]" v-if="i>=j"> ${i*j} </span>
 </div>
</template>

返回

<div>
 <span> 1 </span>
</div>
<div>
 <span> 2 </span><span> 4 </span>
</div>
<div>
 <span> 3 </span><span> 6 </span><span> 9 </span>
</div>
<div>
 <span> 4 </span><span> 8 </span><span> 12 </span><span> 16 </span>
</div>
<div>
 <span> 5 </span><span> 10 </span><span> 15 </span><span> 20 </span><span> 25 </span>
</div>
<div>
 <span> 6 </span><span> 12 </span><span> 18 </span><span> 24 </span><span> 30 </span><span> 36 </span>
</div>
<div>
 <span> 7 </span><span> 14 </span><span> 21 </span><span> 28 </span><span> 35 </span><span> 42 </span><span> 49 </span>
</div>
<div>
 <span> 8 </span><span> 16 </span><span> 24 </span><span> 32 </span><span> 40 </span><span> 48 </span><span> 56 </span><span> 64 </span>
</div>
<div>
 <span> 9 </span><span> 18 </span><span> 27 </span><span> 36 </span><span> 45 </span><span> 54 </span><span> 63 </span><span> 72 </span><span> 81 </span>
</div>
简写

每次都要写 item in items 有些麻烦,这里可以简写成 items,此时默认别名索引分别是 itemindex

<template>
 <li v-for="items">
 ${ index } - ${ item.message }
 </li>
</template>

返回

<li>0 - Foo</li>
<li>1 - Bar</li>
重复次数

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<template>
 <span v-for="10">${ index } </span>
</template>

返回

<span>0</span>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>

虽然有些鸡肋,某些情况下还是有点作用的

对象迭代

你也可以用 v-for 来遍历一个对象,这里用 of 来区分,形如 value of object

<template>
 <li v-for="value of object">
 ${ value }
 </li>
</template>
const data = {
 object: {
 title: 'How to do lists in Vue',
 author: 'Jane Doe',
 publishedAt: '2016-04-10'
 }
}

返回

<li>How to do lists in Vue</li>
<li>Jane Doe</li>
<li>2016年04月10日</li>

同时,支持三个参数,形如 (value, name, index) of object,分别为键名索引

<template>
 <li v-for="(value, name, index) of object">
 ${ index }. ${ name }. ${ value }
 </li>
</template>

返回

<li>0. title. How to do lists in Vue</li>
<li>1. author. Jane Doe</li>
<li>2. publishedAt. 2016年04月10日</li>

对象迭代不支持简写,尽量多使用数组遍历吧

4.渲染

在原生 template 标签扩展了 render 方法,可以传入一个对象,然后返回一个 template文档片段(document-fragment)

const tpl = template.render(data) // template document-fragment
tpl.content; // 返回dom节点
tpl.innerHTML; // 返回字符串

一般通过 .content 可以得到模板的 dom 结构,直接以 appendChild 的方式渲染到页面,这种方式在追加数据的时候更加有效

container.appendChild(tpl.content);

如果内容需要重置,可以简单粗暴的使用 .innerHTML

container.innerHTML = tpl.innerHTML;

兼容性和一些局限

需要支持 ES6 模板字符串语法的浏览器,还在用 IE 的小伙伴可以放弃了

由于使用了很多 DOM API,依赖浏览器环境,因此不支持 Node 等其他非浏览器环境,不支持服务端渲染

参考

Vue 模板语法

ES6模板字符串在HTML模板渲染中的应用

About

web-template.js 是一款基于 ES6 模板字符串解析的模板引擎。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • HTML 68.7%
  • JavaScript 31.3%

AltStyle によって変換されたページ (->オリジナル) /