uniapp 云开发介绍
uniCloud
是 DCloud 联合阿里云、腾讯云、支付宝小程序云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。
可以使用极小的成本 代价开发具轻松实现前后台 整体业务。尤其适用于不太熟悉后端的前端工程师!!!!
普通应用架构
服务空间
一个服务空间对应一整套独立的云开发资源,包括数据库、存储空间、云函数等资源。服务空间之间彼此隔离。
目前DCloud提供了三种服务空间可以提供选择:
- 支付宝小程序云
- 阿里云 提供一个免费的空间
- 腾讯云
云数据库
uniCloud
提供了一个 JSON 格式的文档型数据库。顾名思义,数据库中的每条记录都是一个 JSON 格式的文档。
它是 nosql (类似 MongoDB) 非关系型数据库。
-
可以在web端 或者hbuilderX 使用MongoDB语法或jql语法管理数据库
-
uniapp还提供了独特的 clientDB 能力,可以我们直接在前端页面中读取数据库,极大提高了开发效率
js// 获取db引用 const db = uniCloud.database() //代码块为cdb db.collection('list') .where({ name: "hello-uni-app" //传统MongoDB写法,不是jql写法。实际开发中推荐使用jql写法 }).get() .then((res)=>{ // res 为数据库查询结果 }).catch((err)=>{ console.log(err.code); // 打印错误码 console.log(err.message); // 打印错误内容 })
云存储
云存储 就是一个云端的静态资源管理工具,也提供了cdn功能。支持直接在客户端就上传资源到云存储。
客户端代码
js
uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'a.jpg',
success() {},
fail() {},
complete() {}
});
云函数
云函数是运行在云端/后端的 JavaScript
代码,是基于 Node.js
的扩展。
在常规的 Node API
基础上,uniCloud的云函数环境内置了uniCloud
对象,这个对象内置了网络、数据库等各种
API。开发者未学习过 Node.js
也没有关系,只需要看uniCloud的文档,掌握这个uniCloud
对象的API即可
js
// hello云函数index.js入口文件代码
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
let c = event.a + event.b
return {
sum: c
} // 通过return返回结果给客户端
}
云端一体插件
我们实现一个产品的功能,往往需要前端+后端共同完成,比如验证码、登录、文件上传等等。uniapp提供了云端一体插件,可以直接通过引入的方式就帮我们做好了前端和后端的所有工作,极大简化了开发者的工作。
-
uni-id:不用再开发用户系统。用户注册、登录(含社交登录、短信验证码登录、App一键登录)、修改或重置密
码、token管理、图形验证码、RBAC权限角色系统...所有与用户相关的,不管前端还是云端,代码都是现成的。
-
uni-pay:不管微信还是支付宝,不管App、微信小程序、还是支付宝小程序,不管前端还是服务端,一切都现成的,拿来即用。详见
-
uni-starter:云端一体应用快速开发基本项目模版,实现快速搭建一款应用。它集成了很多通用的功能,比如登录注册、头像、设置、拦截器、banner...详见
-
uni-admin:全端可用的admin后台。自带用户管理、权限管理、角色管理、菜单管理、业务图表统计。更有众多
admin插件,比如cms插件、push、banner管理插件、App升级管理插件...详见
-
uni-search:云端一体搜索。搜索页面、输入联想、搜索历史记录、热搜词分析提取...一应俱全。详见
-
uni-file-picker:前端直传uniCloud存储组件。详见
-
uni-captcha:云端一体图形验证码组件。详见
-
uni-sec-check:免费的内容安全审查,防止用户提交违法的文字或图片。详见
-
uni-upgrade-center:App升级中心。支持整包升级、wgt热更新;支持直接下载安装包或跳转应用商店。详见
-
uni-push2:云端一体的推送,大幅简化推送开发。详见
-
uni-im:开源、多端IM。详见
-
uni-cms:开源、多端内容管理。详见
-
uni-ai:聚合ai能力。详见
-
uni-map:地理位置开发中间件,极大加速地图业务开发效率。详见
云数据库
一个服务空间对应着一个数据库,我们开通了服务空间自然就会有一个数据库了
数据表
DB Schema 数据库范式
新建数据表的渠道有两种
-
可以直接在web控制台来新建
-
可以在
hbuilderX
中新建
建表要遵循 DCloud 的 DB Schema
规范。如数据表的名称 建议是 xxx.schema
。如果是hbuilderX
中创建的 则是 xxx.schema.json
。文件内容如下
json
{
"bsonType": "object", // 固定节点
"description": "该表的描述",
"required": [], // 必填字段列表
"properties": { // 该表的字段清单
"_id": { // 字段名称,每个表都会带有_id字段
"description": "ID,系统自动生成"
// 这里还有很多字段属性可以设置
},
"field2": { // 字段2,每个表都会带有_id字段
"description": ""
// 这里还有很多字段属性可以设置
}
}
}
DB Schema有很多重要的作用:
- 描述数据表结构。一目了然的阅读每个表、每个字段的用途。
- 设置字段的默认值(defaultValue/forceDefaultValue),比如服务器当前时间、当前用户id等。
- 设定字段值域能接受的格式(validator),比如数字、字符串、布尔值,是否可为空,还可以指定的数据要求的正则格式,不符合的格式无法入库。
- 设定字段之间的约束关系(fieldRules),比如字段结束时间需要晚于字段开始时间。
- 设定多个表的关联关系,字段间映射关系(foreignKey),将多个表按一个虚拟联表直接查询,大幅简化联表查询。
- 设定数据操作权限(permission)。什么样的角色可以读/写哪些数据,都可以在这里配置。
- 根据schema自动生成前端界面(schema2code),包括列表、详情、新建和编辑页面,自动处理校验规则。
参考设计
hm-article.schema.json
json
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": [],
"permission": {
"read": true,
"create": true,
"update": true,
"delete": true
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"title":{
"bsonType": "string",
"description": "文章的标题",
"title": "标题",
"minLength": 2,
"maxLength": 20
},
"thumb":{
"bsonType": "string",
"description": "文章封面大图",
"title": "封面图片",
"defaultValue":"https://cdn.slidesharecdn.com/ss_thumbnails/newspaperexamples-stllink-130526034010-phpapp02-thumbnail-4.jpg?cb=1369539652"
},
"category":{
"bsonType": "int",
"enum":[
{
"text":"全部",
"value":0
},
{
"text":"精华",
"value":1
},
{
"text":"分享",
"value":2
}
]
}
}
}
openDB
对于前端的小伙伴或者刚入门的后端工程师来说,虽然平时开发也会接触到相关数据,但是这类数据往往都是一些前辈经过实际开发经验提前设计好的。但是现
在要自己独立来设计,并不是一件简单的事情。那么我们可以借助 openDB的帮助。
openDB
,是一套开放的数据表设计规范,包括了表名、字段等schema定义以及初始数据。其中 DCloud根据常用的系统功能,设计出来几十张数据表,可以给
们提供思路或者直接使用。如
- 用户管理(uni-id):用户相关的表定义,如:角色、权限、积分、任务等
- 日志管理(opendb-admin):管理后台常见功能,应用管理、升级中心、统计结果(新增、活跃、留存等)
- 文章&评论(opendb-news)
- 电商系统(opendb-mall)
- 新闻系统(opendb-news)
预置数据
openDB
不仅支持定义常用的数据表字段,还可以预置初始化数据。
比如,opendb-city-china是opendb中定义好的中国城市字典表
,它的定义分为两个部分:
- collection.json:定义数据表名称、所含字段、每个字段的类型以及读写权限规则等;
- data.json:定义初始化内容
你通过uniCloud web控制台创建openDB
表时,uniCloud
会自动校验该opendb表定义中是否包含data.json
,若包含,则在创建表定义后,自动导入
data.json
。
客户端-操作数据库
clientDB 客户端操作数据库
查询
先引入 uni-ui
-
前端页面编写以下代码,利用uniCloud对象的API进行数据库的查询
vue<template> <view class="content"> <uni-table stripe emptyText="暂无更多数据"> <uni-tr> <uni-th align="center">序号</uni-th> <uni-th align="center">标题</uni-th> <uni-th align="center">分类</uni-th> <uni-th align="center">封面图片</uni-th> <uni-th align="center">操作</uni-th> </uni-tr> <uni-tr v-for="(item, index) in list" :key="item._id" > <uni-td>{{index+1}}</uni-td> <uni-td>{{item.title}}</uni-td> <uni-td>{{item.category}}</uni-td> <uni-td> <image :src="item.thumb" mode="widthFix"></image> </uni-td> <uni-td> <button type="warn">删除</button> </uni-td> </uni-tr> </uni-table> </view> </template> <script setup> // 获取云数据库对象引用 const db = uniCloud.database(); import { ref } from "vue" const list = ref([]); // 查询 const onGet = async () => { const result = await db.collection("hm-article").get(); list.value = result.result.data } // 查询 onGet() </script> <style></style>
-
如果出现以下错误,需要这样解决 提示缺少 uni-id 配置文件
在目录新 新建
config.json
文件,复制配置,修改tokenSecret
然后刷新页面即可
云数据库支持常规的类似MongoDB语法和更加灵活的JQL*( javascript query language)*语法
json
// MongoDB
const result = await db.collection("hm-article").where({title:/云/}).get()
js
// JQL
const result = await db.collection("hm-article").where(`/云/.test(title)`).get()
新增
js
// 新增
const onAdd= async () =>{
await db.collection("hm-article").add({
title:"華為鴻蒙日漸火熱"+list.value.length,
category:2,
thumb:'https://mp-c1674c18-fa0b-4181-90b2-0ffd28dd8786.cdn.bspapp.com/cloudstorage/81fffa58-caf9-4aea-97de-2525ecc51abd.jpeg'
})
}
编辑
js
// 修改
const onUpdate = async (_id) => {
await db.collection('hm-article').doc(_id).update({
title: ""+Date.now(),
category: 0
})
}
删除
js
// 删除
const onDelete = async (_id) => {
await db.collection("hm-article").doc(_id).remove()
}
unicloud-db
unicloud-db 数据库查询组件,可以在组件身上通过属性的方式查询数据库。
支持在在属性中指定要查什么表、哪些字段、以及查询条件
- collection 可以制定查询的单表、多表、或者是数组
- field 指定要返回的字段
- where 查询条件
- orderby 排序
- ....
其中 该组件还提供了许多使用的方法
-
loadMore
在列表的加载下一页场景下,使用ref方式访问组件方法,加载更多数据,每加载成功一次,当前页 +1
查询
vue
<template>
<view class="content">
<!-- <unicloud-db v-slot:default="{data, loading, error, options}" collection="hm-article" where="/强/.test(title)" field="title" orderby="category desc"> -->
<unicloud-db v-slot:default="{data, loading, error, options}" collection="hm-article" orderby="category desc">
<view v-if="error">{{error.message}}</view>
<view v-else>
<uni-table stripe emptyText="暂无更多数据">
<uni-tr>
<uni-th align="center">序号</uni-th>
<uni-th align="center">标题</uni-th>
<uni-th align="center">分类</uni-th>
<uni-th align="center">封面图片</uni-th>
<uni-th align="center">操作</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in data" :key="item._id" >
<uni-td>{{index+1}}</uni-td>
<uni-td>{{item.title}}</uni-td>
<uni-td>{{item.category}}</uni-td>
<uni-td>
<image :src="item.thumb" mode="widthFix"></image>
</uni-td>
<uni-td>
<button type="warn" >删除</button>
</uni-td>
</uni-tr>
</uni-table>
</view>
</unicloud-db>
</view>
</template>
分页
- 设置page-size,指定每一页多少条数据
- 监听 onReachBottom 事件,然后调用 unicloud-db 的loadMore方法即可
vue
<template>
<view class="content">
<!-- <unicloud-db v-slot:default="{data, loading, error, options}" collection="hm-article" where="/强/.test(title)" field="title" orderby="category desc"> -->
<unicloud-db :page-size="2" ref="refCo" v-slot:default="{data, loading, error, options}" collection="hm-article"
orderby="category desc">
<view v-if="error">{{error.message}}</view>
<view v-else>
<uni-table stripe emptyText="暂无更多数据">
<uni-tr>
<uni-th align="center">序号</uni-th>
<uni-th align="center">标题</uni-th>
<uni-th align="center">分类</uni-th>
<uni-th align="center">封面图片</uni-th>
<uni-th align="center">操作</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in data" :key="item._id">
<uni-td>{{index+1}}</uni-td>
<uni-td>{{item.title}}</uni-td>
<uni-td>{{item.category}}</uni-td>
<uni-td>
<image :src="item.thumb" mode="widthFix"></image>
</uni-td>
<uni-td>
<button type="warn">删除</button>
</uni-td>
</uni-tr>
</uni-table>
</view>
</unicloud-db>
</view>
</template>
<script setup>
import {
ref
} from "vue"
import {
onReachBottom
} from "@dcloudio/uni-app"
const refCo = ref(null)
// 分頁事件
onReachBottom(() => {
refCo.value.loadMore()
})
</script>
<style></style>
下拉刷新
vue
<template>
<view class="content">
<!-- <unicloud-db v-slot:default="{data, loading, error, options}" collection="hm-article" where="/强/.test(title)" field="title" orderby="category desc"> -->
<unicloud-db :page-size="2" ref="refCo" v-slot:default="{data, loading, error, options}" collection="hm-article"
orderby="category desc">
<view v-if="error">{{error.message}}</view>
<view v-else>
<uni-table stripe emptyText="暂无更多数据">
<uni-tr>
<uni-th align="center">序号</uni-th>
<uni-th align="center">标题</uni-th>
<uni-th align="center">分类</uni-th>
<uni-th align="center">封面图片</uni-th>
<uni-th align="center">操作</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in data" :key="item._id">
<uni-td>{{index+1}}</uni-td>
<uni-td>{{item.title}}</uni-td>
<uni-td>{{item.category}}</uni-td>
<uni-td>
<image :src="item.thumb" mode="widthFix"></image>
</uni-td>
<uni-td>
<button type="warn">删除</button>
</uni-td>
</uni-tr>
</uni-table>
</view>
</unicloud-db>
</view>
</template>
<script setup>
import {
ref
} from "vue"
import {
onReachBottom,
onPullDownRefresh
} from "@dcloudio/uni-app"
const refCo = ref(null)
// 下拉 事件
onPullDownRefresh(() => {
refCo.value.loadData({
clear: true //可选参数,是否清空数据
}, () => {
uni.stopPullDownRefresh()
})
})
onReachBottom(() => {
refCo.value.loadMore()
})
</script>
<style>
image {
/* width: 200rpx; */
}
</style>
新增
组件实例.add(value, options)
利用组件示例方法 add 即可实现新增
js
// 新增
const onAdd = async () => {
await refCo.value.add({
title: "華為鴻蒙日漸火熱" + refCo.value.dataList.length,
category: 2,
thumb: 'https://mp-c1674c18-fa0b-4181-90b2-0ffd28dd8786.cdn.bspapp.com/cloudstorage/81fffa58-caf9-4aea-97de-2525ecc51abd.jpeg'
})
refCo.value.loadData({
clear: true //可选参数,是否清空数据
})
}
编辑
组件实例.update(id, value, options)
js
// 修改
const onUpdate = async (_id) => {
await refCo.value.update(_id, {
title: "" + Date.now(),
category: 2,
thumb: 'https://mp-c1674c18-fa0b-4181-90b2-0ffd28dd8786.cdn.bspapp.com/cloudstorage/81fffa58-caf9-4aea-97de-2525ecc51abd.jpeg'
})
refCo.value.loadData({
clear: true //可选参数,是否清空数据
})
}
删除
组件实例.remove(id, options)
js
// 刪除
const onDelete = async (_id) => {
const {
confirm
} = await
uni.showModal({
content: '您確定刪除嗎'
});
if (confirm) {
await refCo.value.remove(_id)
refCo.value.loadData({
clear: true //可选参数,是否清空数据
})
}
}
云存储
开发者使用uniCloud
的云存储,无需再像传统模式那样单独去购买存储空间、CDN映射、流量采购
云存储的上传方式有3种:
- web界面:即在unicloud.dcloud.net.cn/ web控制台,点击云存储,通过web界面进行文件上传。该管理界面同时提供了资源浏览、删除等操作界面。
- 客户端API或组件上传:在前端js中编写
uniCloud.uploadFile
,或者使用uni ui的FilePicker组件,文件选择+上传均封装完毕。 - 云函数上传文件到云存储:即在云函数js中编写
uniCloud.uploadFile
客户端API
js
const onUpload = async () => {
//前端代码 // 注意小程序和h5端 選擇文件的api
uni.chooseImage({
count: 1,
success:async(res) =>{
if (res.tempFilePaths.length > 0) {
let filePath = res.tempFilePaths[0]
//进行上传操作
const result = await uniCloud.uploadFile({
filePath: filePath,
cloudPath: 'a.jpg'
});
}
}
});
}
uni-file-picker
文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
vue
<uni-file-picker fileMediatype="image"/>
云函数
云函数是运行在云端/后端的 JavaScript
代码,是基于 Node.js
的扩展。
在常规的 Node API
基础上,uniCloud的云函数环境内置了uniCloud
对象,这个对象内置了网络、数据库等各种
API。开发者未学习过 Node.js
也没有关系,只需要看uniCloud的文档,掌握这个uniCloud
对象的API即可
云函数体验
-
新建云函数 在
uniCloud/cloudfunctions
鼠标右键 云函数名称是hello
-
修改云函数代码
js'use strict'; exports.main = async (event, context) => { //event为客户端上传的参数 console.log('event : ', event) //返回数据给客户端 return {event,msg:"来自云函数的问候"} };
-
云函数模拟调用
-
客户端调用云函数
jsconst onCall = async () => { const result = await uniCloud.callFunction({ name: "hello"// 云函数的名字 }) console.log(result); }
云函数查询云数据库
js
'use strict';
exports.main = async (event, context) => {
const dbJQL = uniCloud.databaseForJQL({ // 获取JQL database引用,此处需要传入云函数的event和context,必传
event,
context
})
const result = await dbJQL.collection('hm-article').get() // 直接执行数据库操作
return result
};
云函数调用其他接口
云函数也可以直接调用其他接口来获取数据的。类似是服务器对服务器进行数据交互
-
在当前云函数目录下打开终端, 安装
axios
shnpm i axios
-
使用
axios
js'use strict'; const axios = require("axios") // 注意需要使用 commonjs 規範 exports.main = async (event, context) => { const result = await axios.get('https://api-hmugo-web.itheima.net/api/public/v1/home/swiperdata'); return result.data };
云对象
云对象可以更加方便的帮我们把一个云函数的不同功能独立出来,方便管理。
比如服务端编写一个云对象todo,该对象有add、get、remove、update等方法。客户端的js则可以直接import这个todo云对象,直接调用add等方法。
-
新建云对象 helloObj
-
编写代码
jsmodule.exports = { add(title, content) { return { errCode: 0, errMsg: '创建成功' } }, remove(id) { // .... return { errCode: 0, errMsg: '刪除成功' } } }
-
客户端直接调用
jsconst helloObj = uniCloud.importObject('helloObj') //第一步导入云对象 const onCallCloudObj = async () => { const result = await helloObj.add('新增',"內容") console.log(result); }
schema2code
根据数据表描述生成前端后端一体代码
DB Schema 在设置字段时,已经包含了大量相关信息,这些信息可以用来生成前端、后端一体代码 (crud) 。如
hm-article.json
json
// 文档教程: https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": ["title"],
"permission": {
"read": true,
"create": true,
"update": true,
"delete": true,
"count": true
},
"properties": {
"_id": {
"description": "ID,系统自动生成"
},
"title": {
"bsonType": "string",
"description": "文章的标题",
"label": "姓名",
"minLength": 2,
"maxLength": 20,
"errorMessage": {
"required": "{label}必填",
"minLength": "{label}不能小于{minLength}个字符"
}
},
"thumb": {
"bsonType": "file",
"description": "文章封面大图",
"title": "封面图片"
},
"category": {
"bsonType": "int",
"enum": [{
"text": "全部",
"value": 0
},
{
"text": "精华",
"value": 1
},
{
"text": "分享",
"value": 2
}
]
}
}
}
生成代码
鼠标选中要生成 增删改查的数据表 ,点击生成代码即可
此时如果没有数据,需要先自己在数据表中插入一些数据。可以在web控制台直接插入数据。
人脸识别
uni实人认证依赖 HBuilderX 3.7.6+,目前仅支持App平台。
人脸识别是一种比普通的手机验证码、账号密码更加安全的登录方式,适用在更加敏感的场合。人脸识别主要是识别 摄像头前活动的人脸 ,与姓名 和身份证号是
否匹配
开通服务
-
该服务需要开发者先在DCloud上进行实名认证
-
充值
业务流程
云端代码
-
新建云对象
faceVerifyObj
-
添加公共 uniCloud 拓展库
-
编辑代码
jsmodule.exports = { _before() { // _before是云对象中每个方法运行前都会执行的方法 this.frvManager = uniCloud.getFacialRecognitionVerifyManager({ requestId: this.getUniCloudRequestId() // 获取当前请求id }) }, // 获取CertifyId // metaInfo 设备信息 // realName 用户真实姓名 // idCard 身份证号码 async getCertifyId(metaInfo, realName, idCard ) { const result = await this.frvManager.getCertifyId({ realName, idCard, metaInfo: JSON.stringify(metaInfo) }) return result }, // 验证当前Certify是否有效 验证人脸是否通过 async getAuthResult(certifyId) { const result = await this.frvManager.getAuthResult({ certifyId }) return result } }
前端代码
js
const onCheckface = async () => {
try {
// 获取实人认证设备信息
const metaInfo = uni.getFacialRecognitionMetaInfo();
// 调用云函数 获取人脸设备信息
const result = await faceVerifyObj.getCertifyId(JSON.parse(metaInfo),"用户名","身份证")
// 调起人脸识别
await uni.startFacialRecognitionVerify({
certifyId: result.certifyId,
progressBarColor: "#CC0000", //刷脸圈的颜色
screenOrientation: "port", //认证界面UI朝向
})
// 验证人脸识别是否通过
const res = await faceVerifyObj.getAuthResult(result.certifyId)
// {
// "errCode": 0,
// "errMsg": "",
// "authState": "SUCCESS",
// "qualityScore": 92.20459747314453, // 活体检测结果分数
// "verifyScore": 99.53412829108788 // 人脸图片质量分
// }
console.log(res);
} catch (e) {
//TODO handle the exception
console.log(e);
}
}
注意
注意
- 获取
certifyId
后,仅在24
小时内可正常调用getAuthResult
接口获取认证结果,超过24
小时后请求该接口将返回56001 请求记录已过期
错误。 certifyId
成功调用后,无论认证结果是否匹配,都仅可再调用5
次getAuthResult
接口获取认证结果,超过5
次后请求该接口将返回56002 请求次数已超限
错误。pictureUrl
照片地址有效期为15
分钟,从查询时开始计时,如有存储需求请尽快处理。