微信小程序中的behaviors
概括
一句話總結: behaviors是用于組件間代碼共享的特性, 類似一些編程語言中的'mixin'或者'traits'.
A.每個behaviors包含一組屬性、數(shù)據(jù)、生命周期函數(shù)、自定義方法 -> 組件引用它時, 屬性、數(shù)據(jù)、生命周期函數(shù)、自定義方法都會被合并到組件中,生命周期函數(shù)也會在對應的時機被調用.
B. 每個組件可以引用多個behavior, behavior也可引用其它behavior;
Demo演示
下文主要貼出了主要代碼, 可自行拷貝運行.
頁面級wxml
// 新建page, 頁面級wxml
<test-comp></test-comp>
// 頁面級json
{
"usingComponents": {
"test-comp": "../components/testComp/testComp"
}
}組件級wxml
// 新建個組件, 組件級wxml
<view>屬性: {{myBehaviorProperty}} --- {{myCompProperty}}</view>
<view>數(shù)據(jù): {{myBehaviorData}} --- {{myCompData}}</view>
<view bind:tap="myBehaviorMethod">觸發(fā)behavior的自定義方法</view>
<view bind:tap="myCompMethod">觸發(fā)組件的自定義方法</view>
// 組件級js
import testBehavior from './testBehavior'
Component({
behaviors: [testBehavior],
properties: {
myCompProperty: {
type: String,
value: ''
}
},
data: {
myCompData: 'myCompData'
},
created: function (){
console.log('[my-component]- created')
},
attached: function (){
console.log('[my-component]- attached')
},
ready: function (){
console.log('[my-component]- ready')
},
methods: {
myCompMethod: function () {
console.log('[my-component]- method')
}
}
})behavior級
// behavior級
export default Behavior({
behaviors: [],
properties: {
myBehaviorProperty: {
type: String,
value: 'myBehaviorProperty'
}
},
data: {
myBehaviorData: 'myBehaviorData'
},
created: function () {
console.log('[my-behavior]- created')
},
attached: function () {
console.log('[my-behavior]- attached')
},
ready: function () {
console.log('[my-behavior]- ready')
},
methods: {
myBehaviorMethod: function () {
console.log('[my-behavior]- method')
}
}
})先來對上述代碼做一波解析:
behavior結構:
屬性: myBehaviorProperty
數(shù)據(jù): myBehaviorData
生命周期: created() && attached() && ready()
自定義方法: myBehaviorMethod
組件引入該behaviors后的結構:
屬性: myBehaviorProperty、 myCompProperty
數(shù)據(jù): myBehaviorData、myCompData
生命周期: created() && attached() && ready()
自定義方法: myBehaviorMethod、myCompMethod
緊接著, 來看看代碼運行結果: 也許你會對輸出有疑問, 先不著急, 慢慢往下看.

進階演示
上面的Demo僅演示了最基礎的behaviors的用法, 接下來我們看看遇到同名的屬性or數(shù)據(jù)or生命周期方法or自定義方法, 該屬性會做些什么呢?
1. 若具有同名的屬性或方法
A. 若組件本身有, 則組件會覆蓋behavior;
B. 若存在嵌套子behaviors的情況, 則父behavior會覆蓋子behavior;
Demo演示: 基于上面的Demo代碼, 追加如下部分
// 新建個組件, 組件級wxml
<view bind:tap="sameMethod">同名屬性: {{sameProperty}}</view>
// 組件級js
properties: {
sameProperty: {
type: String,
value: 'sameProperty-myCompProperty'
}
},
methods: {
sameMethod: function (){
console.log('[my-component]- sameMethod')
}
}
// behavior級
properties: {
sameProperty: {
type: String,
value: 'sameProperty-myBehaviorProperty'
}
},
methods: {
sameMethod: function (){
console.log('[my-behavior]- sameMethod')
}
}上述代碼表現(xiàn)形式如下: 組件的同名屬性覆蓋了behavior的同名屬性; 點擊自定義方法, 觸發(fā)的是組件的自定義方法.

至此, 你會不會好奇如果屬性是個object, 是怎么個表現(xiàn)形式呢, 接下來看看實際效果.
// 新建個組件, 組件級wxml
<view>同名屬性: {{sameProperty && sameProperty.val1}}</view>
<view>同名屬性: {{sameProperty && sameProperty.val2}}</view>
// 組件級js
properties: {
sameProperty: {
type: Object,
value: {
val1: '[my-component]-同名屬性類型是對象'
}
}
}
// behavior級
properties: {
sameProperty: {
type: Object,
value: {
val1: '[my-behavior]-同名屬性類型是對象',
val2: '[my-behavior]-體現(xiàn)同名對象類型不會做合并'
}
}
}上述代碼表現(xiàn)形式如下: 同名屬性即使是對象類型, 也只會做覆蓋,
區(qū)別于下文的同名數(shù)據(jù)的合并操作哦.

2. 若有同名的數(shù)據(jù)
A. 若數(shù)據(jù)類型是對象, 進行對象合并;
B. 其它類型會進行數(shù)據(jù)覆蓋, 覆蓋原則:組件 > 父behavior > 子behavior; 靠后的behavior > 靠前的behavior;
Demo演示: 針對數(shù)據(jù)是對象&非對象
// 組件級js
data: {
sameObj: {
val1: '[my-component]-同名數(shù)據(jù)類型是對象'
},
sameData: false
},
ready: function (){
console.log('[my-component]- ready')
console.log('[my-behavior]- 同名數(shù)據(jù)', this.data.sameObj, this.data.sameData)
},
// behavior級
data: {
sameObj: {
val1: '[my-behavior]-同名數(shù)據(jù)類型是對象',
val2: '[my-behavior]-體現(xiàn)同名數(shù)據(jù)類型做合并'
},
sameData: true
},上述代碼表現(xiàn)形式如下: 同名數(shù)據(jù)對象做合并, 同名數(shù)據(jù)非對象做覆蓋.

3. 若有同名的生命周期函數(shù)
不會被覆蓋、而是在對應的觸發(fā)時機內逐個調用:
A. 不同的生命周期之間, 遵循組件生命周期的執(zhí)行順序;
B. 同種生命周期函數(shù):
①. behavior優(yōu)先于組件執(zhí)行;
②. 子behavior優(yōu)先于父behavior執(zhí)行;
③. 靠前的behavior優(yōu)先于靠后的behavior執(zhí)行;
C. 如果同一個 behavior 被一個組件多次引用,它定義的生命周期函數(shù)只會被執(zhí)行一次;
應用場景
相信到了這里, 你應該明白了Demo演示中控制臺的輸出是基于什么來輸出的, 接下來我們看看什么樣的應用場景會考慮使用該屬性呢?
如下圖, 有個中間彈窗組件&&底部彈窗組件, 均內聚有如下功能點:
A. 觸發(fā)某一條件后, 出現(xiàn)該彈窗;
B. 點擊遮罩層, 關閉彈窗;

考慮下如果將彈窗顯示跟隱藏的邏輯放在behaviors里面, 是否能避免同份代碼邏輯寫2遍的問題呢.
Page中不能使用behaviors、只能在Components中使用!!!!!! 故若遇到真想使用behaviors屬性的頁面, 試試把某塊頁面內容抽離成組件, 然后引用組件的方式去實現(xiàn).
最后
behaviors 是用于組件間代碼共享的特性,類似于一些編程語言中的 “mixins” 或 “traits”。
每個 behavior 可以包含一組屬性、數(shù)據(jù)、生命周期函數(shù)和方法。組件引用它時,它的屬性、數(shù)據(jù)和方法會被合并到組件中,生命周期函數(shù)也會在對應時機被調用。 每個組件可以引用多個 behavior ,behavior 也可以引用其它 behavior 。
屬性&方法
注冊一個 behavior,接受一個 Object 類型的參數(shù)。
| 定義段 | 類型 | 是否必填 | 描述 | 最低版本 |
|---|---|---|---|---|
| properties | Object Map | 否 | 組件的對外屬性,是屬性名到屬性設置的映射表 | |
| data | Object | 否 | 組件的內部數(shù)據(jù),和 properties 一同用于組件的模板渲染 | |
| observers | Object | 否 | 組件數(shù)據(jù)字段監(jiān)聽器,用于監(jiān)聽 properties 和 data 的變化,參見 數(shù)據(jù)監(jiān)聽器 | 2.6.1 |
| methods | Object | 否 | 組件的方法,包括事件響應函數(shù)和任意的自定義方法,關于事件響應函數(shù)的使用,參見 組件間通信與事件 | |
| behaviors | String Array | 否 | 類似于mixins和traits的組件間代碼復用機制,參見 behaviors | |
| created | Function | 否 | 組件生命周期函數(shù)-在組件實例剛剛被創(chuàng)建時執(zhí)行,注意此時不能調用 setData ) | |
| attached | Function | 否 | 組件生命周期函數(shù)-在組件實例進入頁面節(jié)點樹時執(zhí)行) | |
| ready | Function | 否 | 組件生命周期函數(shù)-在組件布局完成后執(zhí)行) | |
| moved | Function | 否 | 組件生命周期函數(shù)-在組件實例被移動到節(jié)點樹另一個位置時執(zhí)行) | |
| detached | Function | 否 | 組件生命周期函數(shù)-在組件實例被從頁面節(jié)點樹移除時執(zhí)行) | |
| relations | Object | 否 | 組件間關系定義,參見 組件間關系 | |
| lifetimes | Object | 否 | 組件生命周期聲明對象,參見 組件生命周期 | 2.2.3 |
| pageLifetimes | Object | 否 | 組件所在頁面的生命周期聲明對象,參見 組件生命周期 | 2.2.3 |
| definitionFilter | Function | 否 | 定義段過濾器,用于自定義組件擴展,參見 自定義組件擴展 | 2.2.3 |
組件中使用
組件引用時,在 behaviors 定義段中將它們逐個列出即可。
代碼示例:
// my-component.js
var myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior],
properties: {
myProperty: {
type: String
}
},
data: {
myData: 'my-component-data'
},
created: function () {
console.log('[my-component] created')
},
attached: function () {
console.log('[my-component] attached')
},
ready: function () {
console.log('[my-component] ready')
},
methods: {
myMethod: function () {
console.log('[my-component] log by myMethod')
},
}
})在上例中, my-component 組件定義中加入了 my-behavior,
而 my-behavior 結構為:
- 屬性:
myBehaviorProperty - 數(shù)據(jù)字段:
myBehaviorData - 方法:
myBehaviorMethod - 生命周期函數(shù):
attached、created、ready
這將使 my-component 最終結構為:
- 屬性:
myBehaviorProperty、myProperty - 數(shù)據(jù)字段:
myBehaviorData、myData - 方法:
myBehaviorMethod、myMethod - 生命周期函數(shù):
attached、created、ready
當組件觸發(fā)生命周期時,上例生命周期函數(shù)執(zhí)行順序為:
[my-behavior] created[my-component] created[my-behavior] attached[my-component] attached[my-behavior] ready[my-component] ready
詳細規(guī)則參考 同名字段的覆蓋和組合規(guī)則。
同名字段的覆蓋和組合規(guī)則
組件和它引用的 behavior 中可以包含同名的字段,對這些字段的處理方法如下:
- 如果有同名的屬性 (properties) 或方法 (methods):
- 若組件本身有這個屬性或方法,則組件的屬性或方法會覆蓋 behavior 中的同名屬性或方法;
- 若組件本身無這個屬性或方法,則在組件的 behaviors 字段中定義靠后的 behavior 的屬性或方法會覆蓋靠前的同名屬性或方法;
- 在 2 的基礎上,若存在嵌套引用 behavior 的情況,則規(guī)則為:引用者 behavior 覆蓋 被引用的 behavior 中的同名屬性或方法。
- 如果有同名的數(shù)據(jù)字段 (data):
- 若同名的數(shù)據(jù)字段都是對象類型,會進行對象合并;
- 其余情況會進行數(shù)據(jù)覆蓋,覆蓋規(guī)則為: 引用者 behavior > 被引用的 behavior 、 靠后的 behavior > 靠前的 behavior。(優(yōu)先級高的覆蓋優(yōu)先級低的,最大的為優(yōu)先級最高)
- 生命周期函數(shù)和 observers 不會相互覆蓋,而是在對應觸發(fā)時機被逐個調用:
- 對于不同的生命周期函數(shù)之間,遵循組件生命周期函數(shù)的執(zhí)行順序;
- 對于同種生命周期函數(shù)和同字段 observers ,遵循如下規(guī)則:
- behavior 優(yōu)先于組件執(zhí)行;
- 被引用的 behavior 優(yōu)先于 引用者 behavior 執(zhí)行;
- 靠前的 behavior 優(yōu)先于 靠后的 behavior 執(zhí)行;
- 如果同一個 behavior 被一個組件多次引用,它定義的生命周期函數(shù)和 observers 不會重復執(zhí)行。
到此這篇關于微信小程序之behaviors的文章就介紹到這了,更多相關微信小程序behaviors內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
pnpm install:ERR_PNPM_PEER_DEP_ISSUES Unmet p
這篇文章主要為大家介紹了pnpm install:ERR_PNPM_PEER_DEP_ISSUES Unmet peer dependencies報錯解決2023-06-06
JavaScript前端實現(xiàn)GIF圖片循環(huán)播放
使用 img 加載 GIF 圖片,內容只會播放一次,之后就會自動暫停,所以這篇文章為大家介紹了如何使用JavaScript實現(xiàn)GIF圖片循環(huán)播放吧2025-03-03
通過JS動態(tài)創(chuàng)建一個html DOM元素并顯示
需要通過點擊某個元素后, 動態(tài)創(chuàng)建一個DOM元素并顯示,因此寫了一些相關的js函數(shù),在此記錄下2014-10-10

