大家好,都吃晚饭了吗?我是Kaiqisan,是一个已经走出社恐的一般生徒,这个话题之前也讲过了,不过这次是要在小程序里面实现,这个模块的功能在小程序中出现得比较多,所以就在之前也用过一次,
它终归还是和web端有点不同,不过还好它并不太复杂。
(web端实现方法详见我的这篇博客-----------> 给个链接)
现在我们写好了这个页面
我们需要点击灰色的页面触发某事件,而点击白色区域不会(很多小程序内部的通知弹窗啥的都是这样的,点击弹窗以外的地方就可以实现弹窗的关闭)
html代码部分
<View className='main'>
<View className='inner' id='app'>
<View className='inner2'>add</View>
<Text>ddd</Text>
</View>
</View>
- 下一步,我们开始绑定点击事件
{/* main是主节点,长宽都是屏幕尺寸 */}
<View className='main' onClick={this.cancel.bind(this)}>
<View className='inner'>
<View className='inner2'>add</View>
<Text>ddd</Text>
</View>
</View>
切记绑定事件一定要绑定到外部的元素上(因为这个事件监测是全屏监测)
- 在书写事件之前要说明一件事情,在小程序的获取事件中,并不会获取当前事件所指向的DOM元素(target)以及其事件的冒泡顺序(path),而是只会获取当前触发事件的元素的id,所以在监听之前,我们需要获取外层元素内部的所有的节点id(内部很多子节点,它们各有自己的id,如果只是获取一个外层的id,整个监测的设计是不彻底的,容易导致不好的用户体验)
所以我们需要遍历这颗节点子树(我们这里使用了递归)
// ts版
searchId(currentNode): void {
let nowList: string[] = this.state.idList;
nowList.push(currentNode.uid);
this.setState({ // 修改idList ,如果您使用vue的话就直接修改this.idList即可
idList: nowList
});
if (currentNode.childNodes.length) {
for (let i = 0; i < currentNode.childNodes.length; i++) {
this.searchId(currentNode.childNodes[i])
}
}
}
// js版
searchId(currentNode) {
let nowList = this.state.idList;
nowList.push(currentNode.uid);
this.setState({ // 修改idList ,如果您使用vue的话就直接修改this.idList即可
idList: nowList
});
if (currentNode.childNodes.length) {
for (let i = 0; i < currentNode.childNodes.length; i++) {
this.searchId(currentNode.childNodes[i])
}
}
}
现在,我们所有的id信息都储存在 idList当中去了
图中为小程序默认给的id,如果您自己命名了某节点id,就不会再采用默认id
然后剩下的判断步骤就和web端的一模一样了
// ts版
cancel(e: TaroEvent<any>) {
// vue直接书写this.idList
if (!this.state.idList.includes(e.target.id)) {
console.log('ok'); // 里面执行符合条件的方法,最常见的就是关闭小窗口
}
}
// js版
cancel(e) {
// vue直接书写this.idList
if (!this.state.idList.includes(e.target.id)) {
console.log('ok'); // 里面执行符合条件的方法,最常见的就是关闭小窗口
}
}
最终实现效果
总结
本篇文章基于taro+react+ts,如果您不是使用上面的框架(或语言或打包工具)请麻烦您稍微切换一下!