瑞巴迪,
從這章開始,我們要講微信小程序的模板語法。
模板語法的定義:
WXML(WeiXin Markup Language)是框架設計的?套標簽語?,結合基礎組件、事件系統,可以構建出頁面的結構。
模板語法有以下四個種類,
1、數據綁定
2、運算
3、列表渲染
4、條件渲染
這是我們接下來要一一重點講解的。
這一章,我們來初步學習模板語法中的數據綁定。
大家可以點擊下方鏈接,找到我們的教科書(微信官方文檔)去學習一下基本定義,有一個大致的了解。
https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/data.html
數據綁定: WXML 中的動態數據均來自對應 Page 的 data
我們還是老方法 ,在實踐中學習,在實操中認識。
1、在全局配置文件app.json 中新增demo03文件,便于我們示范以下具體操作。
代碼如下:
2、打開 pages 文件夾--打開demo03 文件夾--打開demo03.wxml 文件,頁面如下:
在demo03.wxml 文件中,可以看到如下代碼:
代碼中包含標簽和普通文本兩部分內容。
我們先對”text“標簽做簡單描述:
”text“相當于傳統web中的span標簽,是行內元素, 當頁面中存在多個text 標簽時,各標簽也是不換行的。
比如:
我們在demo03.wxml 文件中輸入以下代碼:
<text>1</text>,
<text>2</text>
按下保存鍵,發現,左側的屏幕中,1,2是在同一行的。
這就是說,當頁面中存在多個text 標簽時,各標簽也是不換行的。
2.1 補充:對另一個標簽——”view“標簽進行描述。
”view“標簽相當于以前web 中的 div 標簽, 是塊級元素, 當頁面中有多個 view 標簽時,是會換行的。
比如:
我們在demo03.wxml 文件中輸入以下代碼:
<view>1</view>,
<view>2</view>
按下保存鍵,發現,左側的屏幕中,1,2是各占一行的。
這就是說,當頁面中存在多個view 標簽時,各標簽是換行的。
3、數據綁定中,數據要定義在哪里?
我們打開 pages 文件夾--打開 demo03.js 文件, 文件中,一新建后就有內容存在。如下圖所示。
我們來具體解讀一下,demo03.js 文件中的內容
page: 這里指的是大型的配置方法
其中,page包括的data字段, 這里面都是關鍵字,是不能更改的哦,
而且,里面要放的都是一些初始化的數據,比如變量。
與data 同層級的有很多方法,基本都是生命周期函數,這在以后的章節中會介紹到的。
3.1 這里,給大家介紹一個小技巧:
我們把demo03.js 文件中的內容全部刪除,使其文件呈現空白狀態。
在demo03.js 文件中輸入”page“,會有下拉提示框, 這里選擇page , 就會重新出現刪除前的文件內容。
在我們編輯demo03.js 文件時,如果出現了錯誤, 我們可以選擇全部刪除,然后再用這種方法重新輸入page方法。
歐克,本章數據綁定部分的一部分知識,講解到此,下一章我們繼續講解數據綁定的知識。
搜索并關注微信公眾號:飛寢旺食
獲取更多小程序運營干貨、免費的開發教程、源代碼等!
做小程序我們是認真的!
們可以使用數據綁定(Data Binding)來完成帶可選項的列表,這些可選項來自某個導入的數據源,比如數據庫、XML 文件或者腳本。
數據綁定
下面的控件是支持數據綁定的列表控件:
asp:RadioButtonList
asp:CheckBoxList
asp:DropDownList
asp:Listbox
以上每個控件的可選項通常是在一個或者多個 asp:ListItem 控件中定義,如下:
<html>
<body>
<form runat="server">
<asp:RadioButtonList id="countrylist" runat="server">
<asp:ListItem value="N" text="Norway" />
<asp:ListItem value="S" text="Sweden" />
<asp:ListItem value="F" text="France" />
<asp:ListItem value="I" text="Italy" />
</asp:RadioButtonList>
</form>
</body>
</html>
然而,我們可以使用某種獨立的數據源進行數據綁定,比如數據庫、XML 文件或者腳本,通過數據綁定來填充列表的可選項。
通過使用導入的數據源,數據從 HTML 中分離出來,并且對可選項的修改都是在獨立的數據源中完成的。
在下面的三個章節中,我們將描述如何從腳本化的數據源中綁定數據。
信我或關注微信號:獅范課,回復:學習,獲取免費學習資源包。
聲明式數據綁定的情況
數據綁定最早是被 Angular、Backbone 和 Ember 等框架推廣而流行開來的,現在則在某種程度上是編寫視圖的標準途徑。它能讓“視圖作為數據的函數”,意味著每當某些數據發生變化時,相關視圖將“自動”更新。
不需要冗長的 DOM 操作來保持數據和視圖同步,只需更新數據,視圖就會隨之變化。這是一項殺手級功能,如今但凡理智的開發人員就會用它。所以很容易理解為什么開發人員會使用提供了數據綁定功能的框架,就算框架對于應用來說太大材小用也無所謂:既然框架打理好了一切,何必要費心費力處理那些麻煩的 DOM 操作呢?
但數據綁定并不是什么魔法,你用不著為了用它而動用整個框架。在 Web 組件里只需要幾行代碼就能輕松搞定數據綁定了,沒什么特殊的。
如何實現
就像我上面說的那樣,數據綁定并沒有那么神奇。當基礎數據發生變化時,你的視圖不是憑空“神奇”地更新的。在框架深處,不為人知的某個角落里的設置代碼負責在數據更改時調用并更新視圖。
AngularJS 使用了所謂的“摘要循環”:這是一種粗暴的檢查機制,不斷檢查哪些數據已更改,以便隨時更新對應的視圖。
React 面世時提供了另一種據稱性能更好的解決方案,稱為虛擬 DOM:它是一種 DOM 的 JavaScript 表示,只更新已更改的 DOM 部分。這對列表來說很合適——列表的少數項目發生變化時無需重新渲染整個列表,只需更新已更改的項目。
哪種工具最合適?
圖源:https://xkcd.com/974/
這對于具有復雜 UI 的較大應用程序來說非常有用,但對于大多數應用程序來說實在有些殺雞用牛刀了。編寫一些監視數據的代碼并在數據發生變化時更新相關視圖并不是什么難事。問題是這些數據通常需要傳遞給也需要數據綁定的子組件,所以最后往往會有很多 DOM 操作。
你需要的是一種在數據被推送到子組件時觸發子組件中相同的數據綁定操作的方法。只要父組件的數據發生更改并且某些數據綁定到子組件的視圖,該子組件的視圖也需要更新。
一種方法是利用所有組件的基類,因為 Web 組件是使用 JavaScript 類創建的,所以這是一個很好的選擇。默認情況下 Web 組件擴展 HTMLElement,但我們也可以創建自己的基類來擴展 HTMLElement,如下所示:
export class CustomElement extends HTMLElement
然后我們創建的每個 Web 組件都擴展了這個 CustomElement 基類:
export class MyComponent extends CustomElement
如果你想直接查看代碼,可以訪問 Github 鏈接。
我們將 CustomElement 的內部 state 屬性綁定到視圖來實現數據綁定:
class CustomElement extends HTMLElement { constructor() { super(); this.state={}; } }
我的第一個想法是將 this.state 實現為 Proxy,這樣 state 對象的任何突變都將被自動攔截;但由于 Proxy 可能會影響性能,因此我決定實現一個 setter,它還能同時設置多個屬性:
class CustomElement extends HTMLElement { ... setState(newState) { Object.entries(newState) .forEach(([key, value])=> { this.state[key]=this.isObject(this.state[key]) && this.isObject(value) ? {...this.state[key], ...value} : value; }); } }
setState 方法遍歷 newState 對象的所有條目,并將所有值設置為 this.state 上的對應屬性,隨后我們就應該使用這些值來更新視圖。
通過標準 data 屬性將值綁定到視圖上,在本例中為 data-bind:
<p data-bind="title"></p>
這里的 textContent 綁定到負責管理視圖的組件內的 this.state.title 的值上:
class DemoElement extends CustomElement { constructor() { super(); const shadowRoot=this.attachShadow({mode: 'open'}); shadowRoot.innerHTML=` <p data-bind="title"></p> `; } } const element=document.querySelector('demo-element'); element.setState({title: 'Hello World'}); // the paragraph will now contain the text "Hello World"
這種綁定可以達到任意深度,所以下面這種情況也能做到:
<p data-bind="user.address.city"></p> element.setState({ user: { address: { city: 'Amsterdam' } } }); ---> <p>Amsterdam</p>
還可以將數據綁定到 Web 組件的特定屬性。在此示例中,數據綁定到的 title 屬性上:
<parent-element> <demo-element data-bind="title:name"></demo-element> </parent-element> parentElement.setState({name: 'foo'}); //demoElement.title==='foo'
視圖的更新實際是在 CustomElement 中的 updateBindings 方法中實現的。通過 setState 方法更新 state 時,它會解析更新的屬性以查找綁定到這些屬性的 HTML 元素。
例如下面這樣:
element.setState({ user: { address: { city: 'Amsterdam' } } });
更新 Web 組件內的 this.state.user.address.city,并將數據對象中的鍵轉換為 user.address.city,然后使用它來查找這個數據綁定的元素:
const elements=this.shadowRoot.querySelectorAll('[data-bind$="user.address.city"]');
這將查找所有的 data-bind 屬性以 user.address.city 結尾的元素(注意 data-bind 結尾的),因此它將找到 data-bind=“user.address.city”,但也可以找到 data-bind=“ name:user.address.city“,其中數據專門綁定到 name 屬性。
每當數據綁定到元素的特定屬性(如 data-bind=“name:user.address.city”)時,組件將檢查該元素是否也是擴展 CustomElement 的 Web 組件;如果是,則通過它的 setState 方法更新該屬性。這樣,數據綁定就能一直傳播到所有子組件上。
如果綁定數據的元素是常規 HTML 元素,那么將簡單地更新其 textContent。在這兩種情況下,只需幾行代碼即可有效實現 DOM 的更新。
列表該怎么處理?
像虛擬 DOM 這樣的解決方案真正的用武之地是渲染列表。例如只更改列表的一部分時,虛擬 DOM 將僅更新已更改的部分,而不是重新渲染整個列表。
其機制是在第一次渲染列表時創建 DOM 節點,然后在列表更改時只更新這些現有節點(textContent、屬性等)。復用已經創建的節點比重新渲染整個列表重建所有節點的開銷小得多,因此對于非常大的列表來說這種方法效率更高。
但如果你的列表平均只有 25 個項目時,你可能會想知道重新渲染整個列表能比虛擬 DOM 的方法慢多少。當你渲染 250 個項目時可能會變得很慢,但理智的開發人員在這種情況下就應該分頁了。
我不是說大家就應該拋棄虛擬 DOM,因為它的確是很棒的技術。如果遇到真正需要虛擬 DOM 的情況,自然一定要使用它。我只是希望大家遇到比較輕量的問題時先思考一下能不能找到一個比較輕量的解決方案,而不是上來就動用重量級的殺手锏。
customElement 演示的 Github 倉庫包含一個 Web 組件,它在 li 標簽內渲染任何設置為其 items 屬性的字符串數組。只要將 items 設置為新數組它就會重新渲染整個列表,但是復用現有的 li 標記也很簡單。
結論
答案很清楚了,只需幾行代碼即可對 Web 組件進行聲明式數據綁定。我覺得自己已經清楚地證明了數據綁定很容易實現,并且你不需要動用整個框架也能使用它。
上面提到的 Github 倉庫中的代碼不是 React 或 Vue.js 等框架的替代品,本來也沒這個意思。框架提供的并不只有數據綁定,本文和涉及的代碼是為了證明你不一定需要一個框架來實現聲明式數據綁定。
除了數據綁定之外,customElement 還提供了一些方便的方法來選擇元素以及顯示和隱藏元素。
來源網絡,侵權聯系刪除
私信我或關注微信號:獅范課,回復:學習,獲取免費學習資源包。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。