背景介绍
下面展示的截图是“图书详情”页,点击“相关图书”中的图片之后,还会跳转到这个页面,只是参数不同。
点击右下角“借阅此书”,会弹出一个 popup 组件,该组件的显示与否,由组件内部的 “show” 属性控制。
预期表现
进入“图书详情”页面后,点击“借阅此书”,显示 popup;跳转到下一个“图书详情”页后再返回当前页,popup 仍可正常显示。
Bug情况
在每一次进入“图书详情”页后,popup 都正常显示。
正常情况下,"show”为true时,应该显示popup( console 中的打印内容为 selecteComponent 获取到的该 popup 组件的引用):
但是当点击“相关图书”中的图书链接之后跳转到新的页面再返回,popup 不再显示,即使此时该组件的“show”属性值为true:
复现路径
点击“相关图书”中的图书链接之后跳转到新的页面,再返回,再点击“借阅此书”,popup 不再显示
最简复现Demo
/components/panel/index.wxml
< view class = "popup {{ show ? 'popup--show' : '' }}" > < view class = "popup__mask" bindtap = "onTapMask" /> < view class = "popup__container" > < slot ></ slot > </ view > </ view > |
/components/panel/index.wxss:
.popup__mask { position : fixed ; top : 0 ; left : 0 ; right : 0 ; bottom : 0 ; z-index : 10 ; background : rgba( 0 , 0 , 0 , 0.7 ); display : none ; } .popup__container { position : fixed ; bottom : 0 ; width : 100% ; /* width: 100vw; */ background : white ; transform: translateY( 150% ); transition: all 0.4 s ease; z-index : 11 ; } .popup-- show .popup__container { transform: translateY( 0 ); } .popup-- show .popup__mask { display : block ; } |
/components/panel/index.js:
/** * 底部弹出菜单 */ Component({ properties: { // 点击背景是否自动关闭,默认是 tappableMask: { type: Boolean, value: true } }, data: { show: false }, methods: { show: function () { this .setData({ show: true }) }, close: function () { this .setData({ show: false }) }, onTapMask: function () { if ( this .data.tappableMask) { this .close() } } } }) |
/pages/book-detail/index.wxml:
< button type = "primary" bindtap = "onShowPopup" >借阅此书</ button > < popup id = "popup" > 内容 </ popup > |
/pages/book-detail/index.js:
onShowPopup: function () { var popup = this .selectComponent( "#popup" ) console.log(popup) popup.show() }, |
我的解决办法
将“show”作为组件的属性,由父组件控制:
/components/panel/index.js:
/** * 底部弹出菜单 */ Component({ properties: { // 点击背景是否自动关闭,默认是 tappableMask: { type: Boolean, value: true }, show: { type: Boolean, value: false } }, methods: { close: function () { this .setData({ show: false }) }, onTapMask: function () { if ( this .data.tappableMask) { this .close() } } } }) |
/pages/book-detail/index.wxml:
< button type = "primary" bindtap = "onShowPopup" >借阅此书</ button > < popup id = "popup" show = "{{isPopupShow}}" > 内容 </ popup > |
/pages/book-detail/index.js:
Page({ data: { isPopupShow: false } onShowPopup: function () { this .setData({isPopupShow: true }) } }) |
但是会造成一个问题,就是在从新的图书详情页返回后,AppData窗口失效:
以上是我遇到的一个 bug,感谢解答。
另一个问题:组件的数据绑定的逻辑
当组件的属性是父组件的data中的一个属性时,组件properties中的这个属性,和父组件data中的那个属性的关系是什么?以下是困扰我的现象:
在上面我提供的解决方案中,子组件 popup 将 show 通过 setData 设为 false 时,父组件中的 isPopupShow 依然为 true,但此时 popup 组件不显示; 当父组件的 isPopupShow 为 true 时,再次在父组件中通过 setData 将 isPopupShow 设为 true(也就是说这个属性的值没有变),popup组件依然会显示。
在第二个情况里,既然 isPopupShow 的值没有变,那为什么子组件还会响应更新?这个逻辑到底是什么?双向绑定还是各自的作用域?