微信小程序中的behaviors
概括
一句話總結(jié): behaviors是用于組件間代碼共享的特性, 類似一些編程語(yǔ)言中的'mixin'或者'traits'.
A.每個(gè)behaviors包含一組屬性、數(shù)據(jù)、生命周期函數(shù)、自定義方法 -> 組件引用它時(shí), 屬性、數(shù)據(jù)、生命周期函數(shù)、自定義方法都會(huì)被合并到組件中,生命周期函數(shù)也會(huì)在對(duì)應(yīng)的時(shí)機(jī)被調(diào)用.
B. 每個(gè)組件可以引用多個(gè)behavior, behavior也可引用其它behavior;
Demo演示
下文主要貼出了主要代碼, 可自行拷貝運(yùn)行.
頁(yè)面級(jí)wxml
// 新建page, 頁(yè)面級(jí)wxml
<test-comp></test-comp>
// 頁(yè)面級(jí)json
{
"usingComponents": {
"test-comp": "../components/testComp/testComp"
}
}組件級(jí)wxml
// 新建個(gè)組件, 組件級(jí)wxml
<view>屬性: {{myBehaviorProperty}} --- {{myCompProperty}}</view>
<view>數(shù)據(jù): {{myBehaviorData}} --- {{myCompData}}</view>
<view bind:tap="myBehaviorMethod">觸發(fā)behavior的自定義方法</view>
<view bind:tap="myCompMethod">觸發(fā)組件的自定義方法</view>
// 組件級(jí)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級(jí)
// behavior級(jí)
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')
}
}
})先來(lái)對(duì)上述代碼做一波解析:
behavior結(jié)構(gòu):
屬性: myBehaviorProperty
數(shù)據(jù): myBehaviorData
生命周期: created() && attached() && ready()
自定義方法: myBehaviorMethod
組件引入該behaviors后的結(jié)構(gòu):
屬性: myBehaviorProperty、 myCompProperty
數(shù)據(jù): myBehaviorData、myCompData
生命周期: created() && attached() && ready()
自定義方法: myBehaviorMethod、myCompMethod
緊接著, 來(lái)看看代碼運(yùn)行結(jié)果: 也許你會(huì)對(duì)輸出有疑問(wèn), 先不著急, 慢慢往下看.

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

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

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

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

考慮下如果將彈窗顯示跟隱藏的邏輯放在behaviors里面, 是否能避免同份代碼邏輯寫(xiě)2遍的問(wèn)題呢.
Page中不能使用behaviors、只能在Components中使用!!!!!! 故若遇到真想使用behaviors屬性的頁(yè)面, 試試把某塊頁(yè)面內(nèi)容抽離成組件, 然后引用組件的方式去實(shí)現(xiàn).
最后
behaviors 是用于組件間代碼共享的特性,類似于一些編程語(yǔ)言中的 “mixins” 或 “traits”。
每個(gè) behavior 可以包含一組屬性、數(shù)據(jù)、生命周期函數(shù)和方法。組件引用它時(shí),它的屬性、數(shù)據(jù)和方法會(huì)被合并到組件中,生命周期函數(shù)也會(huì)在對(duì)應(yīng)時(shí)機(jī)被調(diào)用。 每個(gè)組件可以引用多個(gè) behavior ,behavior 也可以引用其它 behavior 。
屬性&方法
注冊(cè)一個(gè) behavior,接受一個(gè) Object 類型的參數(shù)。
| 定義段 | 類型 | 是否必填 | 描述 | 最低版本 |
|---|---|---|---|---|
| properties | Object Map | 否 | 組件的對(duì)外屬性,是屬性名到屬性設(shè)置的映射表 | |
| data | Object | 否 | 組件的內(nèi)部數(shù)據(jù),和 properties 一同用于組件的模板渲染 | |
| observers | Object | 否 | 組件數(shù)據(jù)字段監(jiān)聽(tīng)器,用于監(jiān)聽(tīng) properties 和 data 的變化,參見(jiàn) 數(shù)據(jù)監(jiān)聽(tīng)器 | 2.6.1 |
| methods | Object | 否 | 組件的方法,包括事件響應(yīng)函數(shù)和任意的自定義方法,關(guān)于事件響應(yīng)函數(shù)的使用,參見(jiàn) 組件間通信與事件 | |
| behaviors | String Array | 否 | 類似于mixins和traits的組件間代碼復(fù)用機(jī)制,參見(jiàn) behaviors | |
| created | Function | 否 | 組件生命周期函數(shù)-在組件實(shí)例剛剛被創(chuàng)建時(shí)執(zhí)行,注意此時(shí)不能調(diào)用 setData ) | |
| attached | Function | 否 | 組件生命周期函數(shù)-在組件實(shí)例進(jìn)入頁(yè)面節(jié)點(diǎn)樹(shù)時(shí)執(zhí)行) | |
| ready | Function | 否 | 組件生命周期函數(shù)-在組件布局完成后執(zhí)行) | |
| moved | Function | 否 | 組件生命周期函數(shù)-在組件實(shí)例被移動(dòng)到節(jié)點(diǎn)樹(shù)另一個(gè)位置時(shí)執(zhí)行) | |
| detached | Function | 否 | 組件生命周期函數(shù)-在組件實(shí)例被從頁(yè)面節(jié)點(diǎn)樹(shù)移除時(shí)執(zhí)行) | |
| relations | Object | 否 | 組件間關(guān)系定義,參見(jiàn) 組件間關(guān)系 | |
| lifetimes | Object | 否 | 組件生命周期聲明對(duì)象,參見(jiàn) 組件生命周期 | 2.2.3 |
| pageLifetimes | Object | 否 | 組件所在頁(yè)面的生命周期聲明對(duì)象,參見(jiàn) 組件生命周期 | 2.2.3 |
| definitionFilter | Function | 否 | 定義段過(guò)濾器,用于自定義組件擴(kuò)展,參見(jiàn) 自定義組件擴(kuò)展 | 2.2.3 |
組件中使用
組件引用時(shí),在 behaviors 定義段中將它們逐個(gè)列出即可。
代碼示例:
// 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 結(jié)構(gòu)為:
- 屬性:
myBehaviorProperty - 數(shù)據(jù)字段:
myBehaviorData - 方法:
myBehaviorMethod - 生命周期函數(shù):
attached、created、ready
這將使 my-component 最終結(jié)構(gòu)為:
- 屬性:
myBehaviorProperty、myProperty - 數(shù)據(jù)字段:
myBehaviorData、myData - 方法:
myBehaviorMethod、myMethod - 生命周期函數(shù):
attached、created、ready
當(dāng)組件觸發(fā)生命周期時(shí),上例生命周期函數(shù)執(zhí)行順序?yàn)椋?/p>
[my-behavior] created[my-component] created[my-behavior] attached[my-component] attached[my-behavior] ready[my-component] ready
詳細(xì)規(guī)則參考 同名字段的覆蓋和組合規(guī)則。
同名字段的覆蓋和組合規(guī)則
組件和它引用的 behavior 中可以包含同名的字段,對(duì)這些字段的處理方法如下:
- 如果有同名的屬性 (properties) 或方法 (methods):
- 若組件本身有這個(gè)屬性或方法,則組件的屬性或方法會(huì)覆蓋 behavior 中的同名屬性或方法;
- 若組件本身無(wú)這個(gè)屬性或方法,則在組件的 behaviors 字段中定義靠后的 behavior 的屬性或方法會(huì)覆蓋靠前的同名屬性或方法;
- 在 2 的基礎(chǔ)上,若存在嵌套引用 behavior 的情況,則規(guī)則為:引用者 behavior 覆蓋 被引用的 behavior 中的同名屬性或方法。
- 如果有同名的數(shù)據(jù)字段 (data):
- 若同名的數(shù)據(jù)字段都是對(duì)象類型,會(huì)進(jìn)行對(duì)象合并;
- 其余情況會(huì)進(jìn)行數(shù)據(jù)覆蓋,覆蓋規(guī)則為: 引用者 behavior > 被引用的 behavior 、 靠后的 behavior > 靠前的 behavior。(優(yōu)先級(jí)高的覆蓋優(yōu)先級(jí)低的,最大的為優(yōu)先級(jí)最高)
- 生命周期函數(shù)和 observers 不會(huì)相互覆蓋,而是在對(duì)應(yīng)觸發(fā)時(shí)機(jī)被逐個(gè)調(diào)用:
- 對(duì)于不同的生命周期函數(shù)之間,遵循組件生命周期函數(shù)的執(zhí)行順序;
- 對(duì)于同種生命周期函數(shù)和同字段 observers ,遵循如下規(guī)則:
- behavior 優(yōu)先于組件執(zhí)行;
- 被引用的 behavior 優(yōu)先于 引用者 behavior 執(zhí)行;
- 靠前的 behavior 優(yōu)先于 靠后的 behavior 執(zhí)行;
- 如果同一個(gè) behavior 被一個(gè)組件多次引用,它定義的生命周期函數(shù)和 observers 不會(huì)重復(fù)執(zhí)行。
到此這篇關(guān)于微信小程序之behaviors的文章就介紹到這了,更多相關(guān)微信小程序behaviors內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中數(shù)組常見(jiàn)操作技巧
下面介紹JavaScript中的數(shù)組對(duì)象遍歷、讀寫(xiě)、排序等操作以及與數(shù)組相關(guān)的字符串處理操作,需要的的朋友參考下吧2017-09-09
javascript 7行代碼畫(huà)出一個(gè)圍棋棋盤(pán)
javascript 只有7行代碼即可畫(huà)出圍棋棋盤(pán)的實(shí)現(xiàn)代碼。大家可以看看。2009-07-07
js控制iframe的高度/寬度讓其自適應(yīng)內(nèi)容
這篇文章主要介紹了如何使用js控制iframe的高度/寬度讓其自適應(yīng)內(nèi)容,需要的朋友可以參考下2014-04-04
分享10個(gè)常見(jiàn)的JavaScript前端手寫(xiě)功能
這篇文章主要分享10個(gè)常見(jiàn)的前端手寫(xiě)功能,防抖、節(jié)流、深拷貝、異步控制并發(fā)數(shù)、繼承等功能技巧,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-02-02
JavaScript中使用構(gòu)造器創(chuàng)建對(duì)象無(wú)需new的情況說(shuō)明
JS中創(chuàng)建對(duì)象可以直接使用直接量的方式,這里討論的是定義一個(gè)構(gòu)造器(function)的情況2012-03-03

