vue 异步数据呈现方案

demo 地址 源码地址

起因

当我领会到 写程序的重点在于处理好输入与输出之后 再来写一个搜索组件的时候我关于 loading 的思考如下

  • 什么时候显示 loading ?

    • 请求发起后还没有到达的这一段时间
  • 怎么控制视图在这段时间内显示 loading ?

    • 使用一个变量来控制
  • 那这个变量属于输入吗?

    • 不算,他是一个输出,这个搜索组件的输入只有一个: searchText
  • 这个输出的相关的 input、 transform 怎么样的?

    • input:searchText -> transform:异步请求 -> output:loading 状态
  • 怎么实现这样的一个 transform?

    • 这个 transform 需要立即的返回状态,没有状态页面上无法确定 loading 怎么显示

      • 想到了 promise to object
    • 这个 transform 需要持续的返回新状态。loading 一开始必然是显示,如果之后不返回新状态就没办法关闭了

      • 想到了 vue 的计算属性
      • 想到了事件机制
    • 这个 transform 还需要返回异步请求的结果。

      • object 中新增一个 data 字段用来放结果,还可以有一个 error 字段
    • 所以这个 transform 可以当 input 改变时返回一个 object 并且在 依据 input 发起的异步请求成功或者结束后修改之前返回的 object

然后就是在 vue 中实现这样的一个思路

应用的代码长啥样

/读书笔记/vue/vue异步数据呈现方案.html

demo 地址 源码地址

import { defineComponent, ref } from "vue";
import { usePromiseComputed } from "./lib/vue.composition.api";

export default defineComponent({
  setup(props, ctx) {
    const searchText = ref("");

    const searchResults = usePromiseComputed({
      defaultData: [] as string[],
      getter() {
        return searchApi(searchText.value);
      },
    });

    return { searchText, searchResults };
  },
}); 

这里的 usePromiseComputed 就是之前思考的 transform ,他返回了一个 ref(object) 然后当 searchText 发生变化时会重新执行查询请求 searchApi(searchText.value); , 当查询请求结束的时候他会修改之前返回的 ref(object)

在模板中

<template>
  <input placeholder="请输入你要搜索的关键字" v-model="searchText" />

  <div v-if="searchResults.pending">正在查询中</div>
  <div v-else-if="searchResults.rejected">
    查询失败
    {{ searchResults.error }}
  </div>
  <div v-else-if="searchResults.fulfilled">
    <div v-for="(item, index) in searchResults.data" :key="index">
      {{ item }}
    </div>
  </div>
  
</template> 

在这里可以看出来 usePromiseComputed 返回的结果其中的五个字段,三个状态字段也就是 前文中提到的控制loading的那个变量 两个 结果字段

总结

就上面的代码而言是一个极简 input -> tranform -> out 结构。这里不需要手动的声明一个状态变量,然后在不同的阶段在去修改这个变量,这样的操作封装在了 usePromiseComputed 里面。

关于 usePromiseComputed 的实现可以去这里查看 https://github.com/2234839/vue-demo/blob/master/src/components/promise-loading/lib/vue.composition.api.ts

实际上针对业务还加入了两个可选参数 deps 和 dataMergeFun

利用 deps 可以显式的声明哪些变量变化的时候重新请求

利用 dataMergeFun 可以非常简单的在上面的代码基础上加入请求结果翻页功能

by 崮生 from 崮生 • 一些随笔 🎨,欢迎 赞助本文o")
本文欢迎分享与聚合,全文转载未经授权( 联系我)不许可。

崮生
48 声望0 粉丝

怕什么真理无穷,进一寸一寸的欢喜