通过closable属性决定是否显示默认的关闭按钮,也可以通过关闭图标相关属性配置更改按钮样式,关闭按钮的事件有onClickCloseIcon,通过$emit触发组件的自定义事件close。
onClickCloseIcon() { this.$emit('close'); },
内容分发
接受一个默认的slot,其位置根据传入的 position 参数不同有 top、right、bottom、left、center 五种,根据这五种位置参数有对应的五种不同的弹出位置和动画
过渡动画
使用transform来实现动画效果,根据 position 参数的五种情况有五种默认动画
// popup/index.less .van-bottom-enter, .van-bottom-leave-to { transform: translate3d(0, 100%, 0); } .van-top-enter, .van-top-leave-to { transform: translate3d(0, -100%, 0); } .van-left-enter, .van-left-leave-to { transform: translate3d(-100%, -50%, 0); } .van-right-enter, .van-right-leave-to { transform: translate3d(100%, -50%, 0); }
同时暴露了外部样式类可以用来自定义动画,这里动画阶段划分和vue相同,分类: enter、enter-active、enter-to、leave、leave-active、leave-to
// popup/index.ts VantComponent({ classes: [ 'enter-class', 'enter-active-class', 'enter-to-class', 'leave-class', 'leave-active-class', 'leave-to-class' ], ... }
八、Dialog对话框组件源码分析组件部分源码结构
dialog组件部分源码结构如下:
结构同popup组件,不同点在于index.json使用了 van-popup、van-button 组件,以及多了dialog.ts这个暴露API函数调用方法的文件。
组件布局结构
dialog组件整体基于popup组件,在其默认slot中添加了顶部标题的slot和按钮组元素,大致结构如下
源码结构:
// dialog/index.wxml <van-popup show="{{ show }}" ... > <view wx:if="{{ title || useTitleSlot }}" > <slot wx:if="{{ useTitleSlot }}" /> <block wx:elif="{{ title }}"> {{ title }}</block> </view> <slot wx:if="{{ useSlot }}" /> <view wx:elif="{{ message }}" > <text>{{ message }}</text> </view> <view> <van-button wx:if="{{ showCancelButton }}" ... > {{ cancelButtonText }} </van-button> <van-button wx:if="{{ showConfirmButton }}" ... > {{ confirmButtonText }} </van-button> </view> </van-popup>
函数式调用实现
在前面中通过Dialog函数调用来打开弹出框组件,实现函数式调用的核心思路主要是: 通过selectComponent(selector)方法查找(类似于查找DOM、Vue中查找组件实例)对页面中定义渲染好的dialog组件,手动更新其组件实例的数据。 ** Dialog方法定义如下:
const Dialog: Dialog = options => { options = { ...Dialog.currentOptions, ...options }; return new Promise((resolve, reject) => { const context = options.context || getContext(); const dialog = context.selectComponent(options.selector); delete options.context; delete options.selector; if (dialog) { dialog.setData({ onCancel: reject, onConfirm: resolve, ...options }); queue.push(dialog); } else { console.warn('未找到 van-dialog 节点,请确认 selector 及 context 是否正确'); } }); };
**
函数式调用时候根据传入的options配置去更新找到的组件实例上的属性
由微信小程序自定义组件限制不能更新slot,slot需要用组件嵌套来传入
函数式调用中的options会有默认值强制覆盖掉van-dialog组件属性处传入的非id等其他属性,即函数调用的时通过组件传入的属性无效
**
Dialog.confirm
确认弹窗
调用方法
Dialog.confirm({ selector: '#van-dialog', title: '提示', message: '这里放置提示内容' })
实现方式
Dialog.confirm = options => Dialog({ showCancelButton: true, ...options });
调用Dialog时候默认执行定了显示取消按钮,其他无区别
Dialog.close
关闭弹窗
调用方法
Dialog.close()
实现方式
Dialog.close = () => { queue.forEach(dialog => { dialog.close(); }); queue = []; };
遍历内部缓存的所有调用Dialog方法找到的van-dialog组件实例,执行其close方法
Dialog.setDefaultOptions
更改对话框默认配置
调用方法
Dialog.setDefaultOptions(options)
实现方式
Object.assign(Dialog.currentOptions, options);
通过Object.assign将传入的默认配置合并到内部Dialog.currentOptions配置上
Dialog.resetDefaultOptions
恢复对话框默认配置
调用方法
Dialog.resetDefaultOptions()
实现方式
Dialog.resetDefaultOptions = () => { Dialog.currentOptions = { ...Dialog.defaultOptions }; };
恢复Dialog.currentOptions配置为Dialog.defaultOptions
总结