// basic.ts export const basic = Behavior({ methods: { $emit(...args) { this.triggerEvent(...args); }, set(data: object, callback: Function) { this.setData(data, callback); return new Promise(resolve => wx.nextTick(resolve)); }, getRect(selector: string, all: boolean) { return new Promise(resolve => { wx.createSelectorQuery() .in(this)[all ? 'selectAll' : 'select'](selector) .boundingClientRect(rect => { if (all && Array.isArray(rect) && rect.length) { resolve(rect); } if (!all && rect) { resolve(rect); } }) .exec(); }); } } });
源码: basic.ts
生命周期命名
其实生命周期如何命名到不是很重要,vant-weapp对命名进行了转换主要基于以下两个原因:
开发效率 :vant-weapp源自适用于vue的UI组件库—— vant ,命名统一转换便于现有框架的逻辑复用
使用成本 :生命周期命名向主流MVVM框架靠近减轻使用者的学习成本、框架维护成本
function mapKeys(source: object, target: object, map: object) { Object.keys(map).forEach(key => { if (source[key]) { target[map[key]] = source[key]; } }); } mapKeys(vantOptions, options, { data: 'data', props: 'properties', mixins: 'behaviors', methods: 'methods', beforeCreate: 'created', created: 'attached', mounted: 'ready', relations: 'relations', destroyed: 'detached', classes: 'externalClasses' });
源码:
通过 mapKeys 方法对 VantComponent 中传入的生命周期函数进行了转换,转换名生命周期名称与微信小程序一致
自定义组件的样式隔离
微信小程序自定义组件默认样式作用域的范围是为当前组件,也就是说组件文件夹下的wxss中的样式只对该文件夹下的wxml生效(除去标签名、ID选择器)
这种以组件为单位进行样式隔离的模式类似于React框架中处理的组件样式的库 styled-components
组件间样式共享
要在组件之前共享样式或者让自定义组件接受外部样式,可行方案有如下几种:
| styleIsolation属性配置 |
page-isolated 表示在这个页面禁用 app.wxss ,同时,页面的 wxss 不会影响到其他自定义组件;
page-apply-shared 表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式不会影响到其他自定义组件,但设为 shared 的自定义组件会影响到页面;
page-shared 表示在这个页面禁用 app.wxss ,同时,页面 wxss 样式会影响到其他设为 apply-shared 或 shared 的自定义组件,也会受到设为 shared 的自定义组件的影响。 | styleIsolation 选项从基础库版本 2.6.5 开始支持 | | --- | --- | --- | | addGlobalClass属性配置 | 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面 |
小程序基础库版本 2.2.3 以上支持
等价于styleIsolation: apply-shared
vant-weapp中使用的是此方案 : addGlobalClass: 'true' ,默认的 styleIsolation: 'shared' 不生效 | | externalClasses外部样式类 | 组件的使用者可以指定这个样式类对应的外部样式名 ,对应样式名的样式在组件内部生效 |
基础库 1.9.90 开始支持
vant-weapp中也支持此方式
推荐使用此方式来自定义vant-weapp的样式 | |引用父组件样式 | 即使启用了样式隔离 isolated ,组件仍然可以在局部引用组件所在页面的样式或父组件的样式 | 基础库 2.9.2 开始支持 |
使用总结
使用vant-weapp组件库的使用者最佳的自定义组件样式的方式是: 采用外部样式类+CSS变量,在无相关CSS变量时才用自己的样式+ !important 确保样式优先级 ,在自定义组件中使用vant-weapp的组件时候的注意事项参照 。
自定义组件通信方案
自定义组件通信主要包括 组件参数传递 和 事件监听 ,这两个功能都是微信小程序官网提供的;参数传递是由父传到子的单向传递,而事件监听则是相应原生事件或者自定义事件。自定义事件用于对组件的事件进行封装,自定义事件机制如下:
这里在van-dialog组件使用位置监听bindclick事件,最终这个事件会在van-dialog组件内部的button的tap时被触发,后面源码分析中的自定义组件的自定义事件全部采用的此种模式。
七、Popup弹出层组件源码分析组件部分源码结构
popup组件部分源码结构如下:
组件的命名规范与微信小程序自定义组件的规范相符合(README.md为组件的使用说明文档,用于生成官网的组件文档说明)。
popup组件的配置文件标识当前的index为组件,通过 using-components 引入了 van-icon 和 van-overlay 组件,在对应的wxml中可以直接使用。
组件主要逻辑
弹出层组件主要分类 遮盖层 和 内容层 ,内容层嵌套在遮盖层内部来确保视觉上覆盖在遮盖层之上。
遮盖层及事件
遮盖层通过overlay、overlayStyle等组件属性来控制其是否显示以及遮盖层的样式等,遮盖的事件有 onClickOverlay ,通过$emit触发组件的自定义事件close。
onClickOverlay() { this.$emit('click-overlay'); if (this.data.closeOnClickOverlay) { this.$emit('close'); } }
关闭按钮及事件