微信小程序-氣泡框 Popover

寫在前面


問題截圖

popover問題截圖

問題描述

  • 模擬器顯示正常,但在真機上點擊後,氣泡框的箭頭並沒有消失,且點擊同一級別區域,能利用覆蓋消除箭頭。【是不是一個很可愛的bug?

問題解決過程記錄

  • 定位問題發生的原因範圍

    • 樣式
      • 樣式在判斷顯示條件(wx:if="{{visible}}")生效後,仍然渲染
      • 否定原因
        • 查詢代碼發現,整個樣式背景的設定是在::before僞元素選擇器中
        • 且顯示條件生效,在調試器中已沒有該元素,但仍顯示
    • 邏輯
      • 會不會是組件在渲染時,多渲染一份,我們使用判斷條件進行開關時,只是對其中一個進行了操作
      • 懷疑依據
        • popover問題依據截圖
        • 上圖可見:在popover組件下,有2個通過<slot>插入的相同內容
  • 開始解決問題

    • 查詢官方關於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>
        
      • 但是其結構樹仍然非常正常,並沒有出現那個所謂的"拷貝"組件
        • 改寫v1.1後的結構樹截圖
        • 仔細復現了幾次,發現:多出來的那個組件會有所延遲。抓住這個問題,想到我們在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();
          }
        	```
        
      • 最終復現
        • 官方模擬最終運行截圖
    • 得出問題來源:
      • 在組件中進行了一次setData
    • 思考背後問題
      • 在組件中setData爲什麼會”拷貝“一份相同的在頁面級wxml中?
      • 猜想一:從WXS響應事件中,我隱隱得到了答案
      • wxs相應事件
      • 我們在頁面級通過selectComponent實例化組件,對選中的組件進行操作,官方可以通過拷貝一份相同的組件,使我們便捷的將事件的處理從2次的邏輯層和渲染層通信以及一次渲染,減少到直接對頁面上元素進行操作,即一次邏輯層和渲染層通信以及一次渲染。
      • 猜想二:問題層面是在微信開發者工具中的wxml,渲染方式對於這種情況就是這樣處理的。
  • 官方已給出問題原因

    • wxml面板

如何解決問題

  • 在popover以及popover-item加入
    options: {
    		    multipleSlots: true // 在組件定義時的選項中啓用多slot支持
    		  },
    
  • 就可以解決了。最後建議slot中可以寫上name這樣代碼可能會更易讀。

寫在後面

  • 祝大家多多發財

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章