• 作者:老汪软件技巧
  • 发表时间:2024-10-30 11:02
  • 浏览量:

vue@3.3.4 + antdv@3.2.20

一晃几个月没写文章了,每天忙于刷(mō)题(yú),今天突然来了灵感,便来水一篇。

使用select组件,异步获取options列表并对回填数据进行映射时,你一定碰到过这样的情况:


export default {
    setup() {
        const value = ref("SHANGHAI");
        const list = ref([]);
        // 模拟异步
        setTimeout(() => {
          list.value.push({
            label: "上海",
            value: "SHANGHAI",
          });
        }, 2000);
        
        return { value, list }
    }
}

要想解决拿到list之前的闪烁,第一反应大概率是:异步获取到options后再回填select的value。

但又面临着一个新的问题:如果碰巧有另一个异步操作中使用到了select的value,那就面临着取不到的风险。(同步更不用说)


export default {
    setup() {
        const value = ref(undefined);
        const list = ref([]);
        setTimeout(() => {
          console.log("another value is: ", value.value);
        }, 1000);
        setTimeout(() => {
          list.value.push({
            label: "上海",
            value: "SHANGHAI",
          });
          value.value = "SHANGHAI";
          console.log("value is: ", value.value);
        }, 2000);
        
        return { value, list }
    }
}

当然这也不是什么大问题,不管是hack还是从业务逻辑的角度,总能找到解决办法,但本着用正确的方法做事的态度,借助一位登场率不怎么高的朋友——Suspense提供的帮助,来看一种新思路。

众所周知, antdv的select组件提供了一个optionLabel插槽,也就是select选中了某个值后,显示label的那个文本。

为这个插槽提供一个组件:

// comp.vue

<script>
export default {
  name: "comp",
  props: {
    options: {
      type: Object,
      default: () => [],
    },
    data: {
      type: String,
    },
  },
};
script>

使用异步组件桥接上边这个comp.vue

// asyncComponent.js
import { defineAsyncComponent } from "vue";
const asyncComponent = defineAsyncComponent(async () => {
  // 可以将异步获取options的逻辑放在这里,通过store连接起来
  // 这里为了方便,就模拟一个时间相同的setTimeout
  await new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, 2000);
  });
  return import("./comp.vue");
});
export default asyncComponent;

最后,就是修改select的使用方式


<script>
import asyncComponent from "./asyncComponent";
export default {
    components: { asyncComponent },
    setup() {
        const value = ref("SHANGHAI");
        const list = ref([]);
        
        console.log("value is: ", value.value);
        // 模拟异步
        setTimeout(() => {
          list.value.push({
            label: "上海",
            value: "SHANGHAI",
          });
        }, 2000);
        
        return { value, list }
    }
}
script>

效果如下:加载中...可以换成任何你需要的、合适的内容

既不影响同步操作select值,也没有异步获取options时,真实value闪烁的现象。

使用场景:异步获取options、信息脱敏、国际化翻译等。

这里只是一个思路,可玩性还很大。

优势:

select的文本区域单独抽象成组件利于业务扩展,毕竟labelInValue总有无法满足业务需求的时候;同时也方便处理异步操作中的异常。没有魔改业务逻辑。符合严格贯彻视图与数据分离的MVVM架构项目。处理流程更符合人类认知。为什么这么说,设想一下:

假如你是一个大专前端,名叫小帅,辛勤刷题3个月,终得面试通过拿了大厂offer

某日,你前去办理入职,在楼下费了老鼻子劲才让保安相信你不是要混进去推销信用卡,终于乘电梯来到邮件里约定的楼层

甜美的前台小姐姐:您好~

你:您好,我来办理入职

无用的知识增加了__无用的知识点又增加了

甜美的前台小姐姐:请问联系您的HR是?

你:小A

小姐姐拿起电话联系HR小A,没多大会便放下了电话:抱歉,请您在那边会议室稍等片刻,小A外出公办,马上就回来了~

此时你有三个选项:

反客为主去楼下等去会议室等选项1结局

你:没关系,你们的前端同事们坐在哪里,我先去干活,等小A回来再给我办就行

说罢,便自顾自的走了进去

甜美的前台小姐姐:???

你狗狗祟祟的转了好几圈,终于找到了藏在厕所门口那片不起眼区域里的前端同学们,也不见外,直接坐在了不知是谁的工位上,熟练的打开vscode、百度、chatgpt三件套,劈里啪啦的操作了起来

众前端:你谁?保安??保安??

剧终。

第二天,你又打开了熟悉的豹斯某聘,开始了日复一日已读不回的生活。

选项2结局

你:没关系,我去楼下等小A,等会我们一起上来

说罢,转身离去。毕竟,高手从不回头看爆炸

甜美的前台小姐姐:诶?啊这。。。

话分两头讲,地铁某号线上

HR小A:歪?我亲爱的小B,坏事了救命,我约了个叫小帅的前端今天来办理入职,时间来不及了我赶不回去,你帮我接一下呗?

电话那头的HR小B:霸某茶姬

小A:成交

小B来到前台:咦,没人啊。咦,前台怎么也不在。啊,一定是小A被鸽了

小B:恍恍惚惚哈哈哈哈你被鸽了,姬不能免

小A:行叭,没事我还有个备选的叫大壮,我联系他叭

剧终。

第二天,你又打开了熟悉的豹斯某聘,开始了日复一日已读不回的生活。

选项3结局

这还有啥好说的啊,正常人不都该这么办嘛?

至于后续,那当然是苦卷数载,终得年薪百万,然后出任CEO,迎娶白富美,走向人生巅峰啊~