uniCloud云开发笔记一
云空间配置
创建云空间
- 左上角新建 - 项目 - 输入项目名 - 下面勾选启用uniCloud - 选择后面的服务商这里建议阿里云(反正都一样) - 创建
- 创建完成打开项目 - 找到uniCloud目录(后面有提示未关联云服务空间) - 右键 - 关联云服务空间或项目 - 如果提示缺少appid啥的(有提示找到manifest.json点击重新获取即可,没登陆的话会要求登录) - 然后再次右键点击关联云服务空间或项目
- 第一次创建云开发的话这里是空的(每新建一次代表一个新项目的云空间) - 点击新建 - 这里会跳转到开发者中心后台 - 点击左边侧边栏的uniCloud(没有实名认证的这里会提示需要认证才能使用并且会跳转到实名页面,接下来按提示认证即可)
- 然后点击到uniCloud那个页面 - 点击右上角新建服务空间(新人要同意一下协议) - 建议使用阿里云作为服务商(对比下就知道了,阿里云有免费额度,可以开发中使用,另外收费的额度也不是特别贵) - 选择阿里云 - 输入服务空间名称(也就是相当于自己的后端项目名称) - 选择免费版本(用户量大了再换收费版) - 点击立即购买 - 点击确认开通 - 这样我们就有了一个免费的服务空间了(时长是一个月,后面需要购买,不够阿里云挺便宜的) - 然后等初始化完毕后进行下面操作(初始化的过程可能比较长,耐心等待)
- 初始化完毕后点击服务空间右侧的详情进入服务空间后台 - 点击旁边的变配就是购买其他容量的云空间
- 接下来点击详情进入服务空间后台
创建数据库
- 进入服务空间后台 - 点击云数据库 - 云数据库 - 点击右侧页面左上角的+新建数据表
- 输入表名(下面的分类千万不要勾选,不然会出现很多你不认识的字段) - 点击创建
- 点击新建的表 - 点击添加记录 - 例如我下面的格式
js
{
"name": "张三",
"age": 20,
"sex": "男"
}- 输入完成后页面上面就会显示刚刚添加进去的表数据了,可以发现自动生成了一个_id值,这个是云数据库自动生成的,除此之外还有更多配置,如字段描述,唯一值,权限什么的等等各种配置,可以查阅我下面发的文档地址进行查询 点击查看更多字段相关的配置
- 接下来创建三个记录,加上面这个一共四个
js
{
"name": "李四",
"age": 22,
"sex": "男"
}js
{
"name": "王二",
"age": 18,
"sex": "女"
}js
{
"name": "麻子",
"age": 16,
"sex": "女"
}- 有了以上记录我们就可以在代码里面做操作了(后面会用到)
项目连接云空间
- 回到HBuilder里面 - 找到我们的项目 - 展开找到uniCloud - 后面显示未关联云服务空间 - 右键 - 关联云服务空间或项目 - 选择刚刚我们创建的云空间 - 点击关联即可 - 再次查看后面不显示(未关联云服务空间)了
云函数创建和使用
- 找到项目的uniCloud/cloudfunctions这个文件夹 - 选中后右键 - 新建云函数/云对象 - 输入函数名称(相当于接口名称,要通熟易懂) - 使用默认模版 - 点击创建 - 后续代码都是在这个云函数里面的index.js里面去写,写后端的处理逻辑,默认的模版打印了一下传进来的参数信息,将参数传递给客户端,我们不动这个逻辑,接下来演示怎么发请求以及传递参数
- 在页面代码里面加入如下代码即可发请求,代码如下(我这里使用的是vue3模板)
js
<script setup>
import { onMounted } from 'vue';
onMounted(()=>{
uniCloud.callFunction({
name:"demo01", // 这个name就是云函数名称
data:{ // 不传参的话可以把data去掉
name:'哈哈',
age:20
}
}).then((res)=>{
console.log(res); // 这个res返回的就是上传的参数
})
})
</script>- 然后启动项目,查看打印效果,例如选择浏览器运行,运行后会发现同时打开了原有的控制台和uniCloud控制台可以查看云函数打印的信息,也就是模板默认提供的event也就是参数信息
- 如果运行同时报错了跨域 - 打开云空间后台 - 在云数据库同级下面有个跨域配置 - 例如我本地地址为
192.168.1.92:5173- 则点开跨域配置 - 新增域名 - 将我本地域名添加进去即可 - 如果项目放到静态网页托管之类的平台也是同样将其他平台域名添加进去即可点击查看web端跨域解决方案
云数据库操作
上面已经讲了怎么创建数据库并且新增了四条数据在里面
云函数通过传统方式操作数据库
查
查询全部数据
新增getData云函数,代码如下
js
'use strict';
const db = uniCloud.database(); // 个人理解为是获取数据库实例
exports.main = async (event, context) => {
// 获取demo集合的引用,集合就是表,get()方法默认是获取全部数据
let res = db.collection('demo').get()
//返回数据给客户端
return res
};页面发请求代码如下
js
<script setup>
import { onMounted } from 'vue';
onMounted(()=>{
uniCloud.callFunction({
name:"getData", // 这个name就是云函数名称
}).then((res)=>{
console.log(res); // 这个res返回的就是上传的参数
})
})
</script>查看控制台打印可以发现打印到了所有的数据
查询数据总条数
js
'use strict';
const db = uniCloud.database(); // 个人理解为是获取数据库实例
exports.main = async (event, context) => {
// 获取demo集合的引用,集合就是表,count()方法返回数据总条数
let res = db.collection('demo').count()
//返回数据给客户端
return res
};页面发请求代码同上
分页查询
js
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
// 查询指定条数(如下只查询两条数据)
// let res = await db.collection('demo').limit(2).get()
// 查询指定条数并跳过多少条(就是跳过前两条,从第三条开始查询数据)
// skip公式为: skip((pageNum - 1) * pageSize) pageNum是当前页码,pageSize是每页数量
// 例如查询每页10条数据,从第三页开始,则limit(10).skip((3 - 1) * 10)
let res = await db.collection('demo').limit(2).skip(2).get()
//返回数据给客户端
return res
};页面发请求代码同上
正序倒序查询
js
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
// 如下就是根据id升序排列
let res = await db.collection('demo').orderBy('_id','asc').get()
// 如下就是根据id降序排列
// let res = await db.collection('demo').orderBy('_id','desc').get()
//返回数据给客户端
return res
};页面发请求代码同上
查询字段过滤
js
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
// 过滤字段(如下代码只返回name字段数据)
let res = await db.collection('demo').field({"name":true}).get()
//返回数据给客户端
return res
};where查询
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
// 根据姓名查询张三的数据
// let res = await db.collection('demo').where({
// name:'张三',
// }).get()
// 查询姓名为张三,并且年龄为20的数据
// let res = await db.collection('demo').where({
// name:'张三',
// age:20
// }).get()
// 使用函数过滤查询(更多方法可以参考官方文档: https://doc.dcloud.net.cn/uniCloud/cf-database.html#dbcmd)
let res = await db.collection('demo').where({
// age: dbCmd.eq(20) // 查询年龄为20的用户的数据
// age: dbCmd.gt(20) // 查询年龄大于20的用户的数据
// age:dbCmd.gt(18).and(dbCmd.lt(40)) // 查询年龄大于20并且小于40的数据
// age:dbCmd.and(dbCmd.gt(20),dbCmd.lt(40)) // // 查询年龄大于20并且小于40的数据
// age:dbCmd.in([20,22]) // 查询年龄是20和22的数据
// age:dbCmd.nin([20,22]) // 查询年龄不是20和22的数据
// age:dbCmd.or(dbCmd.lt(20),dbCmd.gt(40)) // 查询年龄是小于20或者大于40的数据
// age:dbCmd.lt(18).or(dbCmd.gt(20).and(dbCmd.lt(40))) // // 查询年龄小于18或者年龄大于20小于40的数据
}).get()
return res
};正则表达式模糊搜索
点击查看官方文档: https://doc.dcloud.net.cn/uniCloud/cf-database.html#regexp
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
let keyword = '张'
let res = await db.collection('demo').where({
name:new RegExp(keyword,"ig") // 不区分大小写和全局匹配,参数一就是正则表达式
}).get()
return res
};
// 例如我一个输入框模糊关键词要去匹配_id和title字段,,同时还要判断是否传入status状态字段,,也就是说这是并联的关系,_id和title字段是或的关系,,,可以按照如下方式去写
let obj = {}
// 判断是否传入status字段
if (body.status) {
obj['status'] = body.status
}
// body.title 要判断是否传入模糊关键词,没传入的话就只放obj字段
const res = await dbs.collection("cloudDrvResourceTable").where(body.title ? dbCmd.and(
dbCmd.or([{
cloud_drv_resource_title: new RegExp(body.title, 'i')
}, {
_id: body.title
}, ]), // 模糊字段
obj // 再把需要并的字段状态并进来
) : obj).get()增
单个新增
新增onceAddData云函数,代码如下
js
'use strict';
const db = uniCloud.database(); // 个人理解为是获取数据库实例
exports.main = async (event, context) => {
let {
name,
age,
sex
} = event // 解构参数
// 获取demo集合的引用,集合就是表,add()方法添加数据
let res = db.collection('demo').add({
name,
age,
sex
})
//返回数据给客户端
return res
};页面发请求代码如下
js
<script setup>
import { onMounted } from 'vue';
onMounted(()=>{
uniCloud.callFunction({
name:"onceAddData", // 这个name就是云函数名称
data:{ // 传递的参数
name:'新增数据',
age:40,
sex:'女'
}
}).then((res)=>{
console.log(res); // 这个res返回的就是上传的参数
})
})
</script>批量新增
新增moreAddData云函数,代码如下
js
'use strict';
const db = uniCloud.database(); // 个人理解为是获取数据库实例
exports.main = async (event, context) => {
let {arr} = event
// 获取demo集合的引用,集合就是表,add()方法添加数据
let res = db.collection('demo').add(arr)
//返回数据给客户端
return res
};页面发请求代码如下
js
<script setup>
const sendData = ()=>{
uniCloud.callFunction({
name: "moreAddData", // 这个name就是云函数名称
data: {
arr: [{ // 传递的参数
name: '新增数据1',
age: 29,
sex: '女'
}, {
name: '新增数据2',
age: 38,
sex: '男'
}, {
name: '新增数据3',
age: 60,
sex: '女'
}]
}
}).then((res) => {
console.log(res); // 这个res返回的就是上传的参数
})
}
</script>改
单个修改
新增indexUpdateData云函数,代码如下
js
'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
let keyword = '张'
// 单个数据修改
// 如果修改的字段不存在,数据库会新增这个字段
let res = await db.collection('demo').doc("67a324db816a3ff63b232881").update({
name:'张三',
age:28
})
return {
msg:'修改成功',
res
}
};页面发请求代码如下
js
<script setup>
const sendData = ()=>{
uniCloud.callFunction({
name: "indexUpdateData", // 这个name就是云函数名称
}).then((res) => {
console.log(res); // 这个res返回的就是上传的参数
})
}
</script>批量修改
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
let keyword = '张'
// 批量数据修改
// 如果修改的字段不存在,数据库会新增这个字段
let res = await db.collection('demo').where({
_id:dbCmd.in(['67a325c755b337b42b584294','67a324db816a3ff63b232881'])
}).update({
name:'哈哈',
age:30
})
return {
msg:'修改成功',
res
}
};页面发请求代码同上
字段是数组或对象的修改
云数据库新增如下一条记录
js
{
"name": "运动员",
"age": 25,
"sex": "男",
"hobby": [
"篮球",
"足球",
"乒乓球",
"羽毛球"
],
"detial": {
"address": "南京",
"phone": 15900000000
}
}执行修改
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
let keyword = '张'
// 数组或者对象数据的修改
let res = await db.collection('demo').where({
_id: '67a4840ce0ec19c842438380' // 根据id获取到这条数据
}).update({
hobby: { // 修改数组的方法,根据下标设置
2: '铅球' // 将数组的下标索引为2的数据改成铅球
},
// detial:{
// address:'北京' // 将对象的address的数据改成北京
// }
"detial.address": '上海' // 将对象的address的数据改成上海
})
return {
msg: '修改成功',
res
}
};更新操作符
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
// 更新操作符的使用
let res = await db.collection('demo').where({
_id: '67a4840ce0ec19c842438380' // 根据id获取到这条数据
}).update({
// hobby: dbCmd.unshift(['游泳','跳水']) // 给数组向前追加两个数据
// hobby: dbCmd.push(['打游戏','看电视']) // 给数组向后追加两个数据
// hobby:dbCmd.pop() // 删除数组最后一个元素
// hobby:dbCmd.shift() // 删除数组最前的一个元素
// age:dbCmd.inc(1) // age字段自增1,自减的话就是-1,常用用直播间点赞,网站访问量等等自增数据的操作
// age:dbCmd.mul(2) // age字段自乘以2
})
return {
msg: '修改成功',
res
}
};覆盖性修改(不会保留其他字段,修改时传什么字段这个数据就是什么)
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
// 更新操作符的使用(这里只能使用doc获取引用,使用where会报错)
let res = await db.collection('demo').doc('67a4840ce0ec19c842438380').set({
tel:12121212212 // 这样的话整条数据就只要tel
})
return {
msg: '修改成功',
res
}
};删
单个删除
新增indexDeleteData云函数,代码如下
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
// 根据id删除
// 方式一
let res = await db.collection('demo').doc('67a325ecc3b5c934eb45487b').remove()
// 方式二
// let res = await db.collection('demo').where({
// _id:'67a4840ce0ec19c842438380'
// }).remove()
return {
msg: '修改成功',
res
}
};条件删除(批量删除)
新增indexDeleteAllData云函数,代码如下先将数据导出避免丢失 - 点击导出 - 选择json - 删除完毕后点击导入再刷新数据就回来了
js
'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
// 条件删除
let res = await db.collection("demo").where({
age:dbCmd.gt(18) // 删除年龄大于18的所有数据
}).remove()
return {
msg: '修改成功',
res
}
};云函数的上传和下载
- 找到uniCloud/cloudfunctions文件夹 - 右键 - 上传所有的云函数 - 控制台提示上传完成 - 打开云空间后台 - 云函数/云对象 - 函数/对象列表 - 这里就会显示我们上传的云函数了 - 也可以自定义域名(方式可以查看下面的前端项目托管,基本一样的)
- 上传完成后可以打开控制台 - 点击连接远程云函数 - 重新启动项目 - 这时候接口访问的就是远程的云函数代码了,本地的云函数代码对请求无影响
- 例如本地代码不小心删了 - 找到uniCloud/cloudfunctions文件夹 - 右键 - 下载所有的云函数 - 就可以把远程的下载下来了
- PS:打包项目必须要连接远程云函数,本地云函数打包后失效的
前端项目托管
完成了上面的增删改查就可以去做一些网页项目了,当我们做完打包后可以托管到云服务器,具体配置如下
- 找到云空间后台 - 前端网页托管 - 上传文件夹(建议选择含根目录,例如我这里上传
wxapp文件夹下面有个index.html文件) - 上传完成后 - 打开上方tab里面的参数配置选项 - 往下看域名信息里面有个默认域名 - 查看默认域名 - 复制到浏览器打开 - 然后在路径后面拼上
/wxapp即可访问到里面的index.html页面 - 如果根目录下有
index.html,默认访问的是这个页面
配置域名
一般提供的默认域名仅供测试使用,正式版会有访问限制,解决办法就是配置自己的域名即可不受限制 购买域名和备案这里我就不讲了,如果有域名的话,看下面教程
- 例如我的买的并备案的域名为
xxx.top - 点击下面添加域名,前缀随便输入,后面跟上自己买的域名,如
demo.xxx.top - 点击确定后,第一次配置会有个弹窗,后续配置就应该没弹窗了,这个没实测过,如果出现弹窗按照如下操作(切记不要关闭页面)
出现弹窗提示验证
- 输入域名
- 选择DNS解析验证
- 记住下面的记录类型/主机记录和记录值
- 打开域名服务商的域名管理(我这里用的是阿里云) - 点击解析 - 添加记录 - 将记录类型选择好 - 主机记录和记录值分别填写上点击确定即可
- 回到域名管理页面
- 点击验证验证通过后即可
上面操作主要是为了获取cname值,不管有没有上面的弹窗只要是添加到列表里面后面都要执行下这个操作
- 找到我们在域名管理添加的域名,记住这个域名,并且复制一下后面的
CNAME值 - 打开域名服务商的域名管理(我这里用的是阿里云) - 点击解析 - 添加记录 - 将记录类型选择
CNAME- 主机记录输入云开发后台添加的域名前缀,记录值就是上面让复制的CNAME分别填写上点击确定即可 - 然后访问域名加上
/wxapp后缀即可访问/wxapp/index.html页面了
可以发现域名是http的这个不是安全协议,这里教大家怎么改成https的
- 点击此网站,注册登陆进去:https://freessl.cn/
- 点击左侧的证书列表 - 申请证书 - 跳转到新页面 - 找到免费证书这一栏 - 我这里选择的是单域名(各位参考自己实际去选择) - 立即申请 - CSR来源选择浏览器生成 - 证书域名填写我们刚刚在云开发后台新增的这个域名 - 验证方式选择DNS - 加密算法选择RSA - 点击提交
- 出现的弹窗 - 复制主机记录/记录类型/记录值
- 打开域名服务商的域名管理(我这里用的是阿里云) - 点击解析 - 添加记录 - 将记录类型选择好 - 主机记录和记录值分别填写上点击确定即可
- 然后点击我已配置完成
- 关闭窗口后点击验证两个字 - 提示验证成功即可
- 然后稍等一会等待证书下发
- 证书下发后点击获取就自动下载了
- 下载完查看压缩包内是否有
.pem和.key文件,有时候生成不完整,如果不全重新操作生成 - 找到域名信息的域名 - 点击右侧更新证书 - 将
.pem文件用记事本打开然后全选里面内容,复制粘贴到第一个输入框内 - 同理.key内容也是这个粘贴到输入框内 - 点击确定 - 点击http强制跳转https开关打开即可 - 然后就会发现域名从http转成了https访问了
- 不过要注意证书有效期,快到期了一定要重新换证书
微信小程序和APP的打包非常简单这里就不讲了,可以查看如下视频:
文件上传(这里演示图片上传)
自动上传(不推荐)
- uni-file-picker文档明确表示,如果绑定了云空间,点击选择文件后默认会上传到云空间 - 云存储 - 空间内置存储里面,但是这种做法不推荐,加入用户上传一个错误的图片,然后用户又重新上传,那这就导致空间内多一个垃圾图片了,如下代码:
js
<template>
<uni-file-picker v-model="imageValue" fileMediatype="image" mode="grid" @select="select" @progress="progress"
@success="success" @fail="fail" />
</template>
<script setup>
import {
ref
} from 'vue'
const imageValue = ref([])
// 获取上传状态
const select = (e) => {
console.log('选择文件:', e)
}
// 获取上传进度
const progress = (e) => {
console.log('上传进度:', e)
}
// 上传成功
const success = (e) => {
// 这里会给我们回调一个在线地址,包含其他的详细的信息
console.log('上传成功',e)
}
// 上传失败
const fail = (e) => {
console.log('上传失败:', e)
}
</script>然后打开页面选择文件就会自动上传到云后台了
手动上传
1.还是跟上面一样的上传,只是变成了手动触发,不能自定义
js
<template>
<uni-file-picker v-model="imageValue" :auto-upload="false" fileMediatype="image" mode="grid" @select="select" @progress="progress"
@success="success" @fail="fail" ref="files"/>
<button @click="upload">上传文件</button>
</template>
<script setup>
import {
ref
} from 'vue'
const imageValue = ref([])
const files = ref(null)
const upload = ()=>{
// 触发此方法就会上传
files.value.upload()
}
// 获取上传状态
const select = (e) => {
console.log('选择文件:', e)
}
// 获取上传进度
const progress = (e) => {
console.log('上传进度:', e)
}
// 上传成功
const success = (e) => {
// 这里会给我们回调一个在线地址,包含其他的详细的信息
console.log('上传成功',e)
}
// 上传失败
const fail = (e) => {
console.log('上传失败:', e)
}
</script>2.自定义上传
js
<template>
<button @click="checkedFile">选择图片</button>
<button @click="chooseFile">开始上传</button>
<image v-if="temFile.length>0" :src="temFile[0].path" mode=""></image>
</template>
<script setup>
import {
ref
} from 'vue';
const temFile = ref([])
const checkedFile = () => {
// 除了选择图片,还有文件,视频等等,api都是choose开头的
uni.chooseImage({
sizeType: ['original'], // original原图 compressed压缩图 默认两者都有
count: 1, // 最多选择1个图片
success: (res) => {
// 这里会返回一个本地服务器文件地址
console.log(res);
temFile.value = res.tempFiles
}
})
}
const chooseFile = () => {
uniCloud.uploadFile({
filePath: temFile.value[0].path,
cloudPath:temFile.value[0].name
}).then(res => {
// 这里包含返回的文件在线地址
console.log('上传云空间成功',res);
})
}
</script>