时间:2023-06-07 07:09:01 | 来源:网站运营
时间:2023-06-07 07:09:01 来源:网站运营
Web 前端模板引擎的选择:无论你是否直接使用模板引擎,Web 模板一直都在,不在前端就在后端,它的出现甚至可以追溯到超文本标记语言 HTML 标准正式确立之前。轻量度:tpl.js、T.js它们的共同特征:全都支持插值。
认知度:arttemplate、mustache.js、doT.js、handlebars.js、pug
DOM-tree-based:domTemplate、transparency、plates
VDOM-based:htmltemplate-vdom、virtual-stache、html-patcher
流行框架:Vue.js、ReactJS、riot
Real-DOM:PowJS
前提,选择的引擎能满足数据渲染需求,且不和现有依赖冲突,如果你已经非常熟悉某个引擎,那你已经有答案了。我认为应该弱化语法风格的对比,偏好是没有可比性的,一些语法甚至有特殊的背景原因。
是一次性的项目需求么? 是的话直接选择轻量的,学习复杂度最低的。 是要做组件开发么?
引擎支持预编译结果,不必每次都实时编译么?
要跨平台么? 有官方提供支持的,首选类 React-JSX 的引擎或纯粹的 VDOM 引擎。
选择学习或维护复杂度最低的,众所周知,开发者对调试的时间超过写代码的时间深恶痛绝。
最后才是性能对比,性能对比是一件非常细致的工作,他人的对比结果不一定符合你的场景。
class HelloMessage extends React.Component { render() { return <div>Hello <x-search>{this.props.name}</x-search>!</div>; }}
编译后:class HelloMessage extends React.Component { render() { return React.createElement( "div", null, "Hello ", React.createElement( "x-search", null, this.props.name ), "!" ); }}
不少 VDOM 引擎也可以编译类似效果,比如 htmltemplate-vdom。<script> var id = 3; var env = { people: [ { id: 'id1', name: 'John', inner: [{ title: 'a1' }, { title: 'b1' }], city: 'New York', active: true }, { id: 'id2', name: 'Mary', inner: [{ title: 'a2' }, { title: 'b2' }], city: 'Moscow' } ], githubLink: 'https://github.com/agentcooper/htmltemplate-vdom', itemClick: function(id) { env.people.forEach(function(person) { person.active = String(person.id) === String(id); }); loop.update(env); } // Omitted .... }; </script>
复杂度有的使用者认为这个应用场景有字符串模板就满足了需求,轻量够用。这些评判都有各自的理由,着眼点不同,标准也就不同了。但是我们还是可以从它们的共性去考虑它们的复杂度。
有的使用者认为字符串拼接技术的模板引擎不够强壮,不够时代感。
有的使用者认为OOP 够理性,够逻辑,够抽象。
有的使用者认为原生 HTML 才叫前端。
有的使用者认为 VDOM 适用性更广。
1.入口参数是个 Object,模板中的变量 x 是该对象的 .x 属性,例:virtual-stache-example这些模式只是理论方面的,通常是模板引擎设计者要解决的问题。对于使用者来说不如直接问:
2.特定语法或属性,比如:Vue.js 的 <a v-on:click="doSomething">...</a>,属性 computed、methods
3.抽象的语义化属性,比如:Vue.js 的 active 这个词适用于多种场景,容易理解且不产生歧义
4.不负责绑定,需要使用者非常熟悉原生方法,用原生方法进行绑定,比如:PowJS
1.可以在 HTML 模板中直接写最简单的 console.log(context) 来调试么?模板引擎团队会给你正确的解决办法,但通常和问题字面描述的目标有所差异。我觉得这就是你评判选择的关键,你对官方给出的正确方法的认可度。
2.可以在多层 DOM 树绑定或传递不同的上下文参数么?
3.可以在多层 DOM 树内层向上访问已经生成的 Node 么?
嵌入到 HTML 中PowJS 是这么实现的:
<template> <details func="repo" param="data" if="is.object(data.content)&&!sel(`#panel details[sha='${data.sha}']`)" open let="ctx=data.content" sha="{{data.sha}}" origin="{{ctx.Repo}}" repo="{{data.owner}}/{{data.repo}}" subdir="{{ctx.Subdir||''}}" filename="{{ctx.Filename}}" render=":ctx" do="this.renew(sel(`#panel details[repo='${data.owner}/${data.repo}']`))" break > <summary>{{ctx.Description}}</summary> <div if="':';" each="ctx.Package,val-pkg"> <p title="{{pkg.Progress}}: {{pkg.Synopsis}}">{{pkg.Import}}</p> </div> </details> <dl func="list" param="data" if="!sel(`#panel details[sha='${data.sha}']`)&&':'||'';" each="data.content,data.sha,val-rep" do="this.appendTo(sel('#panel'))"> <details sha="{{sha}}" repo="{{rep.repo}}"> <summary>{{rep.synopsis}}</summary> </details> </dl></template>
多数模板引擎都会实现 if 、each 这些指令,上面的 PowJS 模板中还有:关键词:选择,引擎,模板