在 HarmonyOS 上做 uni-app x 应用时,云端调用不只有云函数。HarmonyOS 4.61 开始支持 uniCloud.importObject,与 callFunction 云函数是同一批能力。它把云对象导入为本地调用器,之后可以像调本地方法一样调远程方法,例如 todo.add('标题','内容')。对于 todo 列表、用户资料等 CRUD 服务,这种写法比每次 callFunction 传函数名和 data 更直接。下面按 API 签名、云对象编写、泛型、自动 UI、CRUD、加密、鸿蒙强类型适配以及与 callFunction/原生 HTTP 的对比来梳理。
一、importObject 的 API 与兼容点
原先用 callFunction 调云函数,需要传函数名、传 data,再拿 result。云对象则通过 uniCloud.importObject 导入,然后直接调用它的方法。API 签名如下:
- uniCloud.importObject(objectName: string, options?: UniCloudImportObjectOptions): UniCloudCloudObjectCaller
复制代码
options 中常见有 loadingOptions 和 errorOptions。泛型从 4.13 版本起支持。鸿蒙平台从 4.61 开始支持 uniCloud.importObject,跟云函数 callFunction 是同一批支持的。
二、云对象编写与基础调用
云对象是一个目录,核心文件是 index.obj.js。例如 cloudfunctions/todo/index.obj.js:
- 'use strict';
- const db = uniCloud.database()
- const collection = db.collection('todos')
- module.exports = {
- async add(title, content) {
- const result = await collection.add({
- title: title,
- content: content,
- status: 'pending',
- createTime: Date.now()
- })
- return {
- errCode: 0,
- errMsg: '',
- id: result.id
- }
- },
- async list(page, pageSize) {
- const countResult = await collection.count()
- const listResult = await collection
- .skip((page - 1) * pageSize)
- .limit(pageSize)
- .orderBy('createTime', 'desc')
- .get()
- return {
- errCode: 0,
- errMsg: '',
- list: listResult.data,
- total: countResult.total
- }
- },
- async updateStatus(id, status) {
- await collection.doc(id).update({
- status: status
- })
- return {
- errCode: 0,
- errMsg: ''
- }
- },
- async remove(id) {
- await collection.doc(id).remove()
- return {
- errCode: 0,
- errMsg: ''
- }
- }
- }
复制代码
导入后直接调用:
- const todo = uniCloud.importObject('todo')
- const result = await todo.add('标题', '内容')
复制代码
基础 .then 调用中,若没有泛型,res 可转成 UTSJSONObject 再取 id。错误处理建议在 catch 里 console.error 并给出 toast 提示。
三、泛型让鸿蒙强类型下更安全
uni-app x 是强类型语言,云对象返回值最好定义类型。4.13 版本起支持泛型调用:
- type AddResult = {
- errCode: number
- errMsg: string
- id: string
- }
- type ListResult = {
- errCode: number
- errMsg: string
- list: Array<UTSJSONObject>
- total: number
- }
- const todo = uniCloud.importObject('todo')
- todo.add<AddResult>('学习 uni-app x', '写一篇鸿蒙开发文章').then((res) => {
- console.log('添加成功,ID:', res.id)
- })
- todo.list<ListResult>(1, 10).then((res) => {
- console.log('总数:', res.total)
- console.log('列表:', res.list)
- })
复制代码
这里 res.id、res.total、res.list 可以直接访问,不需要先做类型转换。对鸿蒙端来说,类型越明确,编译期越容易发现字段拼写或结构错误。
四、自动 loading 与错误提示
云对象默认会自动展示 loading 和错误提示,可通过 loadingOptions、errorOptions 配置:
- const todo = uniCloud.importObject('todo', {
- loadingOptions: {
- title: '加载中...',
- mask: true
- },
- errorOptions: {
- type: 'modal',
- retry: true
- }
- })
- todo.list<ListResult>(1, 10).then((res) => {
- console.log('列表:', res.list)
- })
复制代码
如果不想用默认 UI,可以设置 customUI: true 关闭,然后自己 showLoading、hideLoading,并在 catch 中处理错误:
- const todo = uniCloud.importObject('todo', {
- customUI: true
- })
- uni.showLoading({ title: '自定义 loading...' })
- todo.list<ListResult>(1, 10).then((res) => {
- uni.hideLoading()
- console.log('列表:', res.list)
- }).catch((err) => {
- uni.hideLoading()
- uni.showToast({
- title: '加载失败',
- icon: 'none'
- })
- })
复制代码
五、CRUD 实战
一个完整的待办 CRUD 可以这样组织类型和调用:
- type TodoItem = {
- _id: string
- title: string
- content: string
- status: string
- createTime: number
- }
- type AddResult = {
- errCode: number
- errMsg: string
- id: string
- }
- type ListResult = {
- errCode: number
- errMsg: string
- list: Array<TodoItem>
- total: number
- }
- type OperationResult = {
- errCode: number
- errMsg: string
- }
- const todo = uniCloud.importObject('todo')
- const addTodo = (title: string, content: string) => {
- todo.add<AddResult>(title, content).then((res) => {
- if (res.errCode == 0) {
- uni.showToast({ title: '添加成功', icon: 'success' })
- console.log('新 ID:', res.id)
- }
- })
- }
- const listTodos = (page: number) => {
- todo.list<ListResult>(page, 10).then((res) => {
- if (res.errCode == 0) {
- console.log('列表:', res.list)
- console.log('总数:', res.total)
- }
- })
- }
- const updateStatus = (id: string, status: string) => {
- todo.updateStatus<OperationResult>(id, status).then((res) => {
- if (res.errCode == 0) {
- uni.showToast({ title: '更新成功', icon: 'success' })
- }
- })
- }
- const removeTodo = (id: string) => {
- todo.remove<OperationResult>(id).then((res) => {
- if (res.errCode == 0) {
- uni.showToast({ title: '删除成功', icon: 'success' })
- }
- })
- }
复制代码
完整页面里通常用 ref 管理 newTitle、newContent、todoList,onMounted 调 loadList。删除前可用 uni.showModal 做二次确认。云对象仍负责 add、list、updateStatus、remove,客户端只关心方法名和返回结构。
六、敏感方法加密调用
对敏感方法可以使用 secretMethods。changePassword 配置为 both,表示请求和响应都加密;updateProfile 配置为 request,表示只加密请求:
- const user = uniCloud.importObject('user', {
- secretMethods: {
- changePassword: 'both',
- updateProfile: 'request'
- }
- })
- user.changePassword('oldPass', 'newPass').then((res) => {
- console.log('修改密码成功')
- })
复制代码
七、鸿蒙强类型限制与 index.obj.d.ts
HarmonyOS 4.61 起支持 uniCloud.importObject,但 uni-app x 是强类型语言,编译时需要读取本地云对象导出的方法列表。因此要确保调用的云对象在本地包含导出的方法。如果云函数加密导致 index.obj.js 无法被解析,需要创建 index.obj.d.ts 声明方法:
- type AnyFunction = (...args: any[]) => any;
- declare const add: AnyFunction
- declare const list: AnyFunction
- declare const updateStatus: AnyFunction
- declare const remove: AnyFunction
- export {
- add,
- list,
- updateStatus,
- remove
- }
复制代码
这一步是鸿蒙适配里最容易漏掉的点。没有声明时,编译期方法列表不完整,类型检查会报错或无法解析方法。
八、和 callFunction、鸿蒙原生 HTTP 对比
云函数写法需要传 name 和 data,再从 res.result 取结果:
- uniCloud.callFunction({
- name: 'todo-add',
- data: { title: '标题', content: '内容' }
- } as UniCloudCallFunctionOptions).then((res) => {
- console.log(res.result)
- })
复制代码
云对象写法更像本地方法:
- const todo = uniCloud.importObject('todo')
- todo.add('标题', '内容').then((res) => {
- console.log(res)
- })
复制代码
云对象可以在一个 index.obj.js 里定义多个方法,不用每个功能创建一个云函数目录。和鸿蒙原生远程调用相比,原生要自己处理 HTTP、序列化和错误处理:
- import { http } from '@kit.NetworkKit'
- const response = await http.createHttp().request(
- 'https://your-server.com/api/todo/add',
- {
- method: http.RequestMethod.POST,
- extraData: JSON.stringify({ title: '标题' })
- }
- )
- const result = JSON.parse(response.result as string)
复制代码
uniCloud 云对象省去搭服务器和处理 HTTP 的步骤,但前提是项目已经接入 uniCloud,并且按鸿蒙强类型要求补好本地声明。
适配清单
1. 确认 HarmonyOS 4.61 及以上,使用 uniCloud.importObject,它与 callFunction 同批支持。
2. 云对象目录放在 cloudfunctions/对象名/index.obj.js,module.exports 暴露方法。
3. 鸿蒙端优先用泛型定义返回结构,减少 UTSJSONObject 转换。
4. 默认自动 UI 可用 loadingOptions/errorOptions;需要自定义交互时设置 customUI: true。
5. 敏感方法通过 secretMethods 配置 both 或 request。
6. 若 index.obj.js 因加密无法解析,补 index.obj.d.ts,声明所有被调方法。
7. 与 callFunction 相比,云对象适合模块化 CRUD;与原生 HTTP 相比,少写网络层,但要接受 uniCloud 运行时约束。 |