写在前面
- 记录基于微信小程序-气泡框实现中产生的问题及思考
问题截图
问题描述
问题解决过程记录
定位问题发生的原因范围
- 样式
- 样式在判断显示条件(wx:if=”“)生效后,仍然渲染
- 否定原因
- 查询代码发现,整个样式背景的设定是在::before伪元素选择器中
- 且显示条件生效,在调试器中已没有该元素,但仍显示
- 逻辑
- 会不会是组件在渲染时,多渲染一份,我们使用判断条件进行开关时,只是对其中一个进行了操作
- 怀疑依据
- 上图可见:在popover组件下,有2个通过<slot>插入的相同内容
- 样式
开始解决问题
- 查询官方关于slot方面的介绍
- 基于官方基础代码,复现问题
- 产生一个child-tag组件,并在其中编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// components/child-tag.js.js
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
/**
* 组件的属性列表
*/
properties: {
},
relations: {
'./component-tag-name': {
type: 'parent',
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
}) - 与component-tag-name绑定形成父子组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30// components/component-tag-name.js
Component({
options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
},
relations: {
'./child-tag': {
type: 'child',
}
},
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
visible: false
},
/**
* 组件的方法列表
*/
methods: {
}
}) - 并将index.html中进行调用
1
2
3
4
5
6
7
8
9
10
11
12<!-- 引用组件的页面模版 -->
<view>
<button type="primary" bindtap="onTap">222</button>
<my-component id="component">
<view slot="content">
这里是插入到组件slot name="content"中的内容
<child-component>
<view slot="child">这里是插入到组件slot name="child"中的内容</view>
</child-component>
</view>
</my-component>
</view> - 但是其结构树仍然非常正常,并没有出现那个所谓的”拷贝”组件
- 仔细复现了几次,发现:多出来的那个组件会有所延迟。抓住这个问题,想到我们在onReady中,注册了该组件,于是,继续模拟
- 修改index.js代码,并在component-tag-name组件注册onTap方法,控制显隐
1
2
3
4
5
6
7
8
9
10onReady() {
this.component = this.selectComponent('#component')
},
onTap() {
console.log('onTap')
wx.createSelectorQuery().select('#component').boundingClientRect(res => {
// 调用自定义组件 popover 中的 onDisplay 方法
this.component.onTap();
}).exec();
} - 最终复现
- 产生一个child-tag组件,并在其中编写
- 得出问题来源:
- 在组件中进行了一次setData
- 思考背后问题
- 在组件中setData为什么会”拷贝“一份相同的在页面级wxml中?
- 猜想一:从WXS响应事件中,我隐隐得到了答案
- 我们在页面级通过selectComponent实例化组件,对选中的组件进行操作,官方可以通过拷贝一份相同的组件,使我们便捷的将事件的处理从2次的逻辑层和渲染层通信以及一次渲染,减少到直接对页面上元素进行操作,即一次逻辑层和渲染层通信以及一次渲染。
- 猜想二:问题层面是在微信开发者工具中的wxml,渲染方式对于这种情况就是这样处理的。
- 查询官方关于slot方面的介绍
官方已给出问题原因
如何解决问题
- 在popover以及popover-item加入
1
2
3options: {
multipleSlots: true // 在组件定义时的选项中启用多slot支持
}, - 就可以解决了。最后建议slot中可以写上name这样代码可能会更易读。
写在后面
- 祝大家多多发财