-
小程序的雙線程模型
- 誰是小程序的宿主環(huán)境?微信客戶端
- 宿主環(huán)境為了執(zhí)行小程序的各種文件:wxml文件融蹂、wxss文件、js文件
-
提供了小程序的雙線程模型
- 雙線程模型
- WXML模板和WXSS央視運(yùn)行于渲染層,渲染層使用WebView線程渲染(一個(gè)程序有多個(gè)頁面丽焊,會(huì)使用多個(gè)WebView的線程)掷倔。
- JS腳本(app.js/home.js等)運(yùn)行有邏輯層眉孩,邏輯層使用JSCore運(yùn)行JS腳本。
- 這兩個(gè)線程都會(huì)經(jīng)由微信客戶端(Native)進(jìn)行中轉(zhuǎn)交互勒葱。
- 誰是小程序的宿主環(huán)境?微信客戶端
界面渲染過程
- 初始化渲染
-
wxml等價(jià)于一顆DOM樹浪汪,也可以使用一個(gè)JS對(duì)象來模擬(虛擬DOM)
-
WXML可以先轉(zhuǎn)成JS對(duì)象,再渲染出真正的DOM樹
-
- 數(shù)據(jù)發(fā)生變化
- 通過setData把msg數(shù)據(jù)從“Hello World”變成“Goodbye”
- 產(chǎn)生的JS對(duì)象對(duì)應(yīng)的節(jié)點(diǎn)就會(huì)發(fā)生變化
- 此時(shí)可以對(duì)比前后兩個(gè)JS對(duì)象得到變化的部分
- 然后把這個(gè)差異應(yīng)用到原來的DOM樹上
- 從而達(dá)到更新UI的目的凛虽,這就是“數(shù)據(jù)驅(qū)動(dòng)”的原理
- 通過setData把msg數(shù)據(jù)從“Hello World”變成“Goodbye”
- 界面渲染整體流程
- 在渲染層死遭,宿主環(huán)境會(huì)把WXML轉(zhuǎn)化成對(duì)應(yīng)的JS對(duì)象;
- 將JS對(duì)象再次轉(zhuǎn)成真實(shí)DOM樹凯旋,交由渲染層線程渲染呀潭;
- 數(shù)據(jù)變化時(shí),邏輯層提供最新的變化數(shù)據(jù)至非,JS對(duì)象發(fā)生變化比較進(jìn)行diff算法對(duì)比钠署;
- 將最新變化的內(nèi)容反映到真實(shí)的DOM樹中,更新UI荒椭;
-
小程序的啟動(dòng)流程
- 官方文檔
- 每個(gè)小程序都需要在app.js中調(diào)用App方法注冊(cè)小程序?qū)嵗?/li>
-
在注冊(cè)時(shí)谐鼎,可以綁定對(duì)應(yīng)的生命周期函數(shù),在生命周期函數(shù)中趣惠,執(zhí)行對(duì)應(yīng)的代碼
-
事件-常見的事件類型
- 什么時(shí)候會(huì)產(chǎn)生事件呢狸棍?
- 小程序需要經(jīng)常和用戶進(jìn)行某種交互,比如點(diǎn)擊界面上的某個(gè)按鈕或者區(qū)域信卡,比如滑動(dòng)了某個(gè)區(qū)域隔缀,這些交互都會(huì)產(chǎn)生各種各樣的事件*;
- 事件是如何處理的呢傍菇?
- 事件是通過bind/catch這個(gè)屬性綁定在組件上的(和普通的屬性寫法很相似猾瘸,以key=“value”形式);
- key以bind或catch開發(fā)丢习,從1.5.0版本開始牵触,可以在bind和catch后加上一個(gè)冒號(hào);
- 同時(shí)在當(dāng)前頁面的Page構(gòu)造器中定義對(duì)應(yīng)的事件處理函數(shù)tapName咐低,如果沒有對(duì)應(yīng)的函數(shù)揽思,觸發(fā)事件時(shí)會(huì)報(bào)錯(cuò)
- 當(dāng)用戶點(diǎn)擊該button區(qū)域時(shí),達(dá)到觸發(fā)條件生成事件tap见擦,該事件處理函數(shù)tapName會(huì)被執(zhí)行钉汗,同時(shí)還會(huì)收到一個(gè)事件對(duì)象event羹令。
- 某些組件會(huì)有自己特性的事件類型,具體查看官方文檔
- 比如input有bindinput/bindblur/bindfocus等
- 比如scroll-view有bindscrolltowpper/bindscrolltolower等
- Touchcancle:在某些特定場(chǎng)景下才會(huì)觸發(fā)(比如來電打斷等)
- tap事件和longpress事件通常只會(huì)觸發(fā)其中一個(gè)
- 什么時(shí)候會(huì)產(chǎn)生事件呢狸棍?
-
組件化開發(fā)
-
組件和頁面樣式細(xì)節(jié)
-
給組件傳遞數(shù)據(jù)和樣式
頁面與組件之間傳遞數(shù)據(jù)使用properties
-
定義組件
my-prop
(my-prop.xml)<view class='title titleclass'>{{title}}</view> <view class='content'>我是組件的內(nèi)容</view>
-
在my-prop.js中定義title的相關(guān)屬性
Component({ properties: { // title: String title: { type: String, value: '我是默認(rèn)的標(biāo)題', observer: function(newVal, oldVal) { console.log(newVal, oldVal) } } }, externalClasses: ['titleclass'] })
observer是記錄改變前后的值
externalClasses讓外界給我們傳遞一個(gè)不一樣的樣式,在my-prop中引用之后损痰,頁面需要賦予titleclass一個(gè)樣式福侈,然后這個(gè)樣式需要在頁面的css中賦予屬性
```
.red {
color: red;
}.green { color: green; } .blue { color: blue; }
-
在頁面(home.xml)中引用組件
my-prop
,并定義title的內(nèi)容<!-- 3.給自定義組件傳遞數(shù)據(jù)/樣式 --> <my-prop title="哈哈哈" titleclass="red"/> <my-prop title="呵呵呵" titleclass="green"/> <my-prop titleclass="blue"/>
頁面(home.xml)中title定義的“哈哈哈”“呵呵呵”會(huì)傳遞給組件my-prop.xml中{{title}}的插值表達(dá)式卢未,此時(shí)組件根據(jù)頁面定義的title展示對(duì)應(yīng)的“哈哈哈”“呵呵呵”
-
- 組件向外傳遞事件-自定義事件
- 示例:點(diǎn)擊組件中的按鈕改變頁面中的數(shù)據(jù)
- 自定義組件(my-event.wxml)
<button size='mini' bind:tap="handleIncrement">+1</button>
- 通過
triggerEvent
發(fā)射事件肪凛,可以傳遞一個(gè)對(duì)象(my-event.js)注意:在頁面中寫方法直接寫,在組件中寫方法需要在methods中寫Component({ methods: { handleIncrement() { // console.log('---------') // 傳遞一個(gè)叫increment的事件辽社,傳遞參數(shù)數(shù)組 this.triggerEvent('increment', {name: 'why', age: 18}, {}) } })
- 在頁面(home.wxml)中引用組件并監(jiān)聽事件
<!-- 4.組件內(nèi)部發(fā)出事件 --> <view>當(dāng)前計(jì)數(shù): {{counter}}</view> <my-event bind:increment="handleIncrement"/>
- 在頁面的邏輯層(home.js)中定義handleIncrement事件,這里相當(dāng)于組件把事件發(fā)射給了頁面伟墙,此時(shí)這個(gè)事件就屬于頁面的邏輯,因此在頁面的邏輯層編寫滴铅。
Page({ data:{ counter:0, }, handleIncrement(event) { console.log('---------', event) this.setData({ counter: this.data.counter + 1 }) }, })
-
-
獲取組件對(duì)象的方式
- 在my-sel.wxml中定義一個(gè)組件
<view>組件內(nèi)的計(jì)數(shù): {{counter}}</view>
- 在home.wxml中引用組件my-sel戳葵,并定義一個(gè)按鈕綁定點(diǎn)擊事件
<!-- 6.直接選中組件修改數(shù)據(jù)/調(diào)用方法 --> <button size='mini' bind:tap="handleIncrementCpn">修改組件內(nèi)的數(shù)據(jù)</button> <my-sel class="sel-class" id="sel-id"/>
- 在home.js中獲取組件對(duì)象
handleIncrementCpn() { // 最終目的: 修改my-sel中的counter // 1.獲取組件對(duì)象 const my_sel = this.selectComponent('.sel-class') console.log(my_sel) // 2.通過setData修改組件中的數(shù)據(jù)(不合理,不規(guī)范) // my_sel.setData({ // counter: my_sel.data.counter + 20 // }) // 3.通過調(diào)用my-sel.js暴露出來的方法對(duì)數(shù)據(jù)進(jìn)行修改 my_sel.incrementCounter(10) },
- 在my-sel.js中定義方法給頁面調(diào)用
methods: { incrementCounter(num) { this.setData({ counter: this.data.counter + num }) } }
-
插槽的使用
-
component構(gòu)造器