微信小程序之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 可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用。 每个组件可以引用多个 behaviorbehavior 也可以引用其它 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
  • 生命周期函数:attachedcreatedready

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

  • 属性:myBehaviorPropertymyProperty
  • 数据字段:myBehaviorDatamyData
  • 方法:myBehaviorMethodmyMethod
  • 生命周期函数:attachedcreatedready

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

  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 不会重复执行。
相关推荐
郭wes代码2 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
.生产的驴7 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
汤姆yu12 小时前
基于微信小程序的乡村旅游系统
微信小程序·旅游·乡村旅游
计算机徐师兄13 小时前
基于TP5框架的家具购物小程序的设计与实现【附源码、文档】
小程序·php·家具购物小程序·家具购物微信小程序·家具购物
曲辒净13 小时前
微信小程序实现二维码海报保存分享功能
微信小程序·小程序
朽木成才15 小时前
小程序快速实现大模型聊天机器人
小程序·机器人
peachSoda715 小时前
随手记:小程序使用uni.createVideoContext视频无法触发播放
小程序
何极光15 小时前
uniapp小程序样式穿透
前端·小程序·uni-app
小墨&晓末15 小时前
【PythonGui实战】自动摇号小程序
python·算法·小程序·系统安全
oil欧哟1 天前
🤔认真投入一个月做的小程序,能做成什么样子?有人用吗?
前端·vue.js·微信小程序