微信小程序之behaviors

目录

概括

Demo演示

进阶演示

[1. 若具有同名的属性或方法](#1. 若具有同名的属性或方法)

[2. 若有同名的数据](#2. 若有同名的数据)

[3. 若有同名的生命周期函数](#3. 若有同名的生命周期函数)

应用场景

最后

属性&方法

组件中使用

代码示例:

同名字段的覆盖和组合规则


概括

一句话总结: behaviors是用于组件间代码共享的特性, 类似一些编程语言中的'mixin'或者'traits'.

A.每个behaviors包含一组属性、数据、生命周期函数、自定义方法 -> 组件引用它时, 属性、数据、生命周期函数、自定义方法都会被合并到组件中,生命周期函数也会在对应的时机被调用.

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>数据: {{myBehaviorData}} --- {{myCompData}}</view>
<view bind:tap="myBehaviorMethod">触发behavior的自定义方法</view>
<view bind:tap="myCompMethod">触发组件的自定义方法</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

数据: myBehaviorData

生命周期: created() && attached() && ready()

自定义方法: myBehaviorMethod

组件引入该behaviors后的结构:

属性: myBehaviorProperty、 myCompProperty

数据: myBehaviorData、myCompData

生命周期: created() && attached() && ready()

自定义方法: myBehaviorMethod、myCompMethod

紧接着, 来看看代码运行结果: 也许你会对输出有疑问, 先不着急, 慢慢往下看.

进阶演示

上面的Demo仅演示了最基础的behaviors的用法, 接下来我们看看遇到同名的属性or数据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')
  }
}

上述代码表现形式如下: 组件的同名属性覆盖了behavior的同名属性; 点击自定义方法, 触发的是组件的自定义方法.

至此, 你会不会好奇如果属性是个object, 是怎么个表现形式呢, 接下来看看实际效果.

复制代码
// 新建个组件, 组件级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]-体现同名对象类型不会做合并'
    }
  }
}

上述代码表现形式如下: 同名属性即使是对象类型, 也只会做覆盖,

区别于下文的同名数据的合并操作哦.

2. 若有同名的数据

A. 若数据类型是对象, 进行对象合并;

B. 其它类型会进行数据覆盖, 覆盖原则:

组件 > 父behavior > 子behavior; 靠后的behavior > 靠前的behavior;

Demo演示: 针对数据是对象&非对象

复制代码
// 组件级js
data: {
  sameObj: {
    val1: '[my-component]-同名数据类型是对象'
  },
  sameData: false
},
ready: function (){
  console.log('[my-component]- ready')
  console.log('[my-behavior]- 同名数据', this.data.sameObj, this.data.sameData)
},

// behavior级
data: {
  sameObj: {
    val1: '[my-behavior]-同名数据类型是对象',
    val2: '[my-behavior]-体现同名数据类型做合并'
  },
  sameData: true
},

上述代码表现形式如下: 同名数据对象做合并, 同名数据非对象做覆盖.

3. 若有同名的生命周期函数

不会被覆盖、而是在对应的触发时机内逐个调用:

A. 不同的生命周期之间, 遵循组件生命周期的执行顺序;

B. 同种生命周期函数:

①. behavior优先于组件执行;

②. 子behavior优先于父behavior执行;

③. 靠前的behavior优先于靠后的behavior执行;

C. 如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数只会被执行一次;

应用场景

相信到了这里, 你应该明白了Demo演示中控制台的输出是基于什么来输出的, 接下来我们看看什么样的应用场景会考虑使用该属性呢?

如下图, 有个中间弹窗组件&&底部弹窗组件, 均内聚有如下功能点:

A. 触发某一条件后, 出现该弹窗;

B. 点击遮罩层, 关闭弹窗;

考虑下如果将弹窗显示跟隐藏的逻辑放在behaviors里面, 是否能避免同份代码逻辑写2遍的问题呢.

Page中不能使用behaviors、只能在Components中使用!!!!!! 故若遇到真想使用behaviors属性的页面, 试试把某块页面内容抽离成组件, 然后引用组件的方式去实现.

最后

behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 "mixins" 或 "traits"。

每个 behavior 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior 。


属性&方法

注册一个 behavior,接受一个 Object 类型的参数。

定义段 类型 是否必填 描述 最低版本
properties Object Map 否 组件的对外属性,是属性名到属性设置的映射表
data Object 否 组件的内部数据,和 properties 一同用于组件的模板渲染
observers Object 否 组件数据字段监听器,用于监听 properties 和 data 的变化,参见 数据监听器 2.6.1
methods Object 否 组件的方法,包括事件响应函数和任意的自定义方法,关于事件响应函数的使用,参见 组件间通信与事件
behaviors String Array 否 类似于mixins和traits的组件间代码复用机制,参见 behaviors
created Function 否 组件生命周期函数-在组件实例刚刚被创建时执行,注意此时不能调用 setData )
attached Function 否 组件生命周期函数-在组件实例进入页面节点树时执行)
ready Function 否 组件生命周期函数-在组件布局完成后执行)
moved Function 否 组件生命周期函数-在组件实例被移动到节点树另一个位置时执行)
detached Function 否 组件生命周期函数-在组件实例被从页面节点树移除时执行)
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
  • 数据字段:myBehaviorData
  • 方法:myBehaviorMethod
  • 生命周期函数:attached、created、ready

这将使 my-component 最终结构为:

  • 属性:myBehaviorProperty、myProperty
  • 数据字段:myBehaviorData、myData
  • 方法:myBehaviorMethod、myMethod
  • 生命周期函数:attached、created、ready

当组件触发生命周期时,上例生命周期函数执行顺序为:

  1. [my-behavior] created
  2. [my-component] created
  3. [my-behavior] attached
  4. [my-component] attached
  5. [my-behavior] ready
  6. [my-component] ready

详细规则参考 同名字段的覆盖和组合规则。

同名字段的覆盖和组合规则

组件和它引用的 behavior 中可以包含同名的字段,对这些字段的处理方法如下:

  • 如果有同名的属性 (properties) 或方法 (methods):
    1. 若组件本身有这个属性或方法,则组件的属性或方法会覆盖 behavior 中的同名属性或方法;
    2. 若组件本身无这个属性或方法,则在组件的 behaviors 字段中定义靠后的 behavior 的属性或方法会覆盖靠前的同名属性或方法;
    3. 在 2 的基础上,若存在嵌套引用 behavior 的情况,则规则为:引用者 behavior 覆盖 被引用的 behavior 中的同名属性或方法。
  • 如果有同名的数据字段 (data):
    • 若同名的数据字段都是对象类型,会进行对象合并;
    • 其余情况会进行数据覆盖,覆盖规则为: 引用者 behavior > 被引用的 behavior 、 靠后的 behavior > 靠前的 behavior。(优先级高的覆盖优先级低的,最大的为优先级最高)
  • 生命周期函数和 observers 不会相互覆盖,而是在对应触发时机被逐个调用:
    • 对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序;
    • 对于同种生命周期函数和同字段 observers ,遵循如下规则:
      • behavior 优先于组件执行;
      • 被引用的 behavior 优先于 引用者 behavior 执行;
      • 靠前的 behavior 优先于 靠后的 behavior 执行;
    • 如果同一个 behavior 被一个组件多次引用,它定义的生命周期函数和 observers 不会重复执行。
相关推荐
李纲明8 小时前
微信小程序 getSystemInfo 提示已废弃、屏幕高度算错胶囊还对不齐?getWindowInfo 和 getDeviceInfo 怎么接才稳
javascript·微信小程序·小程序·小程序开发·devdiy
dreams_dream11 小时前
微信小程序-使用npm包
微信小程序·小程序·npm
L1mbo12 小时前
Lite模式 缓解微信开发者工具卡顿,附 uni-app 实践方案
前端·微信小程序
caoliaoerweima14 小时前
草料二维码小程序上线活码编辑器:手机上也能编辑活码了
智能手机·小程序·编辑器·草料二维码
大数据技术派1 天前
等了一周,我的摸鱼小程序终于微信认证通过了
微信小程序
CSharp精选营2 天前
记一次家庭物品管理的折腾:从“收纳”到“可检索”
微信小程序·aicoding·屋册有序·物品收纳管理·家庭收纳管理工具
dreams_dream3 天前
微信小程序:页面事件-上拉触底
微信小程序·小程序
鹏多多3 天前
AI 到底能不能独立做个产品?我拿一个小程序验证了
前端·微信小程序·ai编程
wafrdggh4 天前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序
计算机毕设定制辅导-无忧学长4 天前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统