目錄
一、自定義組件
1. 組件的創(chuàng)建與引用
1.1 創(chuàng)建組件
1.2?引用組件
1.2.1?局部引用組件
1.2.2 全局引用組件
1.2.3?全局引用 VS 局部引用
1.2.4?組件和頁面的區(qū)別
2. 樣式
2.1?組件樣式隔離
2.2?組件樣式隔離的注意點
2.3?修改組件的樣式隔離選項
2.4?styleIsolation 的可選值
3. 數(shù)據(jù)、方法和屬性
3.1?data 數(shù)據(jù)
3.2 methods方法
3.3?properties 屬性
3.4?data 和 properties 的區(qū)別
3.5?使用 setData 修改 properties 的值
4. 數(shù)據(jù)監(jiān)聽器
4.1 什么是數(shù)據(jù)監(jiān)聽器
4.2?數(shù)據(jù)監(jiān)聽器的基本用法
4.3?監(jiān)聽對象屬性的變化
5.?數(shù)據(jù)監(jiān)聽器 - 案例
1. 案例效果
2.?渲染 UI 結(jié)構(gòu)
3.?定義 button 的事件處理函數(shù)
4. 監(jiān)聽對象中指定屬性的變化
5.?監(jiān)聽對象中所有屬性的變化
6. 純數(shù)據(jù)字段
6.1 什么是純數(shù)據(jù)字段
6.2 使用規(guī)則
6.3?使用純數(shù)據(jù)字段改造數(shù)據(jù)監(jiān)聽器案例
7. 組件的生命周期
7.1?組件全部的生命周期函數(shù)
7.2?組件主要的生命周期函數(shù)
7.3?lifetimes 節(jié)點
8. 組件所在頁面的生命周期
8.1?什么是組件所在頁面的生命周期
8.2?pageLifetimes 節(jié)點
8.3?生成隨機的 RGB 顏色值
9. 插槽
9.1 什么是插槽
9.2.?單個插槽
9.3?啟用多個插槽
9.4 定義多個插槽
9.5?使用多個插槽
10.?父子組件之間的通信
10.1?父子組件之間通信的 3 種方式
10.1.1 屬性綁定
10.1.2 事件綁定
10.1.3 獲取組件實例
11. behaviors
11.1?什么是 behaviors
11.2?behaviors 的工作方式
11.3?創(chuàng)建 behavior
11.4?導入并使用 behavior
11.5?behavior 中所有可用的節(jié)點
11.6?同名字段的覆蓋和組合規(guī)則*
?? 自定義組件小結(jié)
二、使用npm包
1. 小程序?qū)?npm 的支持與限制
2. Vant Weapp
2.1?什么是 Vant Weapp
2.2?安裝 Vant 組件庫
2.3.?使用 Vant 組件
2.4?定制全局主題樣式
3. API Promise化
3.1?基于回調(diào)函數(shù)的異步 API 的缺點
3.2?什么是 API Promise 化
3.3?實現(xiàn) API Promise 化
3.4?調(diào)用 Promise 化之后的異步 API
三、全局數(shù)據(jù)共享
1.?什么是全局數(shù)據(jù)共享
2.?小程序中的全局數(shù)據(jù)共享方案
2.1 MobX
2.1.1?安裝 MobX 相關(guān)的包
2.1.2?創(chuàng)建 MobX 的 Store 實例
2.1.3?將 Store 中的成員綁定到頁面中
2.1.4?在頁面上使用 Store 中的成員
2.1.5?將 Store 中的成員綁定到組件中
2.1.6?在組件中使用 Store 中的成員
四、分包
1. 基礎(chǔ)概念
1.1 什么是分包
1.2 分包的好處
1.3?分包前項目的構(gòu)成
1.4?分包后項目的構(gòu)成
1.5 分包的加載規(guī)則
1.6 分包的體積
2. 使用分包
2.1?配置方法
2.2 打包原則
2.3 引用原則
3. 獨立分包
3.1 什么是獨立分包
3.2 獨立分包和普通分包的區(qū)別
3.3 獨立分包的應用場景
3.4?獨立分包的配置方法
3.5 引用原則
4. 分包預下載
4.1 什么是分包預下載
4.2 配置分包的預下載
4.3 分包預下載的限制
???案例 - 自定義 tabBar
?? 小結(jié)一下
一、自定義組件
1. 組件的創(chuàng)建與引用
1.1 創(chuàng)建組件
①在項目的根目錄中,鼠標右鍵,創(chuàng)建 components -> test 文件夾
②在新建的 components -> test 文件夾上,鼠標右鍵,點擊“?新建 Component?”
③鍵入組件的名稱之后回車,會自動生成組件對應的 4 個文件,后綴名分別為 .js,.json, .wxml 和 .wxss
注意:為了保證目錄結(jié)構(gòu)的清晰,建議把不同的組件,存放到單獨目錄中,例如:
1.2?引用組件
組件的引用方式分為“局部引用”和“全局引用”,顧名思義:?
● 局部引用:組件只能在當前被引用的頁面內(nèi)使用
● 全局引用:組件可以在每個小程序頁面中使用
1.2.1?局部引用組件
在頁面的 .json 配置文件中引用組件的方式,叫做“局部引用”。示例代碼如下:
1.2.2 全局引用組件
在 app.json 全局配置文件中引用組件的方式,叫做“全局引用”。示例代碼如下:
1.2.3?全局引用 VS 局部引用
根據(jù)組件的使用頻率和范圍,來選擇合適的引用方式:
● 如果某組件在多個頁面中經(jīng)常被用到,建議進行“全局引用”
● 如果某組件只在特定的頁面中被用到,建議進行“局部引用”
1.2.4?組件和頁面的區(qū)別
從表面來看,組件和頁面都是由 .js、.json、.wxml 和 .wxss 這四個文件組成的。但是,組件和頁面的 .js 與 .json 文件有明顯的不同:
● 組件的 .json 文件中需要聲明 "component": true 屬性
● 組件的 .js 文件中調(diào)用的是 Component() 函數(shù)
● 組件的事件處理函數(shù)需要定義到 methods 節(jié)點中
2. 樣式
2.1?組件樣式隔離
默認情況下,自定義組件的樣式只對當前組件生效,不會影響到組件之外的 UI 結(jié)構(gòu),如圖所示:
組件 A 的樣式不會影響組件 C 的樣式
組件 A 的樣式不會影響小程序頁面的樣式
小程序頁面的樣式不會影響組件 A 和 C 的樣式
好處:
①?防止外界的樣式影響組件內(nèi)部的樣式
②?防止組件的樣式破壞外界的樣式
2.2?組件樣式隔離的注意點
● app.wxss 中的全局樣式對組件無效
● 只有 class 選擇器會有樣式隔離效果,id 選擇器、屬性選擇器、標簽選擇器不受樣式隔離的影響
建議:在組件和引用組件的頁面中建議使用 class 選擇器,不要使用 id、屬性、標簽選擇器!
2.3?修改組件的樣式隔離選項
默認情況下,自定義組件的樣式隔離特性能夠防止組件內(nèi)外樣式互相干擾的問題。但有時,我們希望在外界能夠控制組件內(nèi)部的樣式,此時,可以通過 styleIsolation 修改組件的樣式隔離選項,用法如下:
2.4?styleIsolation 的可選值
可選值 |
默認值 |
描述 |
isolated |
是 |
表示啟用樣式隔離,在自定義組件內(nèi)外,使用 class 指定的樣式將不會相互影響 |
apply-shared |
否 |
表示頁面 wxss 樣式將影響到自定義組件,但自定義組件 wxss 中指定的樣式不會影響頁面 |
shared |
否 |
表示頁面 wxss 樣式將影響到自定義組件,自定義組件 wxss 中指定的樣式也會影響頁面和其他設置了 apply-shared 或 shared 的自定義組件 |
3. 數(shù)據(jù)、方法和屬性
3.1?data 數(shù)據(jù)
在小程序組件中,用于組件模板渲染的私有數(shù)據(jù),需要定義到 data 節(jié)點中,示例如下:
3.2 methods方法
在小程序組件中,事件處理函數(shù)和自定義方法需要定義到 methods 節(jié)點中,示例代碼如下:
3.3?properties 屬性
在小程序組件中,properties 是組件的對外屬性,用來接收外界傳遞到組件中的數(shù)據(jù),示例代碼如下:
3.4?data 和 properties 的區(qū)別
在小程序的組件中,properties 屬性和 data 數(shù)據(jù)的用法相同,它們都是可讀可寫的,只不過:
● data 更傾向于存儲組件的私有數(shù)據(jù)
● properties 更傾向于存儲外界傳遞到組件中的數(shù)據(jù)
3.5?使用 setData 修改 properties 的值
由于 data 數(shù)據(jù)和 properties 屬性在本質(zhì)上沒有任何區(qū)別,因此 properties 屬性的值也可以用于頁面渲染,或使用 setData 為 properties 中的屬性重新賦值,示例代碼如下:
4. 數(shù)據(jù)監(jiān)聽器
4.1 什么是數(shù)據(jù)監(jiān)聽器
數(shù)據(jù)監(jiān)聽器用于監(jiān)聽和響應任何屬性和數(shù)據(jù)字段的變化,從而執(zhí)行特定的操作。它的作用類似于 vue 中的 watch 偵聽器。在小程序組件中,數(shù)據(jù)監(jiān)聽器的基本語法格式如下:
4.2?數(shù)據(jù)監(jiān)聽器的基本用法
組件的 UI 結(jié)構(gòu)如下:
組件的 .js 文件代碼如下:
4.3?監(jiān)聽對象屬性的變化
數(shù)據(jù)監(jiān)聽器支持監(jiān)聽對象中單個或多個屬性的變化,示例語法如下:
5.?數(shù)據(jù)監(jiān)聽器 - 案例
1. 案例效果
2.?渲染 UI 結(jié)構(gòu)
3.?定義 button 的事件處理函數(shù)
4. 監(jiān)聽對象中指定屬性的變化
5.?監(jiān)聽對象中所有屬性的變化
如果某個對象中需要被監(jiān)聽的屬性太多,為了方便,可以使用通配符 ** 來監(jiān)聽對象中所有屬性的變化,示例代碼如下:
6. 純數(shù)據(jù)字段
6.1 什么是純數(shù)據(jù)字段
概念:純數(shù)據(jù)字段指的是那些不用于界面渲染的 data 字段。
應用場景:例如有些情況下,某些 data 中的字段既不會展示在界面上,也不會傳遞給其他組件,僅僅在當前組件內(nèi)部使用。帶有這種特性的 data 字段適合被設置為純數(shù)據(jù)字段。
好處:純數(shù)據(jù)字段有助于提升頁面更新的性能。
6.2 使用規(guī)則
在 Component 構(gòu)造器的 options 節(jié)點中,指定 pureDataPattern 為一個正則表達式,字段名符合這個正則表達式的字段將成為純數(shù)據(jù)字段,示例代碼如下:
6.3?使用純數(shù)據(jù)字段改造數(shù)據(jù)監(jiān)聽器案例
7. 組件的生命周期
7.1?組件全部的生命周期函數(shù)
小程序組件可用的全部生命周期如下表所示:
生命周期函數(shù) |
參數(shù) |
描述說明 |
created |
無 |
在組件實例剛剛被創(chuàng)建時執(zhí)行 |
attached |
無 |
在組件實例進入頁面節(jié)點樹時執(zhí)行 |
ready |
無 |
在組件在視圖層布局完成后執(zhí)行 |
moved |
無 |
在組件實例被移動到節(jié)點樹另一個位置時執(zhí)行 |
detached |
無 |
在組件實例被從頁面節(jié)點樹移除時執(zhí)行 |
error |
Object Error |
每當組件方法拋出錯誤時執(zhí)行 |
注:關(guān)于組件生命周期函數(shù)執(zhí)行的時機說明
? created
在執(zhí)行created生命周期函數(shù)時,證明組件剛被創(chuàng)建好,但是這個組件還沒有被放到小程序頁面中進行渲染(顯示),此時我們能做的事情是比較少的
? attached
組件創(chuàng)建好以后,緊接著就需要把創(chuàng)建好的組件放進頁面節(jié)點樹里,那么組件剛一被放進節(jié)點樹的時候,此時就會執(zhí)行attached生命周期函數(shù)
? ready
在執(zhí)行attached期間,組件只是剛被放進頁面的UI結(jié)構(gòu)中,但是這個組件還未被渲染,接下來就是組件在頁面上來被真正的渲染出來,當組件被渲染完成以后會執(zhí)行組件的ready生命周期函數(shù),所以ready生命周期函數(shù)執(zhí)行的時機就是在組件剛被渲染完成之后
7.2?組件主要的生命周期函數(shù)
在小程序組件中,最重要的生命周期函數(shù)有 3 個,分別是 created、attached、detached。它們各自的特點如下:
① 組件實例剛被創(chuàng)建好的時候,created 生命周期函數(shù)會被觸發(fā)
● 此時還不能調(diào)用 setData
● 通常在這個生命周期函數(shù)中,只應該用于給組件的 this 添加一些自定義的屬性字段
② 在組件完全初始化完畢、進入頁面節(jié)點樹后, attached 生命周期函數(shù)會被觸發(fā)
● 此時, this.data 已被初始化完畢
● 這個生命周期很有用,絕大多數(shù)初始化的工作可以在這個時機進行(例如發(fā)請求獲取初始數(shù)據(jù))
③ 在組件離開頁面節(jié)點樹后, detached 生命周期函數(shù)會被觸發(fā)
● 退出一個頁面時,會觸發(fā)頁面內(nèi)每個自定義組件的 detached 生命周期函數(shù)
● 此時適合做一些清理性質(zhì)的工作
7.3?lifetimes 節(jié)點
在小程序組件中,生命周期函數(shù)可以直接定義在 Component 構(gòu)造器的第一級參數(shù)中,可以在 lifetimes 字段內(nèi)進行聲明(這是推薦的方式,其優(yōu)先級最高)。示例代碼如下:
8. 組件所在頁面的生命周期
8.1?什么是組件所在頁面的生命周期
有時,自定義組件的行為依賴于頁面狀態(tài)的變化,此時就需要用到組件所在頁面的生命周期。
也就是說,在組件的js文件中,可以監(jiān)聽頁面狀態(tài)的變化即可以監(jiān)聽組件所在頁面的生命周期,然后去執(zhí)行一些操作
例如:每當觸發(fā)頁面的 show 生命周期函數(shù)的時候,我們希望能夠重新生成一個隨機的 RGB 顏色值。
下面我們來看一下,在組件里面都可以訪問頁面的哪些生命周期函數(shù)
在自定義組件中,組件所在頁面的生命周期函數(shù)有如下 3 個,分別是:
生命周期函數(shù) |
參數(shù) |
描述 |
show |
無 |
組件所在的頁面被展示時執(zhí)行 |
hide |
無 |
組件所在的頁面被隱藏時執(zhí)行 |
resize |
Object Size |
組件所在的頁面尺寸變化時執(zhí)行 |
8.2?pageLifetimes 節(jié)點
組件所在頁面的生命周期函數(shù),需要定義在 pageLifetimes 節(jié)點中,示例代碼如下:
8.3?生成隨機的 RGB 顏色值
9. 插槽
9.1 什么是插槽
在自定義組件的 wxml 結(jié)構(gòu)中,可以提供一個 <slot> 節(jié)點(插槽),用于承載組件使用者提供的 wxml 結(jié)構(gòu)。
9.2.?單個插槽
在小程序中,默認每個自定義組件中只允許使用一個 <slot> 進行占位,這種個數(shù)上的限制叫做單個插槽。
9.3?啟用多個插槽
在小程序的自定義組件中,需要使用多 <slot> 插槽時,可以在組件的 .js 文件中,通過如下方式進行啟用。
9.4 定義多個插槽
可以在組件的 .wxml 中使用多個 <slot> 標簽,以不同的 name 來區(qū)分不同的插槽。示例代碼如下:
9.5?使用多個插槽
在使用帶有多個插槽的自定義組件時,需要用 slot 屬性來將節(jié)點插入到不同的 <slot> 中。示例代碼如下:
10.?父子組件之間的通信
10.1?父子組件之間通信的 3 種方式
①?屬性綁定
● 用于父組件向子組件的指定屬性設置數(shù)據(jù),僅能設置 JSON 兼容的數(shù)據(jù)
②?事件綁定
● 用于子組件向父組件傳遞數(shù)據(jù),可以傳遞任意數(shù)據(jù)
③?獲取組件實例
● 父組件還可以通過 this.selectComponent() 獲取子組件實例對象
● 這樣就可以直接訪問子組件的任意數(shù)據(jù)和方法
10.1.1 屬性綁定
屬性綁定用于實現(xiàn)父向子傳值,而且只能傳遞普通類型的數(shù)據(jù),無法將方法傳遞給子組件。父組件的示例代碼如下:
子組件在 properties 節(jié)點中聲明對應的屬性并使用。示例代碼如下:
10.1.2 事件綁定
事件綁定用于實現(xiàn)子向父傳值,可以傳遞任何類型的數(shù)據(jù)。使用步驟如下:
①在父組件的 js 中,定義一個函數(shù),這個函數(shù)即將通過自定義事件的形式,傳遞給子組件
②在父組件的 wxml 中,通過自定義事件的形式,將步驟 1 中定義的函數(shù)引用,傳遞給子組件
③在子組件的 js 中,通過調(diào)用 this.triggerEvent('自定義事件名稱', { /* 參數(shù)對象 */ }) ,將數(shù)據(jù)發(fā)送到父組件
④在父組件的 js 中,通過 e.detail 獲取到子組件傳遞過來的數(shù)據(jù)
步驟1:在父組件的 js 中,定義一個函數(shù),這個函數(shù)即將通過自定義事件的形式,傳遞給子組件。
步驟2:在父組件的 wxml 中,通過自定義事件的形式,將步驟 1 中定義的函數(shù)引用,傳遞給子組件。
步驟3:在子組件的 js 中,通過調(diào)用 this.triggerEvent(‘自定義事件名稱’, { /* 參數(shù)對象 */ }) ,將數(shù)據(jù)發(fā)送到父組件。
步驟4:在父組件的 js 中,通過 e.detail 獲取到子組件傳遞過來的數(shù)據(jù)。
10.1.3 獲取組件實例
可在父組件里調(diào)用 this.selectComponent("id或class選擇器") ,獲取子組件的實例對象,從而直接訪問子組件的任意數(shù)據(jù)和方法。調(diào)用時需要傳入一個選擇器,例如 this.selectComponent(".my-component")。
11. behaviors
11.1?什么是 behaviors
behaviors 是小程序中,用于實現(xiàn)組件間代碼共享的特性,類似于 Vue.js 中的 “mixins”。
11.2?behaviors 的工作方式
每個 behavior 可以包含一組屬性、數(shù)據(jù)、生命周期函數(shù)和方法。組件引用它時,它的屬性、數(shù)據(jù)和方法會被合并到組件中。
每個組件可以引用多個 behavior,behavior 也可以引用其它 behavior。
11.3?創(chuàng)建 behavior
調(diào)用 Behavior(Object object) 方法即可創(chuàng)建一個共享的 behavior 實例對象,供所有的組件使用:
11.4?導入并使用 behavior
在組件中,使用 require() 方法導入需要的 behavior,掛載后即可訪問 behavior 中的數(shù)據(jù)或方法,示例代碼如下:
11.5?behavior 中所有可用的節(jié)點
可用的節(jié)點 |
類型 |
是否必填 |
描述 |
properties |
Object Map |
否 |
同組件的屬性 |
data |
Object |
否 |
同組件的數(shù)據(jù) |
methods |
Object |
否 |
同自定義組件的方法 |
behaviors |
String Array |
否 |
引入其它的 behavior |
created |
Function |
否 |
生命周期函數(shù) |
attached |
Function |
否 |
生命周期函數(shù) |
ready |
Function |
否 |
生命周期函數(shù) |
moved |
Function |
否 |
生命周期函數(shù) |
detached |
Function |
否 |
生命周期函數(shù) |
11.6?同名字段的覆蓋和組合規(guī)則*
組件和它引用的 behavior 中可以包含同名的字段,此時可以參考如下 3 種同名時的處理規(guī)則:
①同名的數(shù)據(jù)字段 (data)
②同名的屬性 (properties) 或方法 (methods)
③同名的生命周期函數(shù)
關(guān)于詳細的覆蓋和組合規(guī)則,大家可以參考微信小程序官方文檔給出的說明:
behaviors | 微信開放文檔
?? 自定義組件小結(jié)
①能夠創(chuàng)建并引用組件
? 全局引用、局部引用、usingComponents
②能夠知道如何修改組件的樣式隔離選項
? options -> styleIsolation( isolated, apply-shared, shared)
③能夠知道如何定義和使用數(shù)據(jù)監(jiān)聽器
? observers
④能夠知道如何定義和使用純數(shù)據(jù)字段
? options -> pureDataPattern
⑤能夠知道實現(xiàn)組件父子通信有哪3種方式
? 屬性綁定、事件綁定、this.selectComponent(' id或class選擇器')
⑥能夠知道如何定義和使用behaviors
? 調(diào)用 Behavior() 構(gòu)造器方法?
二、使用npm包
1. 小程序?qū)?npm 的支持與限制
從小程序基礎(chǔ)庫版本?2.2.1?或以上、及開發(fā)者工具?1.02.1808300 或以上開始,小程序支持使用 npm 安裝第三方包。
目前,小程序中已經(jīng)支持使用 npm 安裝第三方包,從而來提高小程序的開發(fā)效率。但是,在小程序中使用 npm 包有如下 3 個限制:
①不支持依賴于 Node.js 內(nèi)置庫的包
某些npm包依賴于nodejs里的核心模塊,如依賴于fs模塊的包等,這些包就無法在小程序里使用,因為小程序并沒有提供nidejs這樣一個運行環(huán)境。
②不支持依賴于瀏覽器內(nèi)置對象的包
比如,jQuery,因為jQuery依賴于瀏覽器的window等這些內(nèi)置對象。但是小程序并不提供像瀏覽器里這些內(nèi)置對象,所以說依賴于瀏覽器內(nèi)置對象的包,也無法在小程序中正常的運行。
③不支持依賴于 C++ 插件的包
比如,npm上一些負責加密的包,它會依賴于C++的插件來提高加密的性能,但是小程序中不提供C++的運行環(huán)境,所以說在小程序也不支持依賴于 C++ 插件的包
總結(jié):雖然 npm 上的包有千千萬,但是能供小程序使用的包卻“為數(shù)不多”。
2. Vant Weapp
2.1?什么是 Vant Weapp
Vant Weapp 是有贊前端團隊開源的一套小程序 UI 組件庫,助力開發(fā)者快速搭建小程序應用。它所使用的是 MIT 開源許可協(xié)議,對商業(yè)使用比較友好。
?? 官方文檔地址 Vant Weapp - 輕量、可靠的小程序 UI 組件庫
掃描下方的小程序二維碼,體驗組件庫示例:
2.2?安裝 Vant 組件庫
在小程序項目中,安裝 Vant 組件庫主要分為如下 3 步:
①通過 npm 安裝(建議指定版本為@1.3.3)
安裝之前,需要在小程序根目錄中打開命令行工具,使用 npm init -y 初始化一個package.json包管理文件。
②構(gòu)建 npm 包
③修改 app.json
詳細的操作步驟,大家可以參考 Vant 官方提供的快速上手教程:
https://youzan.github.io/vant-weapp/#/quickstart#an-zhuang
2.3.?使用 Vant 組件
安裝完 Vant 組件庫之后,可以在 app.json 的 usingComponents 節(jié)點中引入需要的組件,即可在 wxml 中直接使用組件。示例代碼如下:
2.4?定制全局主題樣式
Vant Weapp 使用 CSS 變量來實現(xiàn)定制主題。 關(guān)于 CSS 變量的基本用法,請參考 MDN 文檔:使用 CSS 自定義屬性(變量) - CSS:層疊樣式表 | MDN
在 app.wxss 中,寫入 CSS 變量,即可對全局生效:
所有可用的顏色變量,請參考 Vant 官方提供的配置文件:https://github.com/youzan/vant-weapp/blob/dev/packages/common/style/var.less
注:page標簽是小程序每個頁面的根節(jié)點,所以說我們可以拿page標簽定義樣式變量,這樣小程序每個頁面都可以訪問到這些CSS變量
3. API Promise化
3.1?基于回調(diào)函數(shù)的異步 API 的缺點
默認情況下,小程序官方提供的異步 API 都是基于回調(diào)函數(shù)實現(xiàn)的,例如,網(wǎng)絡請求的 API 需要按照如下的方式調(diào)用:
缺點:容易造成回調(diào)地獄的問題,代碼的可讀性、維護性差!
3.2?什么是 API Promise 化
API Promise化,指的是通過額外的配置,將官方提供的、基于回調(diào)函數(shù)的異步 API,升級改造為基于 Promise 的異步 API,從而提高代碼的可讀性、維護性,避免回調(diào)地獄的問題。
3.3?實現(xiàn) API Promise 化
在小程序中,實現(xiàn) API Promise 化主要依賴于 miniprogram-api-promise 這個第三方的 npm 包。它的安裝和使用步驟如下:
3.4?調(diào)用 Promise 化之后的異步 API
三、全局數(shù)據(jù)共享
1.?什么是全局數(shù)據(jù)共享
全局數(shù)據(jù)共享(又叫做:狀態(tài)管理)是為了解決組件之間數(shù)據(jù)共享的問題。
開發(fā)中常用的全局數(shù)據(jù)共享方案有:Vuex、Redux、MobX 等。
2.?小程序中的全局數(shù)據(jù)共享方案
在小程序中,可使用 mobx-miniprogram 配合 mobx-miniprogram-bindings 實現(xiàn)全局數(shù)據(jù)共享。其中:
● mobx-miniprogram 用來創(chuàng)建 Store 實例對象
● mobx-miniprogram-bindings 用來把 Store 中的共享數(shù)據(jù)或方法,綁定到組件或頁面
2.1 MobX
2.1.1?安裝 MobX 相關(guān)的包
在項目中運行如下的命令,安裝 MobX 相關(guān)的包:
注意:MobX 相關(guān)的包安裝完畢之后,記得刪除 miniprogram_npm 目錄后,重新構(gòu)建 npm。
2.1.2?創(chuàng)建 MobX 的 Store 實例
2.1.3?將 Store 中的成員綁定到頁面中
2.1.4?在頁面上使用 Store 中的成員
2.1.5?將 Store 中的成員綁定到組件中
2.1.6?在組件中使用 Store 中的成員
四、分包
1. 基礎(chǔ)概念
1.1 什么是分包
分包指的是把一個完整的小程序項目,按照需求劃分為不同的子包,在構(gòu)建時打包成不同的分包,用戶在使用時按需進行加載。
1.2 分包的好處
對小程序進行分包的好處主要有以下兩點:
● 可以優(yōu)化小程序首次啟動的下載時間
默認情況下,小程序不會對項目進行分包,所有的頁面都是打包到一起的,用戶在首次啟動時,小程序需要把整個項目下載下來才能運行,此時項目體積會比較打,因此會導致首次啟動小程序的下載時間比較長。如果采用分包的話,可以先把首頁下載下來,于是就可提高小程序首次啟動的下載時間。
● 在多團隊共同開發(fā)時可以更好的解耦協(xié)作
比如,我們可以按照功能的不同,將小程序劃分為不同的子包,由不同的人負責不同的功能,每個人負責一個分包的開發(fā),開發(fā)效率會更高一些。
1.3?分包前項目的構(gòu)成
分包前,小程序項目中所有的頁面和資源都被打包到了一起,導致整個項目體積過大,影響小程序首次啟動的下載時間。
1.4?分包后項目的構(gòu)成
分包后,小程序項目由 1 個主包 + 多個分包組成:
● 主包:一般只包含項目的啟動頁面或 TabBar 頁面、以及所有分包都需要用到的一些公共資源
● 分包:只包含和當前分包有關(guān)的頁面和私有資源
1.5 分包的加載規(guī)則
①在小程序啟動時,默認會下載主包并啟動主包內(nèi)頁面
● tabBar 頁面需要放到主包中
②當用戶進入分包內(nèi)某個頁面時,客戶端會把對應分包下載下來,下載完成后再進行展示
● 非 tabBar 頁面可以按照功能的不同,劃分為不同的分包之后,進行按需下載
1.6 分包的體積
目前,小程序分包的大小有以下兩個限制:
●? 整個小程序所有分包大小不超過 20M(主包 + 所有分包)
● 單個分包/主包大小不能超過 2M
2. 使用分包
2.1?配置方法
2.2 打包原則
①?小程序會按 subpackages 的配置進行分包,subpackages 之外的目錄將被打包到主包中
②?主包也可以有自己的 pages(即最外層的 pages 字段)
③?tabBar 頁面必須在主包內(nèi)
④?分包之間不能互相嵌套
2.3 引用原則
①主包無法引用分包內(nèi)的私有資源
②分包之間不能相互引用私有資源
③分包可以引用主包內(nèi)的公共資源
3. 獨立分包
3.1 什么是獨立分包
獨立分包本質(zhì)上也是分包,只不過它比較特殊,可以獨立于主包和其他分包而單獨運行。
3.2 獨立分包和普通分包的區(qū)別
最主要的區(qū)別:是否依賴于主包才能運行
● 普通分包必須依賴于主包才能運行
● 獨立分包可以在不下載主包的情況下,獨立運行
3.3 獨立分包的應用場景
開發(fā)者可以按需,將某些具有一定功能獨立性的頁面配置到獨立分包中。原因如下:
● 當小程序從普通的分包頁面啟動時,需要首先下載主包
● 而獨立分包不依賴主包即可運行,可以很大程度上提升分包頁面的啟動速度
注意:一個小程序中可以有多個獨立分包。
3.4?獨立分包的配置方法
3.5 引用原則
獨立分包和普通分包以及主包之間,是相互隔絕的,不能相互引用彼此的資源!例如:
①?主包無法引用獨立分包內(nèi)的私有資源
②?獨立分包之間,不能相互引用私有資源
③?獨立分包和普通分包之間,不能相互引用私有資源
④?特別注意:獨立分包中不能引用主包內(nèi)的公共資源(普通分包可以)
4. 分包預下載
4.1 什么是分包預下載
分包預下載指的是:在進入小程序的某個頁面時,由框架自動預下載可能需要的分包,從而提升進入后續(xù)分包頁面時的啟動速度。
4.2 配置分包的預下載
預下載分包的行為,會在進入指定的頁面時觸發(fā)。在 app.json 中,使用 preloadRule 節(jié)點定義分包的預下載規(guī)則,示例代碼如下:
4.3 分包預下載的限制
同一個分包中的頁面享有共同的預下載大小限額 2M,例如:
???案例 - 自定義 tabBar
? 案例效果
在此案例中,用到的主要知識點如下:
● 自定義組件
● Vant 組件庫
● MobX 數(shù)據(jù)共享
● 組件樣式隔離
● 組件數(shù)據(jù)監(jiān)聽器
● 組件的 behaviors
● Vant 樣式覆蓋
? 實現(xiàn)步驟
自定義 tabBar 分為 3 大步驟,分別是:
①配置信息
②添加 tabBar 代碼文件
③編寫 tabBar 代碼
詳細步驟,可以參考小程序官方給出的文檔:自定義 tabBar | 微信開放
主要代碼如下:?
* app.json
{
"pages": [
"pages/home/home",
"pages/message/message",
"pages/contact/contact"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#13A7A0",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
},
"tabBar": {
"custom": true,
"list": [{
"pagePath": "pages/home/home",
"text": "首頁",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png"
},
{
"pagePath": "pages/contact/contact",
"text": "聯(lián)系我們",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
},
"sitemapLocation": "sitemap.json",
"usingComponents": {
"van-button": "@vant/weapp/button/index",
"my-numbers": "./components/numbers/numbers",
"van-tabbar": "@vant/weapp/tabbar/index",
"van-tabbar-item": "@vant/weapp/tabbar-item/index"
}
}
* custom-tab-bar/index.wxml
<!--custom-tab-bar/index.wxml-->
<!-- <text>這是自定義的TabBar</text> -->
<!-- {{active}}屬性綁定,該值來自于組件腳本文件index.js中從store映射過來的activeTabBarIndex值即active: 'activeTabBarIndex' -->
<!-- Tabbar 標簽欄組件中的Tabbar屬性active-color 選中標簽的顏色,默認#7d7e80 -->
<van-tabbar active="{{active}}" bind:change="onChange" active-color="#13A7A0">
<!-- 按需渲染數(shù)字徽標—— item.info ? item.info : '' ——使用三元表達式判斷哪個tabbar上有徽標info屬性 -->
<van-tabbar-item wx:for="{{list}}" wx:key="index" info="{{item.info ? item.info : ''}}">
<image slot="icon" src="{{item.iconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
<image slot="icon-active" src="{{item.selectedIconPath}}" mode="aspectFit" style="width: 25px; height: 25px;" />
{{item.text}}
</van-tabbar-item>
</van-tabbar>
* custom-tab-bar/index.wxml
// custom-tab-bar/index.js
// storeBindingsBehavior 起到一個橋梁作用:將store里的數(shù)據(jù)或成員映射到當前組件里,來進行使用
import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
// store 數(shù)據(jù)源
import { store } from '../store/store'
Component({
options: {
// 在自定義組件中使用 Vant Weapp 組件時,如果想要在頁面的樣式文件中覆蓋組件的樣式需開啟
// 樣式覆蓋:https://youzan.github.io/vant-weapp/#/custom-style#jie-chu-yang-shi-ge-chi
styleIsolation: 'shared'
},
behaviors: [storeBindingsBehavior], // 通過 storeBindingsBehavior 來實現(xiàn)自棟動綁定
// 聲明一個配置對象
storeBindings: {
// 數(shù)據(jù)源:指定要綁定的數(shù)據(jù)源
store,
// 字段數(shù)據(jù):指定要綁定的字段數(shù)據(jù)
fields: {
sum: 'sum',
active: 'activeTabBarIndex'
},
// 方法:指定要綁定的方法
actions: {
updateActive: 'updateActiveTabBarIndex'
},
},
// 數(shù)據(jù)監(jiān)聽器
observers: {
// 監(jiān)聽sum獲取sum的最新值val
'sum': function (val) {
this.setData({
'list[1].info': val
})
}
},
/**
* 組件的屬性列表
*/
properties: {
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
// 把active抽離到store里進行公共存儲并命名為activeTabBarIndex,所以這里就不需要再定義了,直接使用從store映射過來的activeTabBarIndex即active: 'activeTabBarIndex'
// active: 0,
"list": [
{
"pagePath": "/pages/home/home",
"text": "首頁",
"iconPath": "/images/tabs/home.png",
"selectedIconPath": "/images/tabs/home-active.png"
},
{
"pagePath": "/pages/message/message",
"text": "消息",
"iconPath": "/images/tabs/message.png",
"selectedIconPath": "/images/tabs/message-active.png",
info: 0
},
{
"pagePath": "/pages/contact/contact",
"text": "聯(lián)系我們",
"iconPath": "/images/tabs/contact.png",
"selectedIconPath": "/images/tabs/contact-active.png"
}
]
},
/**
* 組件的方法列表
*/
methods: {
onChange(event) {
// event.detail 的值為當前選中項的索引
// 因為我們把在index.js文件中data里定義的active放在了store里,這里并未定義active,所以this.setData({ active: event.detail })就不使用了,直接使用從store里映射過來的action方法即可
// this.setData({ active: event.detail })
this.updateActive(event.detail)
// 切換tab頁面實現(xiàn)跳轉(zhuǎn)
wx.switchTab({
url: this.data.list[event.detail].pagePath,
})
},
}
})
* custom-tab-bar/index.wxss
/* custom-tab-bar/index.wxss */
/* vant的Tabbar 標簽欄組件圖標跟文字之間margin過大,顯示Tabbar徽標時越過當前Tabbar的范圍,需要重置為0 */
/* 在自定義組件中使用 Vant Weapp 組件時,如果想要在頁面的樣式文件中覆蓋組件的樣式需要在組件的js文件中開啟styleIsolation: 'shared' 配置項,如不開啟,無法覆蓋,樣式不生效*/
/* 樣式覆蓋:https://youzan.github.io/vant-weapp/#/custom-style#jie-chu-yang-shi-ge-chi */
.van-tabbar-item {
--tabbar-item-margin-bottom: 0;
}
* store/store.js
// 在這個 JS 文件中,專門來創(chuàng)建 Store 的實例對象
// 分析:按需導入mobx-miniprogram包的成員:observable 和 action 方法
import { observable, action } from 'mobx-miniprogram'
// observable方法用來創(chuàng)建 Store 的實例對象
// 分析:調(diào)用observable()方法得到一個實例對象,并按需導出,外界在使用時,導入store實例即可使用其中的數(shù)據(jù)與方法
export const store = observable({
// 數(shù)據(jù)字段
numA: 1,
numB: 2,
activeTabBarIndex: 0,
// 計算屬性
// 分析:計算屬性sum前的修飾符get表示當前計算屬性的值是只讀的 ——你只能獲取它的值,無法為它重新賦值。因為計算屬性的值不需要被重新賦值,它的值是依賴數(shù)據(jù)字段的變化自動進行計算的
get sum() {
return this.numA + this.numB
},
// actions 函數(shù),專門來修改 store 中數(shù)據(jù)的值
// 分析:聲明一些action方法如updateNum1、updateNum2,同時分別為他們指定一個function函數(shù),只不過這個函數(shù)需要被action方法包裹起來,即在外面我們需要先調(diào)用action方法,在action方法內(nèi)部傳一個function,通過這個function來修改store內(nèi)數(shù)據(jù)的值,外界傳過來的參數(shù),可以在function的形參里面進行接收,比如外界傳了一個步長值step,接下來可以根據(jù)這個step讓numA進行自增
updateNum1: action(function (step) { // 外界傳參可以使用action方法內(nèi)function的形參接收
this.numA += step
}),
updateNum2: action(function (step) {
this.numB += step
}),
updateActiveTabBarIndex: action(function (index) {
this.activeTabBarIndex = index
})
})
pages/message/message.wxml
<!--pages/message/message.wxml-->
<text>pages/message/message.wxml</text>
<view>~~~~~~</view>
<view>{{numA}} + {{numB}} = {{sum}}</view>
<van-button type="primary" bindtap="btnHandler1" data-step="{{1}}">numA + 1</van-button>
<van-button type="danger" bindtap="btnHandler1" data-step="{{-1}}">numA - 1</van-button>
pages/message/message.js
// pages/message/message.js
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from '../../store/store'
Page({
/**
* 頁面的初始數(shù)據(jù)
*/
data: {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面加載
*/
onLoad(options) {
// this指代當前頁面實例 配置對象包含3個屬性:數(shù)據(jù)源store、字段fields、方法actions
// 分析:調(diào)用createStoreBindings()方法,傳遞一個this(當前頁面實例)和一個配置對象,就可以將store里面對應的字段或?qū)姆椒ń壎ǖ疆斍绊撁娴膶嵗砩?,該方法的最終返回值掛載到頁面上作為當前頁面的一個自定義屬性而存在,這個屬性值storeBindings,作用是當當前頁面被卸載時可以在卸載處理函數(shù)中做請理性的工作
this.storeBindings = createStoreBindings(this, {
// 數(shù)據(jù)源,將來會將store里面對應的屬性或方法綁定到當前頁面實例上
store,
// 數(shù)據(jù)字段,需要將哪些字段綁定到當前頁面上來進行使用
fields: ['numA', 'numB', 'sum'], // 可以為空數(shù)組,默認
// 方法,需要將哪些方法綁定到當前頁面上來進行使用
actions: ['updateNum1'] // 可以為空數(shù)組,默認
})
},
btnHandler1(e) {
// console.log(e)
// 在事件處理函數(shù)中,調(diào)用從store映射過來的updateNum1()方法
this.updateNum1(e.target.dataset.step)
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面顯示
*/
onShow() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面隱藏
*/
onHide() {
},
/**
* 生命周期函數(shù)--監(jiān)聽頁面卸載
*/
onUnload() {
this.storeBindings.detroyStoreBindings()
},
/**
* 頁面相關(guān)事件處理函數(shù)--監(jiān)聽用戶下拉動作
*/
onPullDownRefresh() {
},
/**
* 頁面上拉觸底事件的處理函數(shù)
*/
onReachBottom() {
},
/**
* 用戶點擊右上角分享
*/
onShareAppMessage() {
}
})
?? 小結(jié)一下
①?能夠知道如何安裝和配置 vant-weapp 組件庫
● 參考 Vant 的官方文檔
②?能夠知道如何使用 MobX 實現(xiàn)全局數(shù)據(jù)共享
● 安裝包、創(chuàng)建 Store、參考官方文檔進行使用
③?能夠知道如何對小程序的 API 進行 Promise 化
● 安裝包、在 app.js 中進行配置
④?能夠知道如何實現(xiàn)自定義 tabBar 的效果
● Vant 組件庫 + 自定義組件 + 全局數(shù)據(jù)共享
【前文回顧】???小程序 - 基礎(chǔ)| 頁面導航、頁面事件、生命周期、WXS腳本_04?文章來源:http://www.zghlxwxcb.cn/news/detail-726840.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-726840.html
到了這里,關(guān)于【小程序 - 加強】自定義組件、使用npm包、全局數(shù)據(jù)共享、分包_05的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!