UniCloud 完整入门指南
目录
什么是 UniCloud
UniCloud 是 DCloud 推出的基于 serverless 模式和 js 编程的云开发平台。它让不会后端的前端工程师可以快速完成整栈开发,让开发者专注于业务实现,而无需关心服务器运维等繁琐事务。
主要特点
- 基于 serverless 架构
- 支持 Node.js 编程
- 提供简单易用的云函数
- 集成云数据库
- 支持云存储功能
- 统一账号系统
为什么选择 UniCloud
-
降低开发成本
- 无需购买服务器
- 按量付费,避免资源浪费
- 减少运维成本
-
提高开发效率
- 一体化开发体验
- 前后端统一语言(JavaScript)
- 自动弹性扩容
-
安全可靠
- 内置安全防护
- 自动备份机制
- 专业团队维护
快速开始
1. 环境准备
- 安装 HBuilderX
- 注册 DCloud 开发者账号
- 开通 UniCloud 服务
2. 创建云函数项目
// 创建云函数示例
'use strict';
exports.main = async (event, context) => {
return {
status: 200,
msg: 'Hello UniCloud'
}
}
3. 基础配置
在项目根目录创建 uniCloud
目录,包含以下结构:
├── uniCloud
├── cloudfunctions // 云函数目录
└── database // 数据库目录
基础概念
1. 云函数
云函数是运行在云端的 JavaScript 代码。你可以将云函数理解为一个在云端运行的接口,可以在其中编写任意的服务端代码。
示例代码:
// 云函数示例
exports.main = async function(event, context) {
const db = uniCloud.database()
const collection = db.collection('users')
const res = await collection.get()
return res
}
2. 云数据库
UniCloud 提供了一个 JSON 格式的文档型数据库。它支持在云函数中通过代码操作数据库,也提供了可视化的数据管理界面。
数据库操作示例:
// 插入数据
const db = uniCloud.database()
await db.collection('books').add({
title: '深入浅出 UniCloud',
author: 'DCloud',
price: 99
})
// 查询数据
const res = await db.collection('books')
.where({
price: {
$gt: 50
}
})
.get()
3. 云存储
云存储用于存储文件,支持图片、视频、音频等各种类型的文件。
// 上传文件示例
const result = await uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'images/logo.png'
})
核心功能
1. 数据库操作
增删改查
// 新增
await db.collection('users').add(data)
// 删除
await db.collection('users').doc(id).remove()
// 修改
await db.collection('users').doc(id).update(data)
// 查询
await db.collection('users').where(condition).get()
聚合操作
const $ = db.command.aggregate
await db.collection('orders')
.aggregate()
.group({
_id: '$status',
total: $.sum('$amount')
})
.end()
2. 云函数调用
前端调用
// promise方式
uniCloud.callFunction({
name: 'functionName',
data: {
// 参数
}
}).then(res => {
// 处理返回结果
})
// async/await方式
const res = await uniCloud.callFunction({
name: 'functionName',
data: {
// 参数
}
})
3. 云存储使用
// 上传文件
const result = await uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'folder/file.ext'
})
// 下载文件
const result = await uniCloud.downloadFile({
fileID: 'cloud://xxx.jpg'
})
// 删除文件
const result = await uniCloud.deleteFile({
fileList: ['cloud://xxx.jpg']
})
最佳实践
1. 数据库设计原则
-
合理设计 Schema
- 避免过深的嵌套
- 适当冗余以提高查询效率
- 使用合适的索引
-
优化查询性能
- 避免大量的跨表查询
- 合理使用索引
- 控制返回数据量
2. 云函数开发建议
- 错误处理
exports.main = async function(event, context) {
try {
// 业务逻辑
return {
status: 0,
data: result
}
} catch (e) {
return {
status: -1,
msg: e.message
}
}
}
- 参数校验
exports.main = async function(event, context) {
const { name, age } = event
if (!name || typeof age !== 'number') {
return {
status: -1,
msg: '参数错误'
}
}
// 继续处理
}
3. 安全性建议
-
数据验证
- 前端和后端都要做数据验证
- 使用数据库权限管理
- 实施访问控制
-
敏感数据处理
- 加密存储敏感信息
- 使用环境变量存储密钥
- 控制数据访问权限
常见问题
1. 云函数超时如何处理?
- 默认超时时间为 10 秒
- 可以在云函数配置中修改超时时间
- 建议将耗时操作拆分为多个步骤
2. 如何处理大量数据?
- 使用分页查询
- 采用批量操作
- 考虑使用定时任务
3. 如何优化云函数性能?
- 合理使用缓存
- 优化数据库查询
- 避免不必要的操作
高级功能详解
1. 云函数高级特性
定时触发器
云函数支持定时触发器功能,可以按照指定的时间规则自动执行:
// 配置示例 cloudfunctions/myFunction/config.json
{
"triggers": [{
"name": "myTrigger",
"type": "timer",
"config": "0 0 2 * * *" // 每天凌晨2点执行
}]
}
云函数URL化
将云函数转换为HTTP接口,支持外部系统调用:
// 云函数配置
module.exports = {
path: '/api/test', // 访问路径
method: 'POST', // 请求方法
}
exports.main = async function(event) {
// 函数逻辑
}
中间件
支持使用中间件处理通用逻辑:
const middleware = require('uni-middleware')
module.exports = {
middleware: [
async function auth(ctx, next) {
// 身份验证逻辑
const token = ctx.event.headers.token
if (!token) throw new Error('未授权')
await next()
}
]
}
2. 数据库高级操作
事务处理
const transaction = await db.startTransaction()
try {
await transaction.collection('accounts').doc('user1').update({
balance: db.command.inc(-100)
})
await transaction.collection('accounts').doc('user2').update({
balance: db.command.inc(100)
})
await transaction.commit()
} catch (err) {
await transaction.rollback()
throw err
}
复杂查询
// 关联查询
const $ = db.command.aggregate
db.collection('orders')
.aggregate()
.lookup({
from: 'users',
localField: 'user_id',
foreignField: '_id',
as: 'userInfo'
})
.match({
status: 'pending',
'userInfo.vip': true
})
.project({
_id: 1,
order_no: 1,
'userInfo.nickname': 1
})
.end()
// 地理位置查询
const _ = db.command
db.collection('stores').where({
location: _.geoNear({
geometry: new db.Geo.Point(113.324520, 23.099994),
maxDistance: 1000,
minDistance: 0
})
}).get()
3. 云存储高级应用
文件分片上传
// 前端代码
async function uploadLargeFile(file) {
const chunkSize = 4 * 1024 * 1024 // 4MB per chunk
const chunks = Math.ceil(file.size / chunkSize)
for(let i = 0; i < chunks; i++) {
const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize)
await uniCloud.uploadFile({
filePath: chunk,
cloudPath: `chunks/${file.name}_${i}`,
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
)
console.log(`Chunk ${i + 1}/${chunks}: ${percentCompleted}%`)
}
})
}
}
文件访问控制
// 云函数中生成私有文件临时访问链接
exports.main = async function(event) {
const res = await uniCloud.getTempFileURL({
fileList: [{
fileID: 'cloud://xxx.jpg',
maxAge: 3600, // 链接有效期1小时
}]
})
return res.fileList[0].tempFileURL
}
4. 安全机制
1. 数据库权限控制
// 在 db_init.json 中配置权限
{
"collection": "articles",
"permission": {
"read": true,
"create": "auth.uid != null",
"update": "doc.author_id == auth.uid",
"delete": "doc.author_id == auth.uid"
}
}
2. 敏感数据加密
const crypto = require('crypto')
// 加密函数
function encrypt(data, key) {
const cipher = crypto.createCipher('aes-256-gcm', key)
let encrypted = cipher.update(data, 'utf8', 'hex')
encrypted += cipher.final('hex')
return encrypted
}
// 解密函数
function decrypt(encrypted, key) {
const decipher = crypto.createDecipher('aes-256-gcm', key)
let decrypted = decipher.update(encrypted, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
5. 性能优化
1. 数据库索引优化
// 创建索引
db.collection('users').createIndex({
age: 1,
city: 1
}, {
unique: false,
sparse: true
})
// 使用索引查询
db.collection('users')
.where({
age: _.gt(18),
city: 'Shanghai'
})
.get()
2. 批量操作优化
// 批量插入
const data = Array.from({length: 1000}, (_, i) => ({
name: `user${i}`,
age: Math.floor(Math.random() * 100)
}))
const batchTimes = Math.ceil(data.length / 100)
for (let i = 0; i < batchTimes; i++) {
await db.collection('users').add(
data.slice(i * 100, (i + 1) * 100)
)
}
6. 实用工具和技巧
1. 自定义验证器
// 验证器示例
const validator = {
validateEmail(email) {
const reg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return reg.test(email)
},
validatePhone(phone) {
const reg = /^1[3-9]\d{9}$/
return reg.test(phone)
}
}
// 在云函数中使用
exports.main = async function(event) {
const { email, phone } = event
if (!validator.validateEmail(email)) {
return {
code: -1,
msg: '邮箱格式不正确'
}
}
if (!validator.validatePhone(phone)) {
return {
code: -1,
msg: '手机号格式不正确'
}
}
// 继续处理...
}
2. 错误处理最佳实践
// 自定义错误类
class BusinessError extends Error {
constructor(code, message) {
super(message)
this.code = code
}
}
// 统一错误处理
exports.main = async function(event) {
try {
// 业务逻辑
if (condition) {
throw new BusinessError(10001, '业务错误信息')
}
return {
code: 0,
data: result
}
} catch (e) {
if (e instanceof BusinessError) {
return {
code: e.code,
msg: e.message
}
}
console.error(e)
return {
code: -1,
msg: '系统错误'
}
}
}
7. 项目实战示例
1. 用户认证系统
// 注册
exports.main = async function(event) {
const { username, password, email } = event
// 验证用户名是否存在
const userExist = await db.collection('users')
.where({ username })
.count()
if (userExist.total > 0) {
throw new Error('用户名已存在')
}
// 密码加密
const salt = crypto.randomBytes(16).toString('hex')
const hash = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512').toString('hex')
// 创建用户
const result = await db.collection('users').add({
username,
email,
password: hash,
salt,
created_at: Date.now()
})
return {
code: 0,
data: {
uid: result.id
}
}
}
2. 支付系统集成
// 微信小程序登录
exports.main = async function(event) {
const { code } = event
const wxRes = await uniCloud.getWXContext(code)
// 获取用户信息
const userInfo = await db.collection('users')
.where({
openid: wxRes.OPENID
})
.get()
return {
code: 0,
data: userInfo.data[0]
}
}
开发工具
1. HBuilderX 插件推荐
uni-cloud-router
: 云函数路由管理uni-cloud-database
: 数据库可视化管理eslint-plugin-unicloud
: 代码规范检查
2. 调试技巧
本地调试
// 开启调试模式
const db = uniCloud.database({
debug: true
})
// 查看执行计划
const res = await db.collection('users')
.where({ age: _.gt(18) })
.explain()
console.log(res)
日志管理
// 在云函数中使用
console.log('普通日志')
console.info('信息日志')
console.warn('警告日志')
console.error('错误日志')
// 查看运行日志
uniCloud.logger.log('详细日志信息')
部署和运维
1. 多环境配置
// uniCloud.config.js
module.exports = {
development: {
functionRoot: './cloudfunctions',
spaceName: 'dev-space'
},
production: {
functionRoot: './cloudfunctions',
spaceName: 'prod-space'
}
}
2. 监控告警
// 设置告警规则
exports.main = async function(event) {
try {
// 监控指标
const metrics = await uniCloud.metrics.get({
metric: 'function_duration',
period: 300, // 5分钟
})
// 判断是否需要告警
if (metrics.dataPoints[0].value > 1000) {
// 发送告警
await sendAlert('函数执行时间过长')
}
} catch (e) {
console.error(e)
}
}
最新特性和更新
1. Uni-AD 广告联盟集成
// 获取广告配置
exports.main = async function(event) {
const ads = await uniCloud.getAdConfig({
adpid: ['your_ad_id']
})
return {
code: 0,
data: ads
}
}
2. 微信支付宝等三方服务集成
// 微信小程序登录
exports.main = async function(event) {
const { code } = event
const wxRes = await uniCloud.getWXContext(code)
// 获取用户信息
const userInfo = await db.collection('users')
.where({
openid: wxRes.OPENID
})
.get()
return {
code: 0,
data: userInfo.data[0]
}
}
总结
UniCloud 作为一个现代化的云开发平台,为开发者提供了强大且易用的工具和服务。通过本文的学习,你应该已经掌握了:
- UniCloud 的基本概念和优势
- 如何使用云函数、云数据库和云存储
- 开发中的最佳实践和注意事项
- 常见问题的解决方案
希望这份教程能帮助你更好地使用 UniCloud 进行开发。如果你在使用过程中遇到任何问题,可以参考官方文档或在社区寻求帮助。