微信小程序——自定义组件

6.2.3 自定义组件

自定义组件是开发者可以自行扩充的组件。开发者可以将常用的节点树结构提取成自定义组件,实现代码复用。

1. ShadowTree的概念

我们以下面的代码为例来阐述Shadow Tree的概念。

代码清单6-2 页面节点树(Composed Tree)

<view>

  <input-with-label>

    <label>

      TEXT

    </label>

    <input />

  </input-with-label>

</view>

这里如果将input-with-label抽象成一个组件,那么可以将整个节点树拆分成两部分。

代码清单6-3 组件节点树(Shadow Tree)

<label><slot/></label>

<input />

代码清单6-4 调用组件的节点树

<view>

    <input-with-label>

        TEXT

    </input-with-label>

</view>

在Exparser的组件模型中,这两个节点树可以被拼接成上方的页面节点树。其中,组件的节点树称为“ShadowTree”,即组件内部的实现;最终拼接成的页面节点树被称为“Composed Tree”,即将页面所有组件节点树合成之后的树。在进行了这样的组件分离之后,整个页面节点树实质上被拆分成了若干个ShadowTree(页面的body实质上也是一个组件,因而也是一个ShadowTree)。

同时,各个组件也将具有各自独立的逻辑空间。每个组件都分别拥有自己的独立的数据、setData调用,createSelectorQuery也将运行在Shadow Tree的层面上。关于具体如何使用自定义组件特性,这里不再详细讨论,请参阅小程序开发文档。

2. 运行原理

在使用自定义组件的小程序页面中,Exparser将接管所有的自定义组件注册与实例化。从外部接口上看,小程序基础库提供有Page和Component两个构造器。以Component为例,在小程序启动时,构造器会将开发者设置的properties、data、methods等定义段,写入Exparser的组件注册表中。这个组件在被其它组件引用时,就可以根据这些注册信息来创建自定义组件的实例。Page构造器的大体运行流程与之相仿,只是参数形式不一样。这样每个页面就有一个与之对应的组件,称为“页面根组件”。

在初始化页面时,Exparser会创建出页面根组件的一个实例,用到的其他组件也会响应创建组件实例(这是一个递归的过程)。组件创建的过程大致有以下几个要点:

  1. 根据组件注册信息,从组件原型上创建出组件节点的JS对象,即组件的this;
  2. 将组件注册信息中的data 复制一份,作为组件数据,即this.data;
  3. 将这份数据结合组件WXML,据此创建出Shadow Tree,由于Shadow Tree中可能引用有其他组件,因而这会递归触发其他组件创建过程;
  4. 将ShadowTree拼接到Composed Tree上,并生成一些缓存数据用于优化组件更新性能;
  5. 触发组件的created生命周期函数;
  6. 如果不是页面根组件,需要根据组件节点上的属性定义,来设置组件的属性值;
  7. 当组件实例被展示在页面上时,触发组件的attached 生命周期函数,如果Shadw Tree中有其他组件,也逐个触发它们的生命周期函数。

3. 组件间通信

不同组件实例间的通信有WXML属性值传递、事件系统、selectComponent和relations等方式。其中,WXML属性值传递是从父组件向子组件的基本通信方式,而事件系统是从子组件向父组件的基本通信方式。

Exparser的事件系统完全模仿Shadow DOM的事件系统。在通常的理解中,事件可以分为冒泡事件和非冒泡事件,但在ShadowDOM体系中,冒泡事件还可以划分为在Shadow Tree上冒泡的事件和在Composed Tree上冒泡的事件。如果在Shadow Tree上冒泡,则冒泡只会经过这个组件Shadow Tree上的节点,这样可以有效控制事件冒泡经过的范围。

代码清单6-5 input-with-label的WXML

<label>

  <input />

  <slot />

</label>

代码清单6-6 页面WXML

<view>

  <input-with-label>

    <button />

  </input-with-label>

</view>

用上面的例子来说,当在 button 上触发一个事件时:

l 如果事件是非冒泡的,那只能在 button 上监听到事件;

l 如果事件是在 Shadow Tree 上冒泡的,那 button 、 input-with-label 、view 可以依次监听到事件;

l 如果事件是在 Composed Tree 上冒泡的,那 button 、 slot 、label 、 input-with-label 、 view 可以依次监听到事件。

在自定义组件中使用triggerEvent触发事件时,可以指定事件的bubbles、composed和capturePhase属性,用于标注事件的冒泡性质。

代码清单6-7 triggerEvent事例

Component({

  methods: {

    helloEvent: function() {

      this.triggerEvent('hello', {}, {

        bubbles: true,      // 这是一个冒泡事件

        composed: true,     // 这个事件在Composed Tree 上冒泡

        capturePhase: false // 这个事件没有捕获阶段

      })

    }

  }

})

小程序基础库自身也会通过这套事件系统提供一些用户事件,如tap、touchstart和form组件的submit等。其中,tap等用户触摸引发的事件是在ComposedTree上的冒泡事件,其他事件大多是非冒泡事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值