主题
药品订单与云函数(三)
本页对应 药品订单与云函数,共 7 段视频,约 56 分钟。
学习目标
- 能根据问诊订单状态使用
v-if渲染对应的操作按钮和状态文案,并说明不同状态下可执行操作的原因。 - 能使用 uni-app 加载更多组件,动态绑定
status控制more、loading、no-more提示,并在请求前后正确切换状态。 - 能实现问诊列表分页请求:监听滚动到底部、页码递增、根据总页数更新
hasMore,并在无更多数据时阻止继续请求。 - 能封装并使用防抖函数,说明
debounce返回的是防抖函数,并在滚动请求场景中验证可避免重复请求。 - 能实现下拉刷新:监听刷新事件、重置页码和列表数据、请求第一页,并在请求结束后关闭刷新动画。
- 能说明云开发中云函数、云数据库、云存储的作用,并使用
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常见错误
所有订单状态都显示同样的按钮 现象:待支付、咨询中、已取消的卡片下方都出现"取消 / 继续支付"。 原因:按钮区没有按
status分支渲染,或只写了v-if没写v-else-if,条件写成恒真(如status >= 1)。 修法:按状态值逐一列出分支,咨询中只给"继续咨询",已取消不再给"取消",并在每个分支里只放该状态允许的操作。加载更多组件永远显示"没有更多数据" 现象:列表还能上拉出数据,底部文案却一直是 noMore。 原因:
status写成了静态字符串,或初始值直接给了noMore。 修法:属性前加冒号绑定变量,初始值设loading;请求发出时置loading,请求结束后用hasMore ? 'more' : 'noMore'赋值。上拉加载后列表出现大量重复数据 现象:每滚一次到底,列表里就多出一批与第一页相同的内容。 原因:请求成功后没有执行页码自增,每次请求的
currentPage都是 1。 修法:在请求结束(拿到数据之后)执行currentPage++,注意不要写在请求发出之前,否则首屏就跳页。滚到最后一页还在不停发请求 现象:数据早已到底,继续上拉仍持续发出请求,返回空数组。 原因:只做了分页,没有用"当前页码与总页数比较"得出
hasMore,onReachBottom里无条件调用请求方法。 修法:请求结束处计算hasMore = currentPage <= totalPage,并在触底回调里先判断hasMore为真再请求。加了防抖但请求次数没减少 现象:快速滚动时仍一次触发多个请求,页码出现 4、4、5 这种重复或跳号。 原因:把
debounce(fn, 300)的返回值丢掉了,直接把它当作事件回调;或在事件回调内部每次都重新调用一次debounce,等于每次都造一个新函数,防抖状态被重置。 修法:debounce只负责创建防抖函数,要在 setup 里执行一次并把返回值存起来,事件绑定的是这个返回值;真正要执行的逻辑作为参数传进去,内部若有await记得补async。下拉刷新后列表越刷越长 / 页码接着累加 现象:下拉一次后列表变成两倍长度,或者从第 6 页继续请求。 原因:刷新回调里只调了请求方法,没有把
currentPage重置为 1,也没有清空列表数组。 修法:刷新回调开头先currentPage = 1、list = [],再发起第一页请求。下拉刷新动画一直转圈不消失 现象:松手后顶部 loading 不停,页面卡在刷新态。 原因:控制动画的属性没有绑到页面配置上;或关闭动画的代码写在请求之前、没加
await,异步还没回来就把标志位改回去了。 修法:把该属性绑定到页面,请求前置true,请求方法前加async、调用处加await,请求完成后再置false。调用云函数拿不到返回值 现象:
res打印为 undefined,或云开发控制台看不到调用记录。 原因:把云函数当普通函数直接函数名()调用;或忘了await/.then就去取res.result;或参数没放在data字段里。 修法:统一走await uniCloud.callFunction({ name: 'xxx', data: {...} }),返回值从res.result取;无参时可省略data。
练习
- 给定
status取值 1~5,用v-if / v-else-if写出按钮区分支,并同时给出每种状态对应的状态文案映射,要求"咨询中"不出现取消与继续支付。 - 为加载更多组件写绑定表达式:说明初始值为什么是
loading,并写出请求开始、请求结束两个时机分别给status赋什么值(结束时要结合hasMore)。 - 写出触底加载的完整流程伪代码:监听事件 → 判断是否还有更多 → 请求 → 页码自增 → 重新计算
hasMore,并标注哪一步最容易漏。 - 用已封装的
debounce改造第 3 题的触底请求,写出创建防抖函数与绑定事件的代码;再解释:如果把debounce(getList, 300)直接写在模板事件里会发生什么。 - 实现下拉刷新:写出需要重置的变量、清空的数据、以及保证动画能正确关闭的写法(含
async/await的位置)。 - 写一段云函数调用代码:传入
{ name: '小明' },把返回结果打印出来,并说明参数和返回值分别放在哪个字段。
课堂画面






原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 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取结果。