javascript 下一代模版 — lit html (上)

email-templates-header.png
<header> <h1>Lorem ipsum dolor sit amet consectetur.</h1> <h2>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque, fuga!</h2> </header> <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Modi aspernatur soluta sequi facilis voluptate deserunt minus pariatur necessitatibus asperiores itaque.</p> <div class="page">頁尾</div>
我們在開發 web 應用時候多半也都是在開發使用者互動介面,也就是 HTML 檔案,然後獲取資料,填充 html。我們資料是變化的,我們 html 的結構是相對穩定的。也就是 html 中內容是變化的。我們首先要分清變化與不變的部分。
我們大部分工作就是將動態變化的內容整合到不變的 html 的結構中去。
function createPost(title, content) { let post = document.querySelector(".wrapper"); let header = document.createElement("h1"); let body = document.createElement("p"); header.textContent = title; body.textContent = content; post.appendChild(header); post.appendChild(body) body.addpend(div); return { post } }
剛開始入行的時候,我想大家都是這樣動態新增模板的,我麼 createElement 建立一個 dom 樹,然後新增到 html 中,隨後資料更新了,我們在更新這些節點內容。想必大家都習慣這麼做,雖然很痛苦。因為這個太抽象不直觀。
<template id="post"> <h1>{{title}}</h1> <template is="dom-repeat" items={{items}}> <div>{{item.name}}</div> </template> </template>
有了 template 這個標籤我們工作就變得相對簡單多了,template 中定義和我們最終渲染出的效果比較接近了。
模板
如果要寫出一個好的模板系統並非易事,好的模板系統需要具備以下特點
- 開發體驗
作為開發人員對模板的要求就是所見即所得,雖然 jsx 給我們好的體驗,但是這些模板還是寫在 javascript 中。開發模板我們通常需要花費精力學習一些模板的表示式才可以寫出符合要求的模板。這些模板通常需要編譯,所以還需要了解編譯模板的工具。 - 快速啟動
渲染模板的速度也是一個問題 - 即時更新
快速地 - 作為 javascript 和 html 的橋樑
如果我們 template 寫在 javascript ,這樣 template 一定不那麼直觀。如果寫在 html 中,這樣雖然直觀了但是訪問資料也成為問題,資料更新我們還需要更新模板。
好說了半天我們的今天主角出場。
- 可以在 javascript 中寫的 html 模板
- 快速啟動和更新
- 體積小
- 易於上手、API 支援可擴充套件
可以在 javascript 中寫的 html 模板
- boot fast
- update Fast
- bridge javascript and html
const helloTemplate = (name) => html`<div>Hello ${name}!</div>`;
這裡大家可能注意到使用 es6 模版語法,支援多行我們可以得到所寫即所得的效果,而且這裡使用 es6 表示式${name} 我們不需要其他成本去學習
html` <div> <h1>${title}</h1> <body>${content}</body> </div> `
讓後將我們的 html 的字串賦值給 JavaScript 的變數。
-
一個問題我們 建立 html 是字串還是 DOM 元素呢?
如果只是簡單地生成 html 字串,然後作為 innerhtml 進行賦值就失去了意義。如果返回是一個 dom 那麼我們還需要重構整個 dom 樹。
這裡返回一個 templateResult 結果,這是一個物件,具有 template 的引用,而且具有資料。
render(helloTemplate('zidea'), document.body);
render 這個方法在第一次呼叫時候渲染模版,隨後更新模版的資料。
render(helloTemplate('zidea'), document.body); render(helloTemplate('matthew'), document.body); render(helloTemplate('jang'), document.body);
和 react 有區別嗎?
表面上看很想 jsx ,但是這僅是 JavaScript 的語法,並不是什麼新的語法。hit-html 並沒有虛擬 dom 的概念也也沒有 diff 檢查。
UI=f(state)
這個讓我們想到 redux 和 f 這裡是一個純函式,輸入 state 輸出 UI,根據確定的 state 輸入,輸出的 UI 是確定的。
const postTemplate =(title,content) => html` <div> <h1>${title}</h1> <body>${content}</body> <div>${index}</div> </div> ` render(postTemplate('angular tutorial','angular tutorial content '), document.body);

003.JPG
let header = (title) => html` <h1>${title}</h1> ` const postTemplate =(title,content) => html` <div> ${header(title)} <body>${content}</body> <div>第 ${index} 頁</div> </div> `
在 hit-html 中支援巢狀,html 方法中支援巢狀,可以層層巢狀。
let user = { loggedIn:true, name:'matthew' } const helloTemplate = (name) => html`<div>Hello ${name}!</div>`; let index = 0; let header = (title) => html` <h1>${title}</h1> ` let message = html` 歡迎${user.name} ` const postTemplate =(title,content) => html` <div> ${message} ${header(title)} <body>${content}</body> <div>第 ${index} 頁</div> </div> `
可以通過分支語句控制模版,大家可以看出其好處了,我們完全不用學習一門新的模版語言就可以輕鬆第搞定邏輯控制。
if(user.loggedIn){ message = html` 歡迎${user.name} ` }else{ message = html` 請先登入 ` }
集合的遍歷也是原生的
<div> ${['apple','banana','cherry']} </div>

005.JPG
<ul> ${ ['apple','banana','cherry'].map((item)=> html`<li>${item}</li>` ) } </ul>
讓我們驚歎的也是也支援 DOM 形式的嵌入,可能您已經感覺到了開發的樂趣。
const titleDom = document.createElement('h1'); titleDom.textContent = "標題" const postTemplate =(title,content) => html` <div> ${titleDom} </div> <ul> ${ ['apple','banana','cherry'].map((item)=> html`<li>${item}</li>` ) } </ul> <div> ${message} ${header(title)} <body>${content}</body> <div>第 ${index} 頁</div> </div> `