89 lines
2.0 KiB
TypeScript
89 lines
2.0 KiB
TypeScript
/** 成员数据项 */
|
||
interface SelectMemberItem {
|
||
/** 唯一标识 */
|
||
id: string
|
||
/** 姓名 */
|
||
name: string
|
||
/** 性别 */
|
||
gender: '男' | '女'
|
||
/** 年龄 */
|
||
age: number
|
||
/** 身高(cm) */
|
||
height: number
|
||
/** 头像 URL,无则显示彩色占位圆 */
|
||
avatar?: string
|
||
/** 是否已选中 */
|
||
selected?: boolean
|
||
}
|
||
|
||
/**
|
||
* 选择已有成员抽屉组件
|
||
* Properties: show(控制显示), members(成员列表)
|
||
* Events: close(关闭), select(选中成员,携带 SelectMemberItem)
|
||
*/
|
||
Component({
|
||
properties: {
|
||
/** 是否显示抽屉 */
|
||
show: {
|
||
type: Boolean,
|
||
value: false
|
||
},
|
||
/** 成员列表 */
|
||
members: {
|
||
type: Array,
|
||
value: [] as SelectMemberItem[]
|
||
}
|
||
},
|
||
|
||
data: {
|
||
/** 控制 wx:if,DOM 是否存在 */
|
||
innerShow: false,
|
||
/** 控制 --visible 类,触发 CSS transition */
|
||
animVisible: false
|
||
},
|
||
|
||
observers: {
|
||
/**
|
||
* 监听外部 show 变化,错开两帧:
|
||
* 打开:先插入 DOM,下一帧加动画类
|
||
* 关闭:先移除动画类,等 transition 结束再移除 DOM
|
||
*/
|
||
show(val: boolean) {
|
||
if (val) {
|
||
this.setData({ innerShow: true })
|
||
// 延迟一帧,让 DOM 先以初始状态渲染,再触发 transition
|
||
setTimeout(() => {
|
||
this.setData({ animVisible: true })
|
||
}, 20)
|
||
} else {
|
||
this.setData({ animVisible: false })
|
||
// 等 CSS transition 结束(0.3s)再移除 DOM
|
||
setTimeout(() => {
|
||
this.setData({ innerShow: false })
|
||
}, 300)
|
||
}
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
/** 点击遮罩关闭 */
|
||
onTapMask() {
|
||
this.triggerEvent('close')
|
||
},
|
||
|
||
/** 点击关闭按钮 */
|
||
onTapClose() {
|
||
this.triggerEvent('close')
|
||
},
|
||
|
||
/**
|
||
* 点击成员行,触发 select 事件
|
||
* @param e 携带 data-member 的点击事件
|
||
*/
|
||
onTapMember(e: WechatMiniprogram.TouchEvent) {
|
||
const member = e.currentTarget.dataset.member as SelectMemberItem
|
||
this.triggerEvent('select', member)
|
||
}
|
||
}
|
||
})
|