服务端渲染javascript
浏览器端渲染html
提升开发效率和减小维护成本,先后端协做模式;前端
后端 提供接口html5
前端 视图和交互逻辑。经过Ajax请求数据,拼接html字符串或者使用js模板引擎、数据驱动的框架如Vue进行页面渲染。java
在ES6和Vue这类框架出现之前,前端绑定数据的方式:node
动态拼接html字符串android
js模板引擎。es6
做用:分离 数据和视图。模板对应视图,关注如何展现数据,在模板外头准备的数据, 关注那些数据能够被展现。正则表达式
工做原理 两个步骤:后端
模板解析 / 编译(Parse / Compile)
数据渲染(Render)
主流的前端模板 三种方式:
String-based templating ( 基于字符串的parse和compile过程 )
基于正则表达式 的 模板引擎
正则匹配 {{ }} 的内容,替换为模型中的数据
es6 模板字符串
const template = data => ` <p>name: ${data.name}</p> <p>age: ${data.profile.age}</p> <ul> ${data.skills.map(skill => ` <li>${skill}</li> `).join('')} </ul>` const data = { name: 'zhaomenghuan', profile: { age: 24 }, skills: ['html5', 'javascript', 'android'] } document.body.innerHTML = template(data)
Dom-based templating ( 基于Dom的link或compile过程 )
遍历dom树,提取属性和dom内容,将数据写入到dom树
function MVVM(opt) { this.dom = document.querySelector(opt.el); this.data = opt.data || {}; this.renderDom(this.dom); } MVVM.prototype = { init: { sTag: '{{', eTag: '}}' }, render: function (node) { var self = this; var sTag = self.init.sTag; var eTag = self.init.eTag; var matchs = node.textContent.split(sTag); if (matchs.length){ var ret = ''; for (var i = 0; i < matchs.length; i++) { var match = matchs[i].split(eTag); if (match.length == 1) { ret += matchs[i]; } else { ret = self.data[match[0]]; } node.textContent = ret; } } }, renderDom: function(dom) { var self = this; var attrs = dom.attributes; var nodes = dom.childNodes; Array.prototype.forEach.call(attrs, function(item) { self.render(item); }); Array.prototype.forEach.call(nodes, function(item) { if (item.nodeType === 1) { return self.renderDom(item); } self.render(item); }); } } var app = new MVVM({ el: '#app', data: { name: 'zhaomenghuan', age: '24', color: 'red' } });
Living templating ( 基于字符串的parse 和 基于dom的compile过程 ) 发布-订阅模式