当前位置:   article > 正文

小程序自定义组件扩展功能介绍_网站小程序扩展组件

网站小程序扩展组件

为了更好定制自定义组件的功能,可以使用自定义组件扩展机制。

扩展后的效果

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

  1. // behavior.js
  2. export default Behavior({
  3. definitionFilter(defFields) {
  4. defFields.data.from = 'behavior';
  5. },
  6. });
  7. // component.js
  8. import myBehavior from 'behavior.js';
  9. Component({
  10. data: {
  11. from: 'component',
  12. },
  13. behaviors: [myBehavior],
  14. ready() {
  15. console.log(this.data.from); // 此处会发现输出 behavior 而不是 component
  16. },
  17. });

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

使用扩展

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

以下举个例子来说明:

  1. // behavior3.js
  2. export default Behavior({
  3. definitionFilter(defFields, definitionFilterArr) {},
  4. });
  5. // behavior2.js
  6. import behavior3 from 'behavior3.js';
  7. export default Behavior({
  8. behaviors: [behavior3],
  9. definitionFilter(defFields, definitionFilterArr) {
  10. // definitionFilterArr[0](defFields)
  11. },
  12. });
  13. // behavior1.js
  14. import behavior2 from 'behavior2.js';
  15. export default Behavior({
  16. behaviors: [behavior2],
  17. definitionFilter(defFields, definitionFilterArr) {},
  18. });
  19. // component.js
  20. import behavior1 from 'behavior1.js';
  21. Component({
  22. behaviors: [behavior1],
  23. });

上述代码中声明了 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 的定义对象。

真实案例

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

  1. // behavior.js
  2. export default Behavior({
  3. lifetimes: {
  4. created() {
  5. this._originalSetData = this.setData; // 原始 setData
  6. this.setData = this._setData; // 封装后的 setData
  7. },
  8. },
  9. definitionFilter(defFields) {
  10. const computed = defFields.computed || {};
  11. const computedKeys = Object.keys(computed);
  12. const computedCache = {};
  13. // 计算 computed
  14. const calcComputed = (scope, insertToData) => {
  15. const needUpdate = {};
  16. const data = (defFields.data = defFields.data || {});
  17. for (let key of computedKeys) {
  18. const value = computed[key].call(scope); // 计算新值
  19. if (computedCache[key] !== value)
  20. needUpdate[key] = computedCache[key] = value;
  21. if (insertToData) data[key] = needUpdate[key]; // 直接插入到 data 中,初始化时才需要的操作
  22. }
  23. return needUpdate;
  24. };
  25. // 重写 setData 方法
  26. defFields.methods = defFields.methods || {};
  27. defFields.methods._setData = function (data, callback) {
  28. const originalSetData = this._originalSetData; // 原始 setData
  29. originalSetData.call(this, data, callback); //data 的 setData
  30. const needUpdate = calcComputed(this); // 计算 computed
  31. originalSetData.call(this, needUpdate); // 做 computed 的 setData
  32. };
  33. // 初始化 computed
  34. calcComputed(defFields, true); // 计算 computed
  35. },
  36. });

在组件中使用:

  1. import beh from './behavior.js';
  2. Component({
  3. behaviors: [beh],
  4. data: {
  5. a: 0,
  6. },
  7. computed: {
  8. b() {
  9. return this.data.a + 100;
  10. },
  11. },
  12. methods: {
  13. onTap() {
  14. this.setData({
  15. a: ++this.data.a,
  16. });
  17. },
  18. },
  19. });
  1. <view>data: {{a}}</view>
  2. <view>computed: {{b}}</view>
  3. <button bind:tap="onTap">click</button>

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

此实现只是作为一个简单案例来展示,请勿直接在生产环境中使用。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/387582
推荐阅读
相关标签
  

闽ICP备14008679号