寫在前面
- 記錄基於微信小程序-氣泡框實現中產生的問題及思考
問題截圖
問題描述
- 模擬器顯示正常,但在真機上點擊後,氣泡框的箭頭並沒有消失,且點擊同一級別區域,能利用覆蓋消除箭頭。【是不是一個很可愛的bug?
問題解決過程記錄
-
定位問題發生的原因範圍
- 樣式
- 樣式在判斷顯示條件(wx:if="{{visible}}")生效後,仍然渲染
- 否定原因
- 查詢代碼發現,整個樣式背景的設定是在::before僞元素選擇器中
- 且顯示條件生效,在調試器中已沒有該元素,但仍顯示
- 邏輯
- 會不會是組件在渲染時,多渲染一份,我們使用判斷條件進行開關時,只是對其中一個進行了操作
- 懷疑依據
- 上圖可見:在popover組件下,有2個通過<slot>插入的相同內容
- 樣式
-
開始解決問題
- 查詢官方關於slot方面的介紹
- 基於官方基礎代碼,復現問題
- 產生一個child-tag組件,並在其中編寫
// components/child-tag.js.js Component({ options: { multipleSlots: true // 在組件定義時的選項中啓用多slot支持 }, /** * 組件的屬性列表 */ properties: { }, relations: { './component-tag-name': { type: 'parent', } }, /** * 組件的初始數據 */ data: { }, /** * 組件的方法列表 */ methods: { } })
- 與component-tag-name綁定形成父子組件
// components/component-tag-name.js Component({ options: { multipleSlots: true // 在組件定義時的選項中啓用多slot支持 }, relations: { './child-tag': { type: 'child', } }, /** * 組件的屬性列表 */ properties: { }, /** * 組件的初始數據 */ data: { visible: false }, /** * 組件的方法列表 */ methods: { } })
- 並將index.html中進行調用
<!-- 引用組件的頁面模版 --> <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方法,控制顯隱
onReady() { 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加入
options: { multipleSlots: true // 在組件定義時的選項中啓用多slot支持 },
- 就可以解決了。最後建議slot中可以寫上name這樣代碼可能會更易讀。
寫在後面
- 祝大家多多發財