zoukankan      html  css  js  c++  java
  • 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: 惰性求值

    北栀女孩儿
  • 相关阅读:
    .net在list列表中查询指定的几条
    【JSP】JSP 标准标签库(JSTL)
    【UI】-LigerUI
    【MySQL】MySQL优化
    【微信小程序】menu
    【微信小程序】login
    【插件】PageHelper实现分页
    《学习javascript数据结构与算法》——第四章:队列
    《学习javascript数据结构与算法》——第三章:栈
    《学习javascript数据结构与算法》——第二章:数组
  • 原文地址:https://www.cnblogs.com/wxh0929/p/15437249.html
Copyright © 2011-2022 走看看