小白教程

 找回密码
 立即注册

微信小程序 自定义组件扩展

发布者: 小白教程

自定义组件扩展

为了更好定制自定义组件的功能,可以使用自定义组件扩展机制。从小程序基础库版本 2.2.3 开始支持。

扩展后的效果

为了更好的理解扩展后的效果,先举一个例子:

// behavior.js
module.exports = Behavior({
  definitionFilter(defFields) {
    defFields.data.from = 'behavior'
  },
})

// component.js
Component({
  data: {
    from: 'component'
  },
  behaviors: [require('behavior.js')],
  ready() {
    console.log(this.data.from) // 此处会发现输出 behavior 而不是 component
  }
})

通过例子可以发现,自定义组件的扩展其实就是提供了修改自定义组件定义段的能力,上述例子就是修改了自定义组件中的 data 定义段里的内容。

使用扩展

Behavior() 构造器提供了新的定义段 definitionFilter ,用于支持自定义组件扩展。 definitionFilter 是一个函数,在被调用时会注入两个参数,第一个参数是使用该 behavior 的 component/behavior 的定义对象,第二个参数是该 behavior 所使用的 behavior 的 definitionFilter 函数列表。

以下举个例子来说明:

// behavior3.js
module.exports = Behavior({
    definitionFilter(defFields, definitionFilterArr) {},
})

// behavior2.js
module.exports = Behavior({
  behaviors: [require('behavior3.js')],
  definitionFilter(defFields, definitionFilterArr) {
    // definitionFilterArr[0](defFields)
  },
})

// behavior1.js
module.exports = Behavior({
  behaviors: [require('behavior2.js')],
  definitionFilter(defFields, definitionFilterArr) {},
})

// component.js
Component({
  behaviors: [require('behavior1.js')],
})

上述代码中声明了1个自定义组件和3个 behavior,每个 behavior 都使用了 definitionFilter 定义段。那么按照声明的顺序会有如下事情发生:

  1. 当进行 behavior2 的声明时就会调用 behavior3 的 definitionFilter 函数,其中 defFields 参数是 behavior2 的定义段, definitionFilterArr 参数即为空数组,因为 behavior3 没有使用其他的 behavior 。
  2. 当进行 behavior1 的声明时就会调用 behavior2 的 definitionFilter 函数,其中 defFields 参数是 behavior1 的定义段, definitionFilterArr 参数是一个长度为1的数组,definitionFilterArr[0] 即为 behavior3 的 definitionFilter 函数,因为 behavior2 使用了 behavior3。用户在此处可以自行决定在进行 behavior1 的声明时要不要调用 behavior3 的 definitionFilter 函数,如果需要调用,在此处补充代码 definitionFilterArr[0](defFields) 即可,definitionFilterArr 参数会由基础库补充传入。
  3. 同理,在进行 component 的声明时就会调用 behavior1 的 definitionFilter 函数。

简单概括,definitionFilter 函数可以理解为当 A 使用了 B 时,A 声明就会调用 B 的 definitionFilter 函数并传入 A 的定义对象让 B 去过滤。此时如果 B 还使用了 C 和 D ,那么 B 可以自行决定要不要调用 C 和 D 的 definitionFilter 函数去过滤 A 的定义对象。

真实案例

下面利用扩展简单实现自定义组件的计算属性功能:

// behavior.js
module.exports = Behavior({
  lifetimes: {
    created() {
      this._originalSetData = this.setData // 原始 setData
      this.setData = this._setData // 封装后的 setData
    }
  },
  definitionFilter(defFields) {
    const computed = defFields.computed || {}
    const computedKeys = Object.keys(computed)
    const computedCache = {}

    // 计算 computed
    const calcComputed = (scope, insertToData) => {
      const needUpdate = {}
      const data = defFields.data = defFields.data || {}

      for (let key of computedKeys) {
        const value = computed[key].call(scope) // 计算新值
        if (computedCache[key] !== value) needUpdate[key] = computedCache[key] = value
        if (insertToData) data[key] = needUpdate[key] // 直接插入到 data 中,初始化时才需要的操作
      }

      return needUpdate
    }

    // 重写 setData 方法
    defFields.methods = defFields.methods || {}
    defFields.methods._setData = function (data, callback) {
      const originalSetData = this._originalSetData // 原始 setData
      originalSetData.call(this, data, callback) // 做 data 的 setData
      const needUpdate = calcComputed(this) // 计算 computed
      originalSetData.call(this, needUpdate) // 做 computed 的 setData
    }

    // 初始化 computed
    calcComputed(defFields, true) // 计算 computed
  }
})

在组件中使用:

const beh = require('./behavior.js')
Component({
  behaviors: [beh],
  data: {
    a: 0,
  },
  computed: {
    b() {
      return this.data.a + 100
    },
  },
  methods: {
    onTap() {
      this.setData({
        a: ++this.data.a,
      })
    }
  }
})
<view>data: {{a}}</view>
<view>computed: {{b}}</view>
<button bindtap="onTap">click</button>

实现原理很简单,对已有的 setData 进行二次封装,在每次 setData 的时候计算出 computed 里各字段的值,然后设到 data 中,已达到计算属性的效果。

微信小程序教程
  1. 微信小程序 小程序简介

  2. 微信小程序 开始

  3. 小程序代码构成

  4. 小程序宿主环境

  5. 小程序协同工作和发布

  6. 配置小程序

  7. sitemap配置

  8. 微信小程序 场景值

  9. 微信小程序 注册小程序

  10. 微信小程序 注册页面

  11. 微信小程序 页面生命周期

  12. 微信小程序 页面路由

  13. 微信小程序 模块化

  14. 微信小程序 API

  15. 微信小程序 WXML

  16. 微信小程序 WXSS

  17. 微信小程序 WXS

  18. 微信小程序 事件系统

  19. 微信小程序 简单双向绑定

  20. 微信小程序 基础组件

  21. 微信小程序 获取界面上的节点信息

  22. 微信小程序 响应显示区域变化

  23. 微信小程序 动画

  24. 微信小程序 初始渲染缓存

  25. 微信小程序 运行环境

  26. 微信小程序 JavaScript支持情况

  27. 微信小程序 运行机制

  28. 微信小程序 更新机制

  29. 微信小程序 组件模板和样式

  30. 微信小程序 Component构造器

  31. 微信小程序 组件间通信与时间

  32. 微信小程序 组件生命周期

  33. 微信小程序 behaviors

  34. 微信小程序 组件间关系

  35. 微信小程序 数据监听器

  36. 微信小程序 纯数据字段

  37. 微信小程序 抽象节点

  38. 微信小程序 自定义组件扩展

  39. 微信小程序 开发第三方自定义组件

  40. 微信小程序 单元测试

  41. 微信小程序 开发插件

  42. 微信小程序 使用插件

  43. 微信小程序 插件调用API的限制

  44. 微信小程序 插件功能页

  45. 微信小程序 网络

  46. 微信小程序 文件系统

  47. 微信小程序 画布

  48. 微信小程序 分包加载

  49. 微信小程序 多线程Worker

  50. 微信小程序 服务端能力

  51. 微信小程序 自定义tabBar

  52. 微信小程序 周期性更新

  53. 微信小程序 数据预拉取

  54. 微信小程序 DarkMode适配指南

  55. 微信小程序 大屏适配指南

Archiver|手机版|小黑屋|小白教程 ( 粤ICP备20019910号 )

GMT+8, 2024-9-20 06:36 , Processed in 0.031186 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc. Template By 【未来科技】【 www.wekei.cn 】

返回顶部