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