vant的picker組件數據更新時視圖卻沒有更新???


1、背景

最近項目有個需求,需要使用vant的picker選擇器,並且搭配彈出層使用,並且picker的數據是異步獲取的,但是在測試的過程中,數據已經正確獲取到,頁面也實現了響應式,但是picker選擇器的數據卻沒有更新,這是為什么呢???

  • 代碼:
    • html
      <van-popup position="bottom" v-model:show="showPicker">
            <!-- 
              loading:是否顯示加載狀態,默認為false
              columns:對象數組,配置每一列顯示的數據
              value-key已經棄用,所以需要columns-field-names自定義 Columns 的結構
              show-toolbar:是否顯示頂部欄,默認為true
              confirm:點擊完成按鈕時觸發
              cancel:點擊取消按鈕時觸發
             -->
            {{ sourceData }}
            <van-picker
              default-index="0"
              :loading="loading"
              :columns="sourceData"
              :columns-field-names="customFieldName"
              show-toolbar
              @confirm="onConfirm"
              @cancel="onCancel"
            />
          </van-popup>
    • js:
      let res = await initSelectData({
            data: {},
            method: 'GET',
            url: codeId
      });
      // sourceData = res.data; //直接賦值丟失了響應性
      res.data
          ? res.data.forEach(el => {
              sourceData.push(el);
             })
          : '';
  • 加載數據的現象:

         

  • 加載數據成功后的現象:

           

2、分析

官網地址:https://vant-contrib.gitee.io/vant/v3/#/zh-CN/picker

剛開始的時候我認為是vue的響應式數據問題引起的,后來在popup中打印了數據源sourceData之后,發現頁面的數據已經響應式更新了,但是picker中的下拉選項數據卻並沒有發生變化,所以接下來我查閱了一下vant-picker的官方文檔,發現picker實例上有一個方法 setColumnValues 可以設置對應列中所有的選項,所以我給picker設置了一個ref

  •  html
    <van-picker
            default-index="0"
            ref="picker"
            :loading="loading"
            :columns="sourceData"
            :columns-field-names="customFieldName"
            show-toolbar
            @confirm="onConfirm"
            @cancel="onCancel"
          />
  • js
    /**
         * @description: onMounted 可以用來加載頁面的初始化數據
         * @author: wangxinghua1
         */
        onMounted(async () => {
          console.log(picker.value, '.....');
        });
  • 問題:在onMounted中的結果為:null '.....'。  這就導致頁面加載選擇器數據的時候,沒有辦法獲取到實例,而導致調用 setColumnValues 報錯,這是因為popup彈層在打開前並沒有提前渲染到頁面上(dom加載時並沒加載popup),所以導致ref獲取不到它里面的picker選擇器,解決方法:
    <van-popup
      :lazy-render="false"
    /> 
  • 最終結果是
    • html
      <!-- 
            lazy-render:是否在顯示彈層時才渲染節點,默認為true,防止popup彈出層
                        在打開前並沒有提前渲染到頁面上(dom加載時並沒加載popup),
                        所以導致ref獲取不到它里面的picker選擇器(picker.value),
                        從而使得picker.value.setColumnValues報錯
           -->
          <van-popup :lazy-render="false" position="bottom" v-model:show="showPicker">
            <!-- 
              loading:是否顯示加載狀態,默認為false
              columns:對象數組,配置每一列顯示的數據
              value-key已經棄用,所以需要columns-field-names自定義 Columns 的結構
              show-toolbar:是否顯示頂部欄,默認為true
              confirm:點擊完成按鈕時觸發
              cancel:點擊取消按鈕時觸發
             -->
            {{ sourceData }}
            <van-picker
              default-index="0"
              ref="picker"
              :loading="loading"
              :columns="sourceData"
              :columns-field-names="customFieldName"
              show-toolbar
              @confirm="onConfirm"
              @cancel="onCancel"
            />
          </van-popup>

       

    • js
      // 定義是否顯示彈出層
          let showPicker = ref(false);
      
          // 定義選擇器的數據
          let sourceData = reactive([]);
      
          // 選擇器數據是異步獲取的,可以通過 loading 屬性顯示加載提示
          let loading = ref(false);
      
          // 獲取picher的dom節點,即picker的實例
          let picker = ref(null);
      
          /**
           * @description: onMounted 可以用來加載頁面的初始化數據
           * @author: wangxinghua1
           */
          onMounted(async () => {
            // 當選擇器的數據來源於后端時,判斷是否有請求地址,進行初始化數據
            if (codeId) {
              loading.value = true;
              await loadData();
            }
          });
      
          /**
           * @description: loadData  獲取select的數據
           * @author: wangxinghua1
           */
          const loadData = async () => {
            try {
              let res = await initSelectData({
                data: {},
                method: 'GET',
                url: codeId
              });
              // sourceData = res.data; //直接賦值丟失了響應性
              res.data
                ? res.data.forEach(el => {
                    sourceData.push(el);
                  })
                : '';
              res.data ? (loading.value = false) : (loading.value = false);
              console.log('9999999', picker.value);
              picker.value.setColumnValues(0, sourceData);
              console.log('initSelectData', res, sourceData);
            } catch (e) {
              console.log('select-loaddata', e.errmsg);
            }
          };

       

3、vue3使用ref的步驟

  1. 給元素添加ref屬性<div ref="box"></div>
  2. 在setup函數中,可以使用ref函數,用於創建一個響應式數據const box = ref(null)
  3. 在setup函數中,使用return返回box數據
  4. 在onMounted函數里面訪問

 

 

 

 

 

 

 

 

lazy   [ˈleɪzi]   詳細 X
基本翻譯
adj. 懶惰的;懶洋洋的;怠惰的;慢吞吞的
n. (Lazy)人名;(德)拉齊
網絡釋義
lazy: 懶惰的
Lazy Susan: 餐桌轉盤
Lazy evaluation: 惰性求值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM