1. 什么是小程序?
小程序是一種"不需要下載安裝"即可使用的應(yīng)用廓译,它實現(xiàn)了"觸手可及"的夢想评肆。使用起來方便快捷、用完即走
1.1 目前常見的小程序
- 微信小程序
- 支付寶小程序
- 淘寶小程序
- 抖音小程序
- 頭條小程序
- QQ小程序
- 美團小程序
- 等等
1.1.2 為什么各個平臺都需要支持小程序责循?
你有糟港,我也得有
大廠競爭格局中一個重要的一環(huán)。
小程序作為介于頁面和App之間的一項技術(shù)院仿,它有自身很大的優(yōu)勢
體驗比傳統(tǒng)H5頁面要好很多秸抚,相當于傳統(tǒng)的App,使用起來更加方便歹垫,不需要在應(yīng)用商店中下載安裝剥汤,甚至注冊登錄等麻煩操作。
小程序可以間接的動態(tài)為App添加新動態(tài)
傳統(tǒng)的App更新需要打包排惨,上架到應(yīng)用商店后需要通過審核用戶才能進行下載(App Store)吭敢,但是小程序可以在App不更新的情況下,動態(tài)為自己的應(yīng)用添加新的功能要求暮芭。
1.2 小程序由誰開發(fā)鹿驼?
-
小程序的定位
介于原生App和手機H5頁面之間的一個產(chǎn)品定位 -
由此有一個疑問?小程序是由誰來開發(fā)呢辕宏?
小程序開發(fā)工程師畜晰?
由小程序的技術(shù)特點所決定的,比如微信小程序WXML瑞筐、WXSS凄鼻、JavaScript
它更接近于前端的開發(fā)技術(shù)棧,所以小程序是由前端開發(fā)工程師
來開發(fā)的
1.3 小程序的技術(shù)選型
1.3.1 原生小程序開發(fā)
- 微信小程序
WXML聚假、WXSS块蚌、JavaScript - 支付寶小程序
AXML、ACSS膘格、JavaScript
1.3.2 選擇框架開發(fā)小程序
1.3.2.1 較少使用
- mpvue
mpvue是一個支持vue開發(fā)小程序的前端框架峭范,支持微信小程序、百度小程序瘪贱、頭條小程序虎敦、支付寶小程序游岳,框架在2018年之后就不再維護和更新了,目前已經(jīng)被放棄
- wepy
wepy是由騰訊開源的其徙,一款讓小程序支持組件化開發(fā)的框架,通過預編譯的手段讓開發(fā)者可以選擇自己喜歡的開發(fā)風格去開發(fā)小程序喷户,該框架目前維護的也較少唾那,不推薦使用
1.3.2.2 較常使用
- uni-app
由DCloud團隊開發(fā)和維護,uni-app是一個使用vue開發(fā)所有前端應(yīng)用的框架褪尝,開發(fā)者編寫一套代碼闹获,可以發(fā)布到Ios、Android河哑、Web(響應(yīng)式)避诽、以及各種小程序(微信/支付寶/百度/頭條/飛書/QQ/快手/釘釘/淘寶)、快應(yīng)用等多個平臺璃谨,uni-app目前是很多公司的技術(shù)選型沙庐,特別是希望適配移動端App的公司
- taro
由京東團隊開發(fā)和維護,taro是一個
開放式 跨端 跨框架
解決方案佳吞,支持使用React/Vue/Nerv等框架來開發(fā) (微信/京東/百度/支付寶/字節(jié)跳動/QQ/飛書)小程序 /H5/RN 等應(yīng)用拱雏,taro因為本身支持React、Vue的選擇底扳,給了我們更加靈活的選擇空間铸抑,特別是Taro3.x之后,支持Vue3衷模、React Hook 等寫法 - uni- app和taro開發(fā)原生App
- 無論是適配原生小程序還是原生App鹊汛,都有較多的適配問題,所以還是需要多了解原生的一些開發(fā)知識
- 產(chǎn)品使用體驗整體相較于原生App差很多
- 也有其他的技術(shù)選項來開發(fā)原生App
- ReactNative
- Flutter
1.3.3 需要掌握的預備知識
1.3.3.1 核心技術(shù)
頁面布局
: WXML阱冶,類似于HTML
頁面樣式
: WXSS刁憋,幾乎就是CSS(某些樣式屬性不支持,某些進行了增強熙揍,但是基本是一致的)
頁面腳本
: JavaScript+WXS(WeixinScript)
如果之前已經(jīng)掌握了Vue或者React等框架開發(fā)职祷,那么學習小程序是更簡單的
因為里面的核心思想都是一致的 組件化開發(fā)、數(shù)據(jù)響應(yīng)式届囚、mustache語法有梆、事件綁定、等
2. 小程序架構(gòu)和配置
2.1 小程序的架構(gòu)模型
2.1.1 MVVM架構(gòu)
2.1.1.1 Vue的MVVM和小程序MVVM對比
2.1.1.2 MVVM為什么好用呢意系?
- DOM Listeners
ViewModel層可以將DOM的監(jiān)聽綁定到Model層 - Data Bindings
ViewModel層可以將數(shù)據(jù)的變量泥耀,響應(yīng)式的反應(yīng)到View層
MVVM框架將我們從'命令式編程'轉(zhuǎn)移到'聲明式編程'
2.1.2 誰是小程序的宿主環(huán)境呢?
微信客戶端
宿主環(huán)境為了執(zhí)行小程序的各種文件WXML蛔添、WXSS痰催、JS
小程序基于WebView
環(huán)境下時兜辞,WebView的 JS邏輯、DOM樹構(gòu)建夸溶、CSS解析逸吵、樣式計算、Layout缝裁、Paint(Composite) 都發(fā)生在同一線程扫皱,在 WebView 上執(zhí)行過多的Js邏輯可能會阻塞渲染,導致頁面卡頓捷绑,以此為前提下韩脑,小程序同時考慮了性能與安全,來用了目前稱為雙線程模型
的架構(gòu)粹污。
2.1.3 雙線程模型
- WXML模塊和WXSS樣式運行于渲染層段多,渲染層使用WebView線程渲染(一個程序有多個頁面,會使用多個WebView的線程)
- JS腳本(app.js/home.js等) 運行于邏輯層壮吩,邏輯層使用JsCore運行JS腳本
- 這兩個線程都會經(jīng)由微信客戶端(Native)進行中轉(zhuǎn)交互
2.2 小程序的配置文件
小程序很多開發(fā)需求被規(guī)定在了配置文件中
為什么這樣做进苍?
更利于開發(fā)效率
保證開發(fā)出來的小程序某些開發(fā)風格是一致的
比如導航欄-頂部TabBar 頁面路由等
2.2.1 常見的配置文件
project.config.json 項目配置文件,如項目名稱粥航、appid等
sitemap.json 小程序搜索相關(guān)的
app.json 全局配置
常用
- pages 頁面路徑列表
用于指定小程序由哪些頁面組成琅捏,每一項都對應(yīng)一個頁面的路徑(含文件名)信息
小程序中所有的頁面都必須在pages中進行注冊- window 全局的默認窗口展示
用戶指定窗口如何展示,其中還包含了很多其他的屬性- tabBar 頂部tab欄的展示
page.json 頁面配置
每個小程序頁面也可以使用
.json
文件來對本頁面的窗口表現(xiàn)進行配置
頁面中配置項在當前頁面會覆蓋app.json
(全局配置)的window中相同的配置項
2.3 注冊小程序(App函數(shù))
每個小程序都需要在app.js中調(diào)用 App函數(shù) 注冊
在注冊時可以綁定對應(yīng)的生命周期函數(shù)递雀,在生命周期函數(shù)中執(zhí)行對應(yīng)的代碼
2.3.1 注冊App時柄延,一般會做些什么?
- 判斷小程序的進入場景
- 常見的打開場景
- 群聊會話中打開
- 小程序列表打開
- 微信掃一掃打開
- 另一個小程序打開等
- 如何確定場景缀程?
- 在onLaunch和onShow生命周期回調(diào)函數(shù)中搜吧,會有options參數(shù),其中有scene值 鏈接
- 常見的打開場景
- 監(jiān)聽生命周期函數(shù)杨凑,在生命周期中執(zhí)行對應(yīng)的業(yè)務(wù)邏輯滤奈,比如在某個生命周期函數(shù)中進行登錄操作或者請求網(wǎng)絡(luò)數(shù)據(jù)
- 因為App()實例只有一個,并且是全局共享的(單例對象)撩满,所以可以將一些共享的數(shù)據(jù)放在這里
- 在App中定義全局的數(shù)據(jù)
globalData: { userInfo: {name:"藍"} }
- 在其他頁面中訪問
onLoad(options) { const app = getApp() console.log(app.globalData) }
2.3 注冊頁面(Page函數(shù))
小程序中的每個頁面都有一個對應(yīng)的js文件蜒程,其中調(diào)用Page函數(shù)注冊頁面示例
在注冊時,可以綁定初始化數(shù)據(jù)伺帘,生命周期回調(diào)昭躺,事件處理函數(shù)等
2.3.1 注冊一個page頁面時,一般需要做些什么伪嫁?
- 在生命周期函數(shù)中發(fā)送網(wǎng)絡(luò)請求领炫,從服務(wù)器獲取數(shù)據(jù)
- 初始化一些數(shù)據(jù),以方便被wxml引用展示
- 監(jiān)聽wxml中的事件张咳,綁定對應(yīng)的事件函數(shù)
- 其他的一些監(jiān)聽
- 頁面滾動
- 上拉刷新
- 配置當前監(jiān)聽頁面的json文件
"enablePullDownRefresh": true (開啟上拉刷新)
- 在代碼中進行監(jiān)聽
onPullDownRefresh() {}
- 配置當前監(jiān)聽頁面的json文件
- 下拉加載
- 配置當前監(jiān)聽頁面的json文件
"onReachBottomDistance": 0 (距離底部欄多少距離時開啟下拉加載)
- 在代碼中進行監(jiān)聽
onReachBottom() {}
- 配置當前監(jiān)聽頁面的json文件
- 等
2.4 page頁面的生命周期函數(shù)
3. WXSS-WXML-WXS語法
3.1 WXSS
是一套樣式語言,用于描述wxml的組件樣式,wxss用來決定wxml的組件應(yīng)該怎么顯示
3.1.1 小程序樣式的寫法
- 行內(nèi)樣式
- 頁面樣式
- 全局樣式
三種樣式都可以作用于頁面的組件衰腌,如果有相同的樣式,優(yōu)先級的順序是:行內(nèi)樣式>頁面樣式>全局樣式
目前支持的選擇器
wxss優(yōu)先級與css類似
3.1.2 WXSS的擴展
wxss具有css大部分特性砚哗,同時為了更適合開發(fā)微信小程序,wxss對css進行了擴充及修改
3.1.2.1 尺寸單位
rpx(responsive pixel)
可以根據(jù)屏幕寬度進行自適應(yīng)族沃,規(guī)定屏幕寬度為750px
如在iPhone6上频祝,屏幕寬度為375px,共有375個物理像素脆淹,則750rpx = 375px = 750物理像素, 1rpx = 0.5px = 1物理像素沽一。
- 建議
開發(fā)微信小程序時設(shè)計師可以使用iPhone6作為視覺稿的標準 -
注意
在較小的屏幕上不可避免的會有一些毛刺
3.1.2.2 樣式導入
使用@import
語句可以導入外聯(lián)樣式表盖溺,@import
后跟需要導入的外聯(lián)樣式表的相對路徑,用;
表示語句結(jié)束
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
3.2 WXML
3.2.1 WXML基本格式
類似于HTML代碼
比如可以寫成單標簽铣缠,也可以寫成雙標簽
必須有嚴格的閉合
沒有閉合會導致編譯錯誤
大小寫敏感
class和Class時不同的屬性
3.2.2 Mustache語法
開發(fā)中烘嘱,界面上展示的數(shù)據(jù)并不是寫死的,而是會根據(jù)服務(wù)器返回的數(shù)據(jù)蝗蛙,或者用戶的操作來進行改變蝇庭,如果使用原生JS或者Jquery的話,我們需要通過操作DOM來進行頁面的更新捡硅,小程序和Vue一樣哮内,提供了插值語法,Mustache語法(雙大括號)
3.2.3 block標簽
某些情況下壮韭,我們需要使用 wx:if 或 wx:for 時北发,可能需要包裹一組或者多組組件標簽,我們希望對這一組或者多組標簽進行整體操作喷屋,這時就可以使用block標簽琳拨。
- 注意
<block/>并不是一個組件,它僅僅是一個包裝元素屯曹,不會在頁面中做任何渲染狱庇,只接受控制屬性 - 好處
將需要進行遍歷或者判斷的內(nèi)容進行包裹,將遍歷和判斷的屬性放在block標簽中恶耽,不影響普通屬性的閱讀密任,提高代碼的可讀性
3.2.4 邏輯判斷 wx:if - wx:elif - wx:else
有些時候,我們需要根據(jù)條件來決定一些內(nèi)容是否渲染驳棱,當條件為true時批什,view組件會渲染出來,當條件為false時社搅,view組件不會渲染出來
<view>
<block wx:if="{{score>=90}}">
<view>優(yōu)秀</view>
</block>
<block wx:elif="{{score>80}}">
<view>良好</view>
</block>
<block wx:elif="{{score>=60}}">
<view>及格</view>
</block>
<block wx:else>
<view>不及格</view>
</block>
</view>
3.2.5 hidden屬性
hidden是所有組件都默認擁有的屬性
驻债,當hidden屬性為true時乳规,組件會被隱藏,當hidden屬性為false時合呐,組件會顯示出來
<view hidden="{{false}}">hi hi</view>
3.2.6 hidden和wx:if的區(qū)別
- hidden 控制組件的隱藏和顯示暮的,無論條件組件始終都會被渲染
- wx:if 控制組件是否渲染,wx:if 是惰性的淌实,如果在初始渲染條件為false是冻辩,該組件不會進行任何處理
- 一般來說 wx:if 有更高的切換消耗 而 hidden 有更高的初始渲染消耗,
如果需要頻繁切換拆祈,使用hidden恨闪。如果在運行時條件不大可能改變則使用wx:if
3.2.7 列表渲染
3.2.7.1 wx:for
為什么使用wx:for?
在實際開發(fā)中放坏,服務(wù)器經(jīng)常返回各種列表數(shù)據(jù)咙咽,我們不可能一一從列表中取出數(shù)據(jù)進行展示,需要通過for循環(huán)的方式來遍歷所有的數(shù)據(jù)淤年,一次性的進行展示
在組件中钧敞,我們可以使用wx:for來遍歷數(shù)組(字符串、數(shù)字)麸粮,默認情況下遍歷后wxml中可以使用一個變量index
溉苛,保存的是當前遍歷數(shù)據(jù)的下標值,數(shù)據(jù)中對應(yīng)的某項的數(shù)據(jù)弄诲,使用變量名item獲取
<block>
<!-- 遍歷一個數(shù)組 -->
<view wx:for="{{['abc','aaa','ccc']}}">{{item}}</view>
<!-- 遍歷一個字符串 -->
<view wx:for="{{'hello 你好'}}">{{item}}</view>
<!-- 遍歷一個數(shù)字 -->
<view wx:for="{{5}}">{{item}}</view>
</block>
3.2.7.2 item/index名稱
默認情況下愚战,item/index的名字是固定的
但是某些情況下我們可能想使用其他名稱,或者當出現(xiàn)多層變量時威根,名字會重復
使用wx:for-item
和wx:for-index
修改數(shù)組當前元素和下標的變量名
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>
3.2.7.3 wx:key的值以兩種形式提供
-
字符串
凤巨,代表在for循環(huán)的array中item的某個property,該property的值需要是列表中唯一的字符串或者數(shù)字洛搀,且不能動態(tài)改變 - 保留關(guān)鍵字
*this
敢茁,代表在for循環(huán)中的item本身,這種表示需要item本身是一個唯一的字符串或者數(shù)字
3.2 WXS
3.2.1 什么是WXS留美?
3.2.1.1 WXS(WeiXin Script) 是小程序的一套腳本語言彰檬,結(jié)合 WXML,可以構(gòu)建出頁面的結(jié)構(gòu)谎砾。
官方:WXS 與 JavaScript 是不同的語言逢倍,有自己的語言,并不和 JavaScript 一致景图。(不過基本一致)
WXS中目前只能使用ES5较雕,ES6的使用會報錯
3.2.2 為什么要設(shè)計WXS語言?
3.2.2.1 在WXML中是不能直接調(diào)用Page
/Component
中定義函數(shù)的; (雙線程模式)
<!-- 在vue中可以直接調(diào)用函數(shù) 但是在小程序中這樣調(diào)用是沒用的(以前這樣調(diào)用會報錯,現(xiàn)在不會報錯但是沒有任何結(jié)果顯示) -->
<view>結(jié)果:{{formatCount(value)}}</view>
但是某些情況下亮蒋,我們希望使用函數(shù)來處理WXML中WXML中的數(shù)據(jù)(類似于Vue中的過濾器)扣典,這個時候就可以使用WXS了
3.2.3 WXS使用的限制和特點:
- WXS 不依賴于運行時的基礎(chǔ)庫版本,可以在所有版本的小程序中運行慎玖;
- WXS 的運行環(huán)境和其他 JavaScript 代碼是隔離的贮尖,WXS中不能調(diào)用其他JavaScript文件中定義的函數(shù),也不能調(diào)用小程序提供的API趁怔;
- 由于運行環(huán)境的差異湿硝,在IOS設(shè)備上小程序內(nèi)的WXS會比JavaScript代碼快 2~20 倍,在android設(shè)備上二者運行效率無差異润努;
3.2.4 WXS的寫法
3.2.4.1 WXS有兩種寫法:
- 寫在<wxs>標簽中
- 寫在以.wxs結(jié)尾的文件中
3.2.4.2 <wxs>標簽的屬性:
屬性名 | 類型 | 說明 |
---|---|---|
module | String | 當前<wxs> 標簽的模塊名关斜。必填字段。 |
src | String | 引用.wxs 文件的相對路徑铺浇。僅當本標簽為單閉合標簽或標簽內(nèi)容為空時有效蚤吹。 |
3.2.5 每一個.wxs文件和 <wxs> 標簽都是一個單獨的模塊。(一個wxml文件中可以引入多個wxs"module不能重復")
- 每個模塊都有自己獨立的作用域随抠。即在一個模塊里面定義的變量與函數(shù),默認為私有的繁涂,對其他模塊不可見拱她;
- 一個模塊想要對外暴露起內(nèi)部的私有變量,只能通過
module.exports
實現(xiàn)扔罪;
3.2.6 WXS簡單案例
傳入一個數(shù)字(整數(shù)或小數(shù))秉沼,格式化后進行展示(例如36456,展示結(jié)果3.6萬)
-
傳入一個時間(秒)矿酵,格式化后進行展示(例如100秒唬复,展示結(jié)果為01:40)
wxml
<wxs module="format" src="/utils/format.wxs"></wxs>
<block>
<view>傳入一個數(shù)字(整數(shù)或小數(shù)),格式化后進行展示(例如36456全肮,展示結(jié)果3.6萬)</view>
<view>結(jié)果:{{format.formatCount(value)}}</view>
<input type="number" model:value="{{value}}" class="my-input" />
</block>
<block>
<view>傳入一個時間(秒)敞咧,格式化后進行展示(例如100秒,展示結(jié)果為01:40)</view>
<view>結(jié)果:{{format.formatDuration(value1)}}</view>
<input type="number" model:value="{{value1}}" class="my-input" />
</block>
- wxs
function formatCount(count) {
var patrn = getRegExp('(^[0-9]*\.([0-9]{1}\d*)$)|(^[0-9]*$)')
if (!patrn.test(count)) return count ? "格式錯誤" : "";
var count = +count;
if (count > 100000000) {
return (count / 100000000).toFixed(1) + "億"
} else if (count > 10000) {
return (count / 10000).toFixed(1) + "萬"
}
return count
}
function disposeTime(time) {
return time < 10 ? "0" + time : time
}
function formatDuration(duration) {
var patrn = getRegExp('(^[0-9]*$)');
if (!patrn.test(duration)) return "格式錯誤";
var isHours = duration >= 3600;
if (isHours) {
var hours = disposeTime(Math.floor(duration / 3600));
duration = duration - hours * 3600;
}
var minutes = disposeTime(Math.floor(duration / 60));
var seconds = disposeTime(duration % 60);
return (isHours ? (hours + ":") : "") + minutes + ":" + seconds;
}
module.exports = {
formatCount: formatCount,
formatDuration: formatDuration
}
3.2.7 WXS中使用正則表達式
直接使用會報錯 var patrn = /'(^[0-9]*$)'/;
要使用getRegExp函數(shù)
var patrn = getRegExp('(^[0-9]*$)');
- 注意 使用getRegExp時里面不要帶
/
9枷佟P萁ā!评疗! - 錯誤
getRegExp('/(^[0-9]*$)/');
- 正確
getRegExp('(^[0-9]*$)');
4. 事件處理
4.1 什么時候會產(chǎn)生事件测砂?
小程序需要經(jīng)常和用戶進行某種交互,比如點擊界面上的某個按鈕或者區(qū)域百匆,比如滑動了某個區(qū)域 等
4.2 什么是事件砌些?
事件是視圖層到邏輯層的通訊方式
事件可以將用戶的行為反饋到邏輯層進行處理
事件可以綁定在組件上,當觸發(fā)事件時加匈,就會執(zhí)行邏輯層中對應(yīng)的事件處理函數(shù)
事件對象可以攜帶額外信息存璃,如id仑荐、dataset、touches等
4.3 事件是如何處理的有巧?
- 事件通過
bind
/catch
這個屬性綁定在組建上的(和普通的屬性寫法很相似释漆,以key="value"形式) - key以bind或catch開頭,從
1.5.0
版本開始篮迎,可以在bind和catch后加一個冒號 - 同時在當前頁面的Page構(gòu)造器中定義對應(yīng)的事件處理函數(shù)男图,如果沒有對應(yīng)的函數(shù),觸發(fā)事件時會報錯
- 比如當用戶點擊該button區(qū)域時甜橱,達到觸發(fā)條件生成事件tap逊笆,該事件處理函數(shù)會被執(zhí)行,同時還會收到一個事件對象
event
- 比如當用戶點擊該button區(qū)域時甜橱,達到觸發(fā)條件生成事件tap逊笆,該事件處理函數(shù)會被執(zhí)行,同時還會收到一個事件對象
4.4 事件對象event
當某個事件觸發(fā)時岂傲,會產(chǎn)生一個事件對象难裆,并且這個對象被傳入到回調(diào)函數(shù)中
4.4.1 BaseEvent基礎(chǔ)事件對象屬性列表
4.5 current Target和target的區(qū)別
-
currentTarget
事件處理程序注冊的元素 -
target
事件觸發(fā)實際目標元素
4.6 touches和changedTouches的區(qū)別
- 在touched中不同
- 多手指觸摸時不同
4.7 事件參數(shù)傳遞
4.7.1 dataset
當視圖層發(fā)生事件時,某些情況需要事件攜帶一些參數(shù)到執(zhí)行的函數(shù)中镊掖,這個時候就可以通過data-屬性來完成
- 格式
data-屬性的名稱
- 獲取
e.currentTarget.dataset.屬性的名稱
4.7.2 mark
版本2.7.1以上才可以使用
使用mark來識別具體觸發(fā)事件的target節(jié)點乃戈,還可以用于承載一些自定義數(shù)據(jù)
當事件觸發(fā)時,事件冒泡路徑上所有的mark會被合并亩进,并返回給事件回調(diào)函數(shù)
即使事件不是冒泡事件症虑,也會mark
如何存在同名的mark,父節(jié)點的mark會被子節(jié)點的覆蓋
在自定義組件中接收事件時归薛,mark不包含自定義組件外的節(jié)點的mark
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按鈕</button>
</view>
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
4.7.3 dataset和mark的區(qū)別
- mark會包含從觸發(fā)事件的節(jié)點到根節(jié)點上的所有的mark屬性值
- dataset僅包含一個節(jié)點的data-屬性值
- dataset的值會做大小寫的轉(zhuǎn)換谍憔,mark不會做大小寫的轉(zhuǎn)換
4.8 事件冒泡和事件捕獲
當界面產(chǎn)生了一個事件時,事件分為了捕獲階段和冒泡階段
5. 組件化開發(fā)
1.6.3版本后小程序才開始支持自定義組件的開發(fā)
5.1 組件化思想的應(yīng)用
- 盡可能的將頁面拆分成一個個小的主籍、可復用的組件
- 讓代碼更加方便組織和管理习贫,并且擴展性也更強
5.2 創(chuàng)建一個組件
類似于頁面,自定義組件由
json wxml wxss js
四個文件組成
首先先在根目錄下創(chuàng)建一個文件夾components
千元,在里面存放后續(xù)新建的自定義組件
-
自定義組件的步驟
- 首先需要先在創(chuàng)建的自定義組件的json文件中進行自定義組件的聲明(將component字段設(shè)置為true)
- 在wxml中編寫組件自己的模版
- 在wxss中編寫組件自己的相關(guān)樣式
- 在js文件中可以定義數(shù)據(jù)或組件內(nèi)部的相關(guān)邏輯
5.3 使用自定義組件和細節(jié)注意事項
自定義組件也是可以引用自定義組件的苫昌,引用方法類似于頁面引用自定義組件的方法(使用usingComponents字段)
自定義組件和頁面所在項目根目錄名不能以"wx-"為前綴,否則會報錯
如果在app.json和usingComponents聲明某個組件诅炉,那么所有頁面和組件都可以直接使用該組件
5.4 組件的樣式細節(jié)
5.4.1 組件內(nèi)的樣式 對 外部樣式 的影響
- 組件內(nèi)的class樣式蜡歹,只對組件wxml內(nèi)的節(jié)點生效,對引用組件的Page頁面不生效
- 組件內(nèi)不能使用id選擇器涕烧、屬性選擇器月而、標簽選擇器
5.4.2 外部樣式 對 組件內(nèi)的樣式 的影響
- 外部使用class的樣式,只對外部wxml的class生效议纯,對組件內(nèi)是不生效的
- 外部使用了id選擇器父款、屬性選擇器不會對組件內(nèi)產(chǎn)生影響
- 外部使用了標簽選擇器,會對組件內(nèi)產(chǎn)生影響
5.4.3 如何讓class可以相互影響
- 在Component中,可以傳入一個options屬性憨攒,其中options屬性中有一個styleIsolation(隔離)屬性
- styleIsolation常用的三個值
-
isolated
表示啟動樣式隔離世杀,在自定義組件內(nèi)外,使用class指定的樣式將不會互相影響 -
apply-shared
表示頁面wxss樣式將影響到自定義組件肝集,但自定義組件wxss中指定的樣式不會影響頁面 -
shared
表示頁面wxss樣式將影響到自定義組件瞻坝,自定義組件wxss中指定的樣式也會影響頁面和其他設(shè)置
-
5.5 組件的通訊
很多情況下,組件內(nèi)展示的內(nèi)容(數(shù)據(jù)杏瞻、樣式所刀、標簽)并不是在組件內(nèi)寫死的,而是可以由使用者來決定的
5.5.1 向組件傳遞數(shù)據(jù) - properties
給組件傳遞數(shù)據(jù)
大部分情況下捞挥,組件只負責布局和樣式浮创,內(nèi)容是由使用組件的對象決定的,所以經(jīng)常需要從外部傳遞數(shù)據(jù)給我們的組件砌函,讓我們的組件來進行展示
5.5.1.1 如何傳遞斩披?
使用properties屬性
- 支持的類型
String、Number讹俊、Boolean垦沉、Object、Array仍劈、null(不限制類型)
- 默認值
可以通過value設(shè)置默認值
5.5.2 向組件傳遞樣式 - externalClasses
有時候我們不希望將樣式在組件內(nèi)固定不變乡话,而是外部可以決定樣式
使用externalClasses屬性
- 在Component對象中定義externalClasses屬性
- 在組件那的wxml中使用externalClasses屬性中的class
- 在頁面中傳入對應(yīng)的class,并且給這個class設(shè)置樣式
5.5.3 組件向外傳遞事件 - 自定義事件
有時候自定義組件內(nèi)部發(fā)生了事件耳奕,需要告知使用者,這個時候就可以使用自定義事件
5.5.4 頁面直接調(diào)用組件方法
在父組件里調(diào)用 this.selectComponent诬像,獲取子組件的實例對象
調(diào)用時需要傳入一個匹配選擇器selector 如:this.selectComponent(".tabs")
5.6 插槽slot
5.6.1 現(xiàn)實生活中什么是插槽屋群?
- 在生活中很多地方都有插槽,電腦的USB插槽坏挠,插板當中的電源插槽
- 插槽的目的是讓我們原來的設(shè)備具備更多的擴展性
- 比如電腦的USB我們可以插入U盤芍躏、硬盤、手機降狠、音箱对竣、鍵盤、鼠標等
5.6.2 組件的插槽
組件的插槽是為了讓我們封裝的組件更加具有擴展性榜配,讓使用者可以決定組件內(nèi)部的一些內(nèi)容到底展示什么
例子
移動開發(fā)中否纬,幾乎每個頁面都有導航欄
導航欄必然會封裝成一個插槽,比如nav-bar組件
一旦有了這個組件蛋褥,我們就可以在多個頁面中進行復用了
但是我們并不能確保每個頁面中的導航欄是一模一樣的临燃,整體樣式架構(gòu)是一樣的可能里面的內(nèi)容不一樣,這個時候就可以使用插槽
5.6.3 單個插槽的使用
除了內(nèi)容和樣式可能由外界決定之外,也可能外界想決定顯示的方式膜廊,比如我們有一個組件定義了頭部和尾部乏沸,但是中間的內(nèi)容可能是一段文字、圖片或者進度條爪瓜,在不確定外界想插入什么其他組件的前提下蹬跃,我們可以在組件內(nèi)預留插槽
5.6.4 多個插槽的使用
有時候為了讓組件更加靈活,我們需要定義多個插槽
5.6.5 slot插槽使用默認值方案
前提:
在很多場景下我們希望自定義組件有較好的擴展性
铆铆,在不傳入slot的情況下默認展示默認的結(jié)構(gòu)與樣式蝶缀,但小程序中的slot沒有像vue中的slot一樣提供默認值,這時候我們可以通過偽類選擇器
:empty 和相鄰選擇器
+控制元素的display
來實現(xiàn)
- 使用自定義組件
<view>
<slot-item>
<button>我是一個按鈕</button>
</slot-item>
<slot-item></slot-item>
<slot-item>
<text style="color: red;">我是一個文本</text>
</slot-item>
</view>
- 實現(xiàn)自定義組件
wxml
<view class="container">
<view>我是header</view>
<view class="content">
<slot></slot>
</view>
<!-- 插槽默認值 -->
<view class="default">我是slot默認值</view>
<view>我是footer</view>
</view>
wxss
.default {
width: 200rpx;
height: 200rpx;
background-color: #f99;
text-align: center;
line-height: 200rpx;
margin: 0 auto;
/* 默認值默認不顯示 */
display: none;
}
/* 當插槽內(nèi)為空時 通過相鄰選擇器將默認值顯示 */
.content:empty+.default {
display: block;
}
5.7 behaviors
behaviors用于組件間代碼共享的特性算灸,類似于一些編輯語言中的"mixins"
- 每個behaviors可以包含一組屬性扼劈、數(shù)據(jù)、生命周期和方法
- 組件應(yīng)用它時菲驴,它的屬性荐吵、數(shù)據(jù)和方法會被合并到組件中,生命周期也會在對應(yīng)時機被調(diào)用
- 每個組件引用多個behavior赊瞬,behavior也可以引用其它behavior
5.8 組件的生命周期
指的是組件自身的一些函數(shù)先煎,這些函數(shù)在特殊的時間點或遇到一些特殊的框架事件時被觸發(fā),最重要的生命周期是 created巧涧、attached薯蝎、detached,包含了一個組件實例生命流程的最主要的時間點
2.2.3起谤绳,組件的生命周期也可以在lifetimes字段內(nèi)進行聲明占锯,推薦使用這個方式聲明,其優(yōu)先級最高
Component({
lifetimes: {
attached: function() {
// 在組件實例進入頁面節(jié)點樹時執(zhí)行
},
detached: function() {
// 在組件實例被從頁面節(jié)點樹移除時執(zhí)行
},
},
// 以下是舊式的定義方式缩筛,可以保持對 <2.2.3 版本基礎(chǔ)庫的兼容
attached: function() {
// 在組件實例進入頁面節(jié)點樹時執(zhí)行
},
detached: function() {
// 在組件實例被從頁面節(jié)點樹移除時執(zhí)行
},
// ...
})
5.9 組件所在頁面的生命周期
還有一些特殊的生命周期消略,它們并非與組件有很強的關(guān)聯(lián),但有時組件需要獲知瞎抛,以便組件內(nèi)部處理艺演,這樣的生命周期稱為"組件所在頁面的生命周期",在pageLifetimes定義段中定義
Component({
pageLifetimes: {
show: function() {
// 頁面被展示
},
hide: function() {
// 頁面被隱藏
},
resize: function(size) {
// 頁面尺寸變化
}
}
})
5.10 Component構(gòu)造器
-
properties
定義傳入的屬性
-
data
定義內(nèi)部屬性
-
methods
定義方法
-
options
額外配置選項
-
externalClasses
引用外部樣式
-
observers
屬性和數(shù)據(jù)監(jiān)聽
-
pageLifetimes
頁面生命周期
-
lifetimes
組件生命周期
6. 系統(tǒng)API調(diào)用
持續(xù)更新...