鸿蒙 uni-app x 云对象 importObject 适配
在 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 运行时约束。
Re: 鸿蒙 uni-app x 云对象 importObject 适配
感谢分享,整理得很实用。以前鸿蒙端调云函数确实要每次 callFunction 带函数名和 data,云对象 importObject 后直接 todo.add 这种写法清爽很多。按 index.obj.js 组织 add、list、updateStatus、remove 的 CRUD 示例也很清楚,容易照着改。泛型那段对 uni-app x 强类型帮助很大,AddResult 和 ListResult 定义好之后,res.id、res.total 能直接访问,少掉一层 UTSJSONObject 转换,编译期也更容易发现字段错误。另外 loadingOptions、errorOptions 默认处理 loading 和错误提示,适合快速页面。想问下 customUI 设为 true 后,手动 showLoading、hideLoading 一般放在调用云对象方法前后,还是在导入对象时做统一封装?还有 list 返回的数组里如果存的是 UTSJSONObject,鸿蒙端渲染前是否还要再转成具体 item 类型?期待后续补充。Re: 鸿蒙 uni-app x 云对象 importObject 适配
楼主整理得挺全的,鸿蒙端 uni-app x 用 importObject 确实比每次 callFunction 传函数名和 data 顺手很多,尤其是 todo 这种 CRUD,直接 todo.add、todo.list 调起来更像本地方法。泛型那块很实用,uni-app x 本来就是强类型,返回值定义好类型后 res.id、res.total 能直接访问,编译期也能少踩字段拼错的坑。默认 loading 和错误提示加上 loadingOptions、errorOptions 基本够用,想自定义再用 customUI 关掉自己 showLoading、hideLoading 和 catch 处理也更灵活。鸿蒙 4.61 和 callFunction 同批支持这个兼容点很关键,收藏了,期待后面的 CRUD、加密和强类型适配内容。Re: 鸿蒙 uni-app x 云对象 importObject 适配
看完挺有收获,特别是云对象这套写法用 CRUD 来说明很直观。以前 callFunction 每次都要传函数名和 data,拿 result 再解析;换成 importObject 之后,像 todo.add、todo.list 这样直接调用,代码确实清爽很多。 泛型那段也很实用。uni-app x 在鸿蒙上强类型,返回值如果能定义成 AddResult、ListResult,res.id、res.total、res.list 就能直接访问,不用先转 UTSJSONObject,字段拼写和结构问题也更容易在编译期暴露。鸿蒙 4.61 开始支持 importObject,并且和 callFunction 是同一批能力,这个版本点很关键。 自动 loading 和错误提示那块也挺方便,loadingOptions、errorOptions 能省不少模板代码;如果不想用默认 UI,再 customUI: true 自己 showLoading、hideLoading,并在 catch 里处理,这个思路很清晰。 想问一下,如果 list 返回的每一项结构固定,是不是也可以把 ListResult 里的 Array 换成更具体的类型?这样前端遍历和访问字段应该会更安全。整体感觉 importObject 很适合 todo、用户资料这类服务化接口,比每次 callFunction 更接近本地方
页:
[1]