Skip to content

药品订单与云函数(三) ​

本页对应 药品订单与云函数,共 7 段视频,约 56 分钟。

学习目标 ​

  1. 能根据问诊订单状态使用 v-if 渲染对应的操作按钮和状态文案,并说明不同状态下可执行操作的原因。
  2. 能使用 uni-app 加载更多组件,动态绑定 status 控制 more、loading、no-more 提示,并在请求前后正确切换状态。
  3. 能实现问诊列表分页请求:监听滚动到底部、页码递增、根据总页数更新 hasMore,并在无更多数据时阻止继续请求。
  4. 能封装并使用防抖函数,说明 debounce 返回的是防抖函数,并在滚动请求场景中验证可避免重复请求。
  5. 能实现下拉刷新:监听刷新事件、重置页码和列表数据、请求第一页,并在请求结束后关闭刷新动画。
  6. 能说明云开发中云函数、云数据库、云存储的作用,并使用 uniCloud.callFunction 调用云函数、传递参数和获取返回值。

知识点 ​

本节笔记未附图片,以下按转写稿保留关键代码片段,不补造完整源码。

订单状态决定按钮和文案 ​

为什么需要: 问诊订单状态不同,用户能执行的操作也不同。比如“咨询中”不能再取消,也不该继续支付;“已取消”也没必要再次取消。按钮如果写死,就会出现业务上不允许的操作。

怎么想: 先把状态和操作列成对应关系:待支付可取消/支付,待接诊可取消等,咨询中展示继续咨询。页面渲染时按状态分支,而不是机械复制按钮。

怎么做: 用 v-if 按状态值渲染不同按钮,文案也按状态切换。转写稿中的“V杠if”即 v-if:

html
<button v-if="status === 1">取消</button>
<button v-if="status === 1">去支付</button>
<!-- 其他状态同样按状态分支渲染对应按钮 -->

易错点: 不要只抄按钮结构而忽略状态含义;状态值和按钮数量要跟业务表格一致,避免“咨询中还能取消”这类错误。

加载更多组件的 status ​

为什么需要: 列表分页时,用户需要知道当前是“加载中”“还有更多”还是“没有更多”。uni-app 的 uni-load-more 组件正好提供这类提示。

怎么想: 组件第一次使用,先认识 status 的三个取值:more 表示还有更多,loading 表示正在加载,noMore 表示没有更多。初始应为 loading,因为页面一刷新就发请求。

怎么做:

html
<uni-load-more :status="loadMoreStatus" />
js
const loadMoreStatus = ref('loading')
// 请求开始
loadMoreStatus.value = 'loading'
// 请求结束,再根据 hasMore 判断
loadMoreStatus.value = hasMore.value ? 'more' : 'noMore'

转写稿中先固定写成“没有更多”只是为了认识组件,后续必须改成动态判断。

易错点: 不要把 status 写死;请求开始要变 loading,请求结束要按 hasMore 切到 more 或 noMore。

分页请求与 hasMore 判断 ​

为什么需要: 滚动到底部要请求下一页,否则列表只有第一页;同时不能无休止请求,必须判断是否还有数据。

怎么想: 三个条件:监听滚动到底部;每次请求后页码加一;用“下一次要请求的页码”和总页数比较,得出 hasMore。

怎么做: 滚动到底部事件触发请求;请求结束后:

js
currentPage.value++
hasMore.value = currentPage.value <= totalPage.value
loadMoreStatus.value = hasMore.value ? 'more' : 'noMore'

只有 hasMore 为 true 时才继续请求。

易错点: 页码不递增会导致重复请求第一页;不判断总页数会请求空页。转写稿调试时出现“页码重复”就是防抖和页码控制要一起处理。

防抖处理滚动请求 ​

为什么需要: 滚动到底部很容易连续触发多次请求,造成重复数据。防抖能把多次操作合并为最后一次执行。

怎么想: debounce 本身不是防抖函数,而是“创建防抖函数”的工具;它的返回值才是真正可调用的防抖函数。

怎么做:

js
import { debounce } from '@/utils/index.js'

const getOrderList = debounce(async () => {
  // 原来的分页请求逻辑
}, 300)

易错点: 不要误以为 debounce 就是防抖函数;必须接收它的返回值。异步请求中该加 async/await 的地方不能漏。

下拉刷新要重置页码和列表 ​

为什么需要: 用户下拉刷新时,应从第一页重新取数据,而不是接着旧页码继续追加。

怎么想: 刷新等于“回到初始状态”:页码重置为 1,列表清空,再请求第一页;请求结束后关闭下拉动画。

怎么做:

js
function onPullDownRefresh() {
  currentPage.value = 1
  orderList.value = []
  getOrderList()
}

页面级下拉刷新可在请求结束后调用 uni.stopPullDownRefresh();若用组件级刷新,则重置对应刷新状态变量。

易错点: 只重置页码不清空列表,会混入旧数据;忘记关闭动画,刷新图标会一直转。

云开发与云函数的基本认识 ​

为什么需要: 云函数可以理解为跑在云端的普通函数,作用类似后端接口;云数据库存数据,云存储存文件。

怎么想: 普通函数在本地客户端执行;云函数在服务器/云端执行。调用云函数就像调用后端接口,可传参、可拿返回值。

怎么做:

js
const res = await uniCloud.callFunction({
  name: 'uni-test',
  data: { name: '小明' }
})
console.log(res)

云函数里 return 的内容就是接口返回结果。

易错点: 有参数用 data 传,无参数可省略;结果从 res 取。不要把 uniCloud.callFunction 当成普通函数直接写函数名调用。

订单状态决定按钮渲染 ​

为什么需要:问诊订单状态不同,用户能执行的操作也不同。比如订单已在“咨询中”,再显示“取消”或“继续支付”就不合理;已取消的订单也不应再次显示“取消”。
怎么想:先把状态映射成操作,再用 v-if 按状态渲染按钮,而不是机械照抄。转写稿中明确:待支付可“取消/支付”,咨询中应“继续咨询”,其他状态按对应关系处理。
怎么做:在模板里按状态值切换按钮组;不同状态展示不同文字。
易错点:状态与按钮错配;所有状态都渲染同一组按钮;只改文字不改显示条件。

加载更多组件 ​

为什么需要:列表滚动加载时要告诉用户“正在加载”“还有更多”“没有更多”,否则用户不知道是否还能继续拉。
怎么想:使用 uni-app 扩展组件“加载更多”,核心是 status 三态:loading、more、noMore。页面初次刷新就会发请求,所以初始值应为 loading。
怎么做:

html
<uni-load-more :status="loadStatus" />
js
const loadStatus = ref('loading')

// 请求发出前
loadStatus.value = 'loading'
// 请求结束后,根据是否还有更多数据切换
loadStatus.value = hasMore.value ? 'more' : 'noMore'

转写稿的调试过程是:先固定写 loading、more、noMore 观察组件显示,再改成变量控制;请求结束先写死 noMore 熟悉组件,最后用 hasMore 判断。
易错点:把值写死;把 noMore 写成 no more;忘记请求前重置为 loading;未按官方方式引入扩展组件。

分页请求问诊列表 ​

为什么需要:列表数据多,不能一次全取;滚动到底部再请求下一页,体验更好。
怎么想:用 scroll-view 的 @scrolltolower 监听触底;每请求成功一次页码加一;用“下一次请求页码”和“总页数”比较,判断 hasMore。
怎么做:

html
<scroll-view scroll-y @scrolltolower="onScrollToLower">
  <!-- 列表 -->
</scroll-view>
js
const currentPage = ref(1)
const totalPage = ref(0)
const hasMore = ref(true)

async function onScrollToLower() {
  if (!hasMore.value) return
  await getOrderList()
}

// getOrderList 请求成功后
currentPage.value++
hasMore.value = currentPage.value <= totalPage.value

转写稿调试时观察到:页码从 1 变到 6,说明共 6 页;继续滚动时 hasMore 变为 false,此时不应再请求。
易错点:页码始终为 1 导致数据重复;没有判断 hasMore 仍继续请求;触底连续触发导致重复请求。

防抖处理 ​

为什么需要:滚动触底很容易一次发多个请求,需要把多次操作合并为最后一次执行。
怎么想:防抖是“多次操作只在最后一次执行”;节流是“固定时间段内执行一次”。这里适合防抖。注意 debounce 本身不是防抖函数,而是创建防抖函数的工具,返回值才是防抖函数。
怎么做:

js
export function debounce(fn, delay = 300) {
  let timer
  return function (...args) {
    clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}
js
const getOrderList = debounce(async () => {
  // 原请求逻辑
}, 300)

易错点:把 debounce(...) 的返回值丢掉;异步逻辑忘记 async/await;延迟过小仍可能重复请求。

下拉刷新 ​

为什么需要:用户下拉时希望重新从第一页取数据,并清空旧列表。
怎么想:刷新等于“页码重置为 1 + 列表清空 + 重新请求 + 关闭刷新动画”。
怎么做:

html
<scroll-view
  refresher-enabled
  :refresher-triggered="isRefreshing"
  @refresherrefresh="onRefresh"
>
js
const isRefreshing = ref(false)

async function onRefresh() {
  isRefreshing.value = true
  currentPage.value = 1
  orderList.value = []
  await getOrderList()
  isRefreshing.value = false
}

易错点:忘记重置页码;忘记清空列表;不加 await 导致动画提前关闭;属性名拼写错误。

云开发与云函数简介 ​

为什么需要:uni-app 项目可用 uniCloud 提供云函数、云数据库、云存储,云函数可理解为后端接口。
怎么想:云函数≈接口;云数据库≈数据库;云存储≈文件上传。调用云函数用 uniCloud.callFunction。
怎么做:

js
uniCloud.callFunction({
  name: 'uiTest',
  data: { name: '小明' }
}).then(res => {
  console.log(res.result)
})

易错点:云函数名写错;参数应放 data;返回结果在 res.result;云函数需在云开发控制台调试或上传后使用。

订单状态与按钮渲染:先判断“这个状态能不能点” ​

为什么需要:问诊订单在不同状态下,用户能做的操作不同。待支付时可以取消或支付;咨询中再显示“取消”“继续支付”就不合理;已取消再显示“取消”也没有意义。
怎么想:先梳理状态与操作的对应关系,再用 v-if 按状态渲染按钮,而不是把所有按钮都写死。
怎么做:例如:

html
<button v-if="orderStatus === 1">取消</button>
<button v-if="orderStatus === 1">去支付</button>
<button v-if="orderStatus === 3">继续咨询</button>

不同状态展示不同文字时,也用条件判断处理。
易错点:不要机械抄代码,要理解“状态不同,操作不同”;否则会出现咨询中还能取消、已取消还能再次取消等逻辑错误。

加载更多组件:让底部提示跟着请求状态走 ​

为什么需要:列表底部要提示“加载中”“上拉显示更多”“没有更多数据”,手写容易乱。
怎么想:使用 uni-app 扩展组件 uni-load-more,它的 status 有三个关键取值:loading、more、no-more。
怎么做:

html
<uni-load-more :status="loadStatus"></uni-load-more>

页面刷新后会立即请求数据,所以初始值设为 loading;每次发请求设为 loading,请求结束后根据 hasMore 设为 more 或 no-more。
易错点:不要把 status 写死成 no-more;也不要把“还有更多数据”和“没有更多数据”混用。

分页请求:滚动到底部才请求下一页 ​

为什么需要:列表数据多,不能一次全取;滚动到底部再请求更符合使用习惯。
怎么想:要解决三件事:怎么知道到底部、页码怎么变、还有没有下一页。
怎么做:监听页面滚动到底部事件 onReachBottom,触发请求:

js
onReachBottom() {
  if (!this.hasMore) return
  this.getOrderList()
}

请求成功后让页码加一,并判断是否还有更多:

js
this.currentPage++
this.hasMore = this.currentPage <= res.totalPage

易错点:页码不加一会一直请求第一页,数据重复;没有 hasMore 判断时,最后一页后还会继续发无效请求。

防抖处理:避免一次滚动发多次请求 ​

为什么需要:滚动到底部时容易连续触发多次请求,造成重复数据。
怎么想:这里适合用防抖:多次触发只在最后一次执行。注意防抖和节流不同:节流是某个时间段内只执行一次。
怎么做:把防抖封装到工具文件并导出,在页面中导入:

js
import { debounce } from '@/utils/index.js'

this.getOrderList = debounce(async () => {
  // 原分页请求逻辑
}, 300)

易错点:debounce 本身不是防抖函数,它返回的函数才是真正要调用的防抖函数;另外原请求里有 await,外层要写 async。

下拉刷新:重置页码和列表再请求 ​

为什么需要:用户下拉时希望从第一页重新加载最新数据。
怎么想:刷新不是简单再请求一次,而是要把页码恢复为 1,把列表清空,再请求第一页。
怎么做:监听下拉刷新事件,请求前打开刷新状态,请求结束后关闭:

js
async onRefresh() {
  this.isRefreshing = true
  this.currentPage = 1
  this.list = []
  await this.getOrderList()
  this.isRefreshing = false
}

易错点:不加 async/await,关闭动画可能先于请求结束执行;页码和列表不重置,会追加出重复数据。

云开发与云函数:把云函数当成后端接口 ​

为什么需要:云开发包含云函数、云数据库、云存储。云函数用于在云端执行逻辑,可以理解为“后端接口”。
怎么想:云函数本质仍是普通函数,只是运行在云端;调用时通过 uniCloud.callFunction。
怎么做:

js
const res = await uniCloud.callFunction({
  name: 'uni-test',
  data: { name: '小明' }
})
console.log(res.result)

易错点:转写稿里的“语音函数”应写“云函数”;云函数不是本地普通函数,不能直接写函数名调用;返回值从 res.result 取。

代码示例 ​

示例 1:问诊订单列表渲染(状态决定按钮 + 加载更多组件) ​

vue
<!-- components/order-list/order-list.vue -->
<template>
  <view class="order-list">
    <view class="order-item" v-for="item in orderList" :key="item.id">
      <view class="item-header">
        <text class="doctor">{{ item.doctorName }}</text>
        <!-- 状态不同,文字不同 -->
        <text class="status">{{ statusText[item.status] }}</text>
      </view>

      <view class="item-body">
        <text>就诊人:{{ item.patientName }}</text>
        <text>下单时间:{{ item.createTime }}</text>
      </view>

      <!-- 状态不同,可执行的操作也不同 -->
      <view class="item-footer" v-if="item.status === 1">
        <button size="mini" @click="onCancel(item)">取消问诊</button>
        <button size="mini" type="primary" @click="onPay(item)">去支付</button>
      </view>
      <view class="item-footer" v-else-if="item.status === 2">
        <button size="mini" @click="onCancel(item)">取消问诊</button>
        <button size="mini" type="primary" @click="onPay(item)">继续支付</button>
      </view>
      <!-- 咨询中:只有"继续咨询"一个按钮,不能取消、也不能再支付 -->
      <view class="item-footer" v-else-if="item.status === 3">
        <button size="mini" type="primary" @click="onChat(item)">继续咨询</button>
      </view>
      <!-- status === 4、5 按课上梳理的表格继续往下写 v-else-if 即可 -->
    </view>

    <!-- uni-app 扩展组件:加载更多 -->
    <uni-load-more :status="loadStatus" />
  </view>
</template>

<script setup>
import { ref } from 'vue'

const orderList = ref([])

// 订单状态 → 展示文字
const statusText = {
  1: '待支付',
  2: '待接诊',
  3: '咨询中',
  4: '已完成',
  5: '已取消'
}

// 加载更多组件的状态:loading / more / noMore
const loadStatus = ref('loading')

const onCancel = (item) => {}
const onPay = (item) => {}
const onChat = (item) => {}
</script>

<style>
.order-list { padding: 20rpx; }
.order-item {
  background: #fff;
  border-radius: 12rpx;
  padding: 24rpx;
  margin-bottom: 20rpx;
}
.item-header { display: flex; justify-content: space-between; }
.item-body { display: flex; flex-direction: column; margin: 16rpx 0; color: #666; }
.item-footer { display: flex; justify-content: flex-end; gap: 20rpx; }
</style>

关键行与易错点

  • v-if / v-else-if 判断的是 item.status,不是 全局状态,所以按钮写在 v-for 内部。
  • 状态 3(咨询中)只能有一个“继续咨询”按钮:订单已经在咨询中,说明已支付成功,再出现“取消”“继续支付”都是业务错误——这是最容易照抄抄错的地方。
  • uni-load-more 是扩展组件,属性叫 status,只有 loading / more / noMore 三个取值,分别对应“加载中”“上拉显示更多”“没有更多数据”。拼成 no more 是错的。
  • loadStatus 初始值给 'loading',因为页面一进来就发请求,此时就是加载中状态。

示例 2:分页请求 + 防抖(utils 封装 + 页面使用) ​

js
// utils/index.js

/**
 * 防抖:多次触发,只在最后一次执行
 * 注意:它本身不是防抖函数,而是"创建"防抖函数的工厂
 */
export const debounce = (fn, delay = 300) => {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * 节流:固定时间间隔内只执行一次
 */
export const throttle = (fn, delay = 300) => {
  let flag = true
  return function (...args) {
    if (!flag) return
    flag = false
    setTimeout(() => {
      flag = true
      fn.apply(this, args)
    }, delay)
  }
}
vue
<!-- components/order-list/order-list.vue -->
<template>
  <scroll-view class="order-list" scroll-y @scrolltolower="onScrollToLower">
    <view class="order-item" v-for="item in orderList" :key="item.id">
      <!-- 列表渲染同上,此处省略 -->
      <text>{{ item.doctorName }}</text>
    </view>

    <uni-load-more :status="loadStatus" />
  </scroll-view>
</template>

<script setup>
import { ref } from 'vue'
import { debounce } from '@/utils/index.js'

const orderList = ref([])
const loadStatus = ref('loading')
const currentPage = ref(1)   // 当前(下一次要请求的)页码
const totalPage = ref(1)     // 后端返回的总页数
const hasMore = ref(true)    // 是否还有更多数据

// debounce 的返回值才是真正的防抖函数
const getOrderList = debounce(async () => {
  loadStatus.value = 'loading'

  const res = await uni.request({
    url: 'https://example.com/api/order/list',
    data: { type: 2, page: currentPage.value, pageSize: 5 }
  })

  // 追加,不是覆盖
  orderList.value = [...orderList.value, ...res.data.list]

  // 请求结束后:页码加一
  currentPage.value++
  totalPage.value = res.data.pages
  // 用"下一次要请求的页码"和总页数比较
  hasMore.value = currentPage.value <= totalPage.value
  loadStatus.value = hasMore.value ? 'more' : 'noMore'
}, 300)

// 滚动到底部
const onScrollToLower = () => {
  if (!hasMore.value) return
  getOrderList()
}
</script>

<style>
.order-list { height: 100vh; }
.order-item { padding: 24rpx; border-bottom: 1rpx solid #eee; }
</style>

关键行与易错点

  • debounce 是创建防抖函数的工厂,const getOrderList = debounce(fn, 300) 里 getOrderList 才是防抖函数,直接调用 debounce(...) 是没有意义的。
  • 分页三件套缺一不可:① 监听滚动到底部(@scrolltolower)② 请求结束后 currentPage++ ③ 用 currentPage <= totalPage 判断 hasMore。漏掉第②步会出现“每页都是第 1 页、数据重复”的现象。
  • orderList.value = [...orderList.value, ...list] 是追加;如果写成 = 直接赋值就变成覆盖,永远只有一页数据。
  • hasMore 为 false 时要在 onScrollToLower 里直接 return,否则会继续发无用请求(已经到底了还请求)。
  • scroll-view 必须给固定高度(如 height: 100vh)才能真正滚动,否则 scrolltolower 永远不触发。
  • 不做防抖时,一次快速滑动会连续触发多次请求,出现“页码 4、4、5……”这种重复请求。

示例 3:下拉刷新(重置页码 + 清空列表 + 关闭动画) ​

vue
<!-- components/order-list/order-list.vue -->
<template>
  <scroll-view
    class="order-list"
    scroll-y
    :refresher-enabled="true"
    :refresher-triggered

常见错误 ​

  1. 所有订单状态都显示同样的按钮 现象:待支付、咨询中、已取消的卡片下方都出现"取消 / 继续支付"。 原因:按钮区没有按 status 分支渲染,或只写了 v-if 没写 v-else-if,条件写成恒真(如 status >= 1)。 修法:按状态值逐一列出分支,咨询中只给"继续咨询",已取消不再给"取消",并在每个分支里只放该状态允许的操作。

  2. 加载更多组件永远显示"没有更多数据" 现象:列表还能上拉出数据,底部文案却一直是 noMore。 原因:status 写成了静态字符串,或初始值直接给了 noMore。 修法:属性前加冒号绑定变量,初始值设 loading;请求发出时置 loading,请求结束后用 hasMore ? 'more' : 'noMore' 赋值。

  3. 上拉加载后列表出现大量重复数据 现象:每滚一次到底,列表里就多出一批与第一页相同的内容。 原因:请求成功后没有执行页码自增,每次请求的 currentPage 都是 1。 修法:在请求结束(拿到数据之后)执行 currentPage++,注意不要写在请求发出之前,否则首屏就跳页。

  4. 滚到最后一页还在不停发请求 现象:数据早已到底,继续上拉仍持续发出请求,返回空数组。 原因:只做了分页,没有用"当前页码与总页数比较"得出 hasMore,onReachBottom 里无条件调用请求方法。 修法:请求结束处计算 hasMore = currentPage <= totalPage,并在触底回调里先判断 hasMore 为真再请求。

  5. 加了防抖但请求次数没减少 现象:快速滚动时仍一次触发多个请求,页码出现 4、4、5 这种重复或跳号。 原因:把 debounce(fn, 300) 的返回值丢掉了,直接把它当作事件回调;或在事件回调内部每次都重新调用一次 debounce,等于每次都造一个新函数,防抖状态被重置。 修法:debounce 只负责创建防抖函数,要在 setup 里执行一次并把返回值存起来,事件绑定的是这个返回值;真正要执行的逻辑作为参数传进去,内部若有 await 记得补 async。

  6. 下拉刷新后列表越刷越长 / 页码接着累加 现象:下拉一次后列表变成两倍长度,或者从第 6 页继续请求。 原因:刷新回调里只调了请求方法,没有把 currentPage 重置为 1,也没有清空列表数组。 修法:刷新回调开头先 currentPage = 1、list = [],再发起第一页请求。

  7. 下拉刷新动画一直转圈不消失 现象:松手后顶部 loading 不停,页面卡在刷新态。 原因:控制动画的属性没有绑到页面配置上;或关闭动画的代码写在请求之前、没加 await,异步还没回来就把标志位改回去了。 修法:把该属性绑定到页面,请求前置 true,请求方法前加 async、调用处加 await,请求完成后再置 false。

  8. 调用云函数拿不到返回值 现象:res 打印为 undefined,或云开发控制台看不到调用记录。 原因:把云函数当普通函数直接 函数名() 调用;或忘了 await / .then 就去取 res.result;或参数没放在 data 字段里。 修法:统一走 await uniCloud.callFunction({ name: 'xxx', data: {...} }),返回值从 res.result 取;无参时可省略 data。

练习 ​

  1. 给定 status 取值 1~5,用 v-if / v-else-if 写出按钮区分支,并同时给出每种状态对应的状态文案映射,要求"咨询中"不出现取消与继续支付。
  2. 为加载更多组件写绑定表达式:说明初始值为什么是 loading,并写出请求开始、请求结束两个时机分别给 status 赋什么值(结束时要结合 hasMore)。
  3. 写出触底加载的完整流程伪代码:监听事件 → 判断是否还有更多 → 请求 → 页码自增 → 重新计算 hasMore,并标注哪一步最容易漏。
  4. 用已封装的 debounce 改造第 3 题的触底请求,写出创建防抖函数与绑定事件的代码;再解释:如果把 debounce(getList, 300) 直接写在模板事件里会发生什么。
  5. 实现下拉刷新:写出需要重置的变量、清空的数据、以及保证动画能正确关闭的写法(含 async/await 的位置)。
  6. 写一段云函数调用代码:传入 { name: '小明' },把返回结果打印出来,并说明参数和返回值分别放在哪个字段。

课堂画面 ​

课堂画面 01

课堂画面 02

课堂画面 03

课堂画面 04

课堂画面 05

课堂画面 06

原视频对照 ​

#视频时长
1优医咨询-组件渲染数据说明04:09
2优医咨询-加载更多组件说明05:12
3优医咨询-分页请求问诊列表10:31
4优医咨询-问诊订单防抖处理10:28
5优医咨询-问诊列表下拉刷新08:03
6云开发概念介绍04:56
7云函数的基本用法13:30

小结 ​

  • 按钮与状态文案是"状态驱动 UI":先确定状态与操作的对应关系,再用条件渲染落地,不能机械抄分支。
  • 加载更多组件的 status 必须是变量而非固定值,且与请求生命周期绑定:请求中 loading、结束按 hasMore 二选一。
  • 分页三要素缺一不可:触底监听、请求后页码自增、用页码与总页数比较得出 hasMore,并在触底时先判 hasMore。
  • 页码自增的位置在请求成功之后,过早自增会跳页,忘记自增会重复数据。
  • 防抖函数由 debounce 创建出来,创建一次、复用同一个,debounce 本身不是防抖函数;它的作用是"多次触发只执行最后一次",与节流"固定时间间隔内只执行一次"不同。
  • 下拉刷新的本质是回到初始状态:页码归 1、列表清空,再走一次首屏请求流程。
  • 关闭下拉动画依赖 async/await 保证时序,否则动画会在请求返回前被错误关闭或一直不关。
  • 云函数 = 跑在服务端的普通函数,调用方式等价于调后端接口:callFunction({ name, data }) 传参、res.result 取结果。