组件数据绑定文档 & 发现的一个bug
发布于 6 年前 作者 mingfeng 4607 次浏览 来自 问答

背景介绍

下面展示的截图是“图书详情”页,点击“相关图书”中的图片之后,还会跳转到这个页面,只是参数不同。

点击右下角“借阅此书”,会弹出一个 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.4s 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 的值没有变,那为什么子组件还会响应更新?这个逻辑到底是什么?双向绑定还是各自的作用域?

回到顶部