服務端渲染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過程 ) 發佈-訂閱模式