一个H5页面,让你看懂数据库增删改查。
写在最前面
我是自学前端的小白,所以只能演示基本的操作,关于复杂的连表增删改查,还没有研究过。 就以这个demo
数据库为原型,完成查询、新增、修改、删除的基本操作示例。
1、查询,①在网站初始化时需要调用查询;②用户查询电户号时,需要调用查询;③新增或删除电户信息时,需要比对数据,也需要调用查询。
2、新增,分为①在demo
下,再新增_id
,并添加字段和值;②在指定_id
下指定位置新增。
3、更新,分为①覆盖式更新;②在同一个_id
下指定位置更新数据。
4、删除,分为①指定_id
全部删除;②在指定_id
下,指定位置删除数据。
在云函数写好之后,还需页面调用处理返回的数据,文末有示例。
一、准备云数据库
- 云数据库有两个,'initial'和'demo',后面有展开数据演示。
- 'initial',用于初始化页面。
- 'demo',用于增删改查。
二、编写云函数
- uniCloud数据库,允许在网页端直接使用
uniCloud.callFunction
函数调用数据库的数据。- 但是,建议使用云函数调用,这样数据更安全。
- 云函数的主流是路由——自动匹配对应的云函数去处理数据,我还不会,所以就写了五个云函数,在页面要用哪个就调用哪个。
2.1 云函数默认目录。
uniCloud/cloudfunctions/云函数名称/云函数名称.js
2.2 uniCloud数据库操作基于mongoDB,可以查询相关文档。
三、获取数据的云函数
await db.collection('demo').field({}).get();
3.1 初始化页面获取数据的方法
- 初始化页面,需要调用的云数据库,名称
initial
,展开如下:
复制代码{
"_id":"603a0b27c9e7be00013b5e33",
"ArrList":["沙沟村","大东沟村","罗家坡村","小山岔村","渡口村","七家洼村"]
}
---------------华丽的---------分割线-------------
{
"_id":"603a120b20be4e000120b8f6",
"groupArr": {
"0": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],
"1": ["一变","二变","三变"],
"2": ["一变","二变","三变","四变"],
"3": ["一变","二变","三变","四变","五变"]
--------后面-------还有------内容-------省略------
}
}
- 初始化云函数,名称也叫
initial
,代码如下: - get()获取的数据存放在data数组中,第一个
_id
的数据,就是data[0],第二个_id
的数据,就是data[1]
复制代码'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
let [str] = event;
if(str ==='initial'){
let res = await db.collection('initial').field({_id:0,ArrList:1,'groupArr.0':1}).get();
//get()获取的数据存放在data数组中,第一个`_id`数据,就是data[0]
let cunList = res.data[0].ArrList;
//get()获取的数据存放在data数组中,第二个`_id`数据,就是data[1]
let zuList = res.data[1].groupArr[0];
//code的数字,只是为了前端if判断时好用,并没有什么实际意义。
return {
code:888,
msg:'初始化数据成功',
cunList,
zuList
}
}else{
return{
code:400,
msg:'您请求的数据格式有误'
}
}
}
- 前端页面调用的代码,在
onLoad
生命周期内,将查询的数据赋值给两个数组,再渲染到页面中(两个列表中)。 - 页面端调用的代码
this.$api.HandleUnicloud(cloudName, mydata){res=>{}}
,如何而来,文末有详解
复制代码export default {
data() {
return {
cun_list: [],
zu_list: []
}
}
onLoad() {
let mydata = ['initial'];
let cloudName = 'initial';
this.$api.HandleUnicloud(cloudName, mydata).then(res => {
this.cun_list = res.cunList;
this.zu_list = res.zuList;
});
}
}
3.2 ★重点★ 查询返回指定字段的数据
-
示例
demo
数据库,由六部分组成,每一个_id
独立为一个单元。 -
数据库展开
复制代码{
"_id":"603eeaa40daee300011f18f4",
"villages": {
"name": "沙沟村",
"id": 0,
"groupArr": ["沙沟一变","沙沟二变","沙沟三变","同心一变","双明一变","双明二变"],
"group-1": [{"3102568889": "翟**"},{"3105360550": "李**"},{"3105360619": "马**"},..省略..],
"group-2": [{"3078734642": "刘**"},..省略..],
"group-3": [],
"group-4": [],
"group-6": []
}
}
------------华丽的-----------分割线------------------
{
"_id":"603eeab4e857bd0001690475",
"villages": {
"name": "大东沟村",
"id": 1,
"groupArr": ["一变","二变","三变"]
}
}
------------华丽的-----------分割线----------------
{
"_id":"603eeab4e857bd0001690475",
"villages": {
"name": "XXX村",
"id": 2,
"groupArr": ["一变","二变","三变","四变"]
}
}
-------后面----还有-----数据-----不再-----展示-----
field({})
,可以返回指定字段的内容,必须使用get()
方法才能获取到数据。1
表示显示,没有标注的数据不显示。但是_id
是默认显示的。field({'ArrList':1,_id:0})
,不显示_id
,查询关于ArrList
的信息,field({'villages.group-2':1})
查询 villages 数组或对象内 group-2 的内容。- 与变量相结合的查询方式,有二种:
const groupNum = "group-3";
field({[`villages.${groupNum}`]:1})
const groupNum = "group-4";
field({['villages.'+ groupNum]:true})
复制代码'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
//event==mydata: { cunIndex: 0, groupName: 'group-1', userObj: { username: '', usernum: '' }, pageNum: 0, rowsNum: 10 }
let {cunIndex,groupName,userObj,pageNum,rowsNum} = event;
let resData = await db.collection('demo')
.field({_id:0,[`villages.${groupName}`]:1})
.get();
//resList等于当前村下的,当前变电组的,全部用户的信息
let resList = resData.data[`${cunIndex}`].villages[`${groupName}`];
//如果当前村的变电组不存在,或者变电组内没有数据时,调用
if(!resList||resList.length===0){
return {
code:400,
msg:'该村变电组内还未收录用户信息',
}
}
//这一段为翻页时调用
//请求的数据条数(rowsNum默认10条)
//pageNum当前点击的页码(由于是H5的原因默认是1)
let pageStarNum = (pageNum - 1) * rowsNum;
let pageEndNum = pageStarNum + rowsNum;
let pagesTotal = resList.length;
//pages表示返回的数据,在页面中总共要显示多少页
let pages = parseInt(pagesTotal/rowsNum);
//前端页面点击页码后,显示从第几条数据到第几条数据的列表
let resArr = resList.slice(pageStarNum,pageEndNum);
//resObj用于存放,数据库查找到的电户信息
let resObj = {};
//遍历当前变电组内所有的用户信息,当遍历的姓名与查询的姓名一致时
//把结果追加给resObj,使用合并对象的方法Object.assign(resObj,item)也行
resList.forEach(item=>{
if(Object.values(item)==userObj.username){
resObj = {...item}
}
})
//当用户没有输入姓名,直接查询,会获取全部列表
if(userObj.username===''){
return {
code:200,
msg:'当前查询的是:该变电组内所有用户的信息',
resArr,
pages
}
}
//当输入的姓名,查询不到时调用
//返回当前村、变电组,全部列表数据
//pages是总页数
if(Object.keys(resObj).length===0){
return {
code:404,
msg:'抱歉!该变电组内未收录此用户的信息',
resArr,
pages
}
}
//当输入的姓名,数据库中有时调用
//msg的信息可以使用模板字符串
return {
code:200,
msg:`「 ${userObj.username} 」的电户号,查询结果如下:`,
resObj
}
}
四、新增数据的云函数
4.1 在原数据外,新增一个_id,add()
- 新增单一数据,用大括号包裹数据
{"name": "张三"}
。 - 新增多条数据,用中括号包裹数据
[{"name": "张三"},{"name": "李四"},{"name": "王五"}]
。
复制代码const db = uniCloud.database();
exports.main = async (event, context) => {
let resData = await db.collection('demo')
.add([{"name": "张三"},{"name": "李四"},{"name": "王五"}]);
let resList = await db.collection('demo').get();
return {
code:200,
msg:'添加数据成功',
resList
}
};//数据返回结果
{
"code": 200,
"msg": "添加数据成功",
"resList": {
"data": [{
"_id": "60210b53ef338d00016d2404",
....此处 .... 省略 ....一万字....
},
{
"_id": "6038d46620be4e00011e5cf4",
"name": "张三"
},
{
"_id": "6038d46620be4e00011e5cf5",
"name": "李四"
},
{
"_id": "6038d46620be4e00011e5cf6",
"name": "王五"
}
}]
}
4.2 在指定_id内,指定位置新增。
-
doc('_id').update();
方法可用于更改,也可用于新增。 -
普通数组添加、删除数据,官方文档中有示例,这里演示的是,数据为对象的数组
"group-1":[{key:value},{key:vlaue}]
如何新增。 -
update(),需紧随
doc()
之后,doc()
内写指定数据的_id
,因为一个集合内可能有多个_id
-
在
update()
内引用变量,需要使用[`${变量名}`]
-
在数组尾部新增对象,可以在中括号内写模板字符串
dbCmd.push([{...addUserObj}])
复制代码'use strict';
const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
let {cunIndex,groupName,userObj} = event;
if(userObj.username==''||userObj.usernum==''){
return{
code:400,
msg:'新增数据不能为空'
}
}
let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();
//用于获取_id,存放与data[{_id:***},{_id:***},{_id:***},***]中
let id = resData.data[`${cunIndex}`]['_id'];
let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];
let isTrue = true;
//先查询,用户要新增的电户号码,在数据库中,有没有,有就赋值false
if (groupArr) {
groupArr.forEach(val=>{
if(Object.keys(val)==userObj.usernum){
isTrue = false;
}
});
//如果数据库中没有该电户号码,就在对应村、变电组的尾部新增该数据
if(isTrue){
let addUserObj = {[`${userObj.usernum}`]:userObj.username};
let resSucc = await db.collection('demo')
.doc(`${id}`)
.update({
villages: {
[`${groupName}`]: dbCmd.push([{...addUserObj}])
}
})
return {
code: 200,
msg: '数据添加成功',
resSucc
}
//当数据库中有该电户号码时,就提示已经存在
}else{
return {
code: 400,
msg: `抱歉!电户号「 ${userObj.usernum} 」已经存在`
}
}
}
//如果该村还未创建该变电组,就新建变电组,之后再新增用户信息
if (!groupArr) {
let resSucc = await db.collection('demo')
.doc(`${id}`)
.update({
villages: {
[`${groupName}`]: dbCmd.set([{
[`${userObj.usernum}`]: userObj.username
}])
}
})
return {
code: 200,
msg: '创建变电组成功,数据添加成功',
resSucc
}
}
}
五、更新数据的云函数
5.1 覆盖式更新
- 覆盖式更新的意义不大,会将原数据彻底清除,一般情况下用不到。
update({'villages':dbCmd.set({key:value})})
将villages做为字段,后面跟一个对象
复制代码const db = uniCloud.database();
const dbCmd = db.command;
exports.main = async (event, context) => {
let resSucc = await db.collection('demo')
.doc("600bfa4d7f06f30001b47259")
.update({
'villages':dbCmd.set({
"6640059601": "张三"
})
}
);
let resObj = await db.collection('demo').get();
return {
code:200,
resObj,
resSucc
}
}
//返回的数据结果 villages下只剩下一个对象了
"villages": {"6640059601":"张三"}
5.2 指定_id
下,指定位置更新。
- 指定位置更新,同上面的update()方法一致,这里省略。
六、删除数据的云函数
6.1 删除指定_id的数据库的全部数据
-
collection.doc(_id).remove()
-
doc()
内只能写字符串或者数字,可以使用ES6模板字符串doc(`${id}`)
复制代码// 删除指定_id的数据
const db = uniCloud.database();
exports.main = async (event, context) => {
const id = '60388f7eb6ce210001cbbf14';
await db.collection('demo')
.doc(`${id}`)
.remove();
let resData = await db.collection('demo').get();
return resData;
};
6.2 删除指定位置的数据
- 在update()内使用remove(),方法挂载在command下,不能用于数组,删除后,数组原索引位置会变成null。但是可以用于对象,删除key就等于删除了该对象。doc(`${id}`).update({villages:{name:dbCmd.remove()}})
- 更新数组,可以先获取数组,再修改数组,最后把新数组更新到原位置即可。update({villages:{[`${groupName}`]:[...groupArr]}})
复制代码'use strict';
const db = uniCloud.database();
exports.main = async (event, context) => {
let {cunIndex,groupName,userObj} = event;
let resData = await db.collection('demo').field({_id: 1,[`villages.${groupName}`]: 1}).get();
let id = resData.data[`${cunIndex}`]['_id'];
let groupArr = resData.data[`${cunIndex}`].villages[`${groupName}`];
let isTrue = false;
var index = 0;
if (!groupArr) {
return {
code: 400,
msg: '抱歉!该村还未创建此变电组数据',
resSucc
}
};
groupArr.forEach((val,i)=>{
if(Object.keys(val)==userObj.usernum){
isTrue = true;
index = i
}
});
//先查询数据在数组中的索引,使用splice,删除数据,把获得的新数组,更新到原位置处
if(isTrue){
groupArr.splice([`${index}`],1);
let resData = await db.collection('demo')
.doc(`${id}`)
.update({
villages:{
[`${groupName}`]:[...groupArr]
}
})
return {
code: 200,
msg: `「 ${userObj.usernum} 」数据删除成功`,
index,
groupArr,
resData
}
};
return {
code: 400,
msg: '数据删除失败,原因:电户号错误'
}
}
七、处理云函数返回数据的工具函数
- 工具函数的路径
common/api/index.js
- HandleUnicloud有两个参数,用于
uniCloud.callFunction({name,data})
传参。 cloudName
表示,需要调用哪个云函数。mydata
表示,用户向云函数传递的数据。
复制代码const HandleUnicloud = (cloudName,mydata)=>{
return new Promise((reslove,reject)=>{
uniCloud.callFunction({
name:cloudName,
data:mydata
}).then(res=>{
if(res.result){
reslove(res.result)
}else{
reject(res.result)
}
}).catch(res=>{
console.log(res);
})
});
};
export default{
HandleUnicloud
}
八、全局注册处理云函数数据的工具函数
- 先引入
import api from './common/api'
- 再注册
Vue.prototype.$api = api
复制代码import Vue from 'vue'
import App from './App'
import api from './common/api'
Vue.config.productionTip = false
Vue.prototype.$api = api
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
九、页面调用的方法
this.$api.HandleUnicloud()
复制代码addData() {
//用户传给云函数的数据,赋值给mydata
let mydata = this.mydata;
//当前需要调用的云函数名称
let cloudName = 'UpdateAdd';
//用于检查姓名和电户号码的正则函数checkName()和checkNum()
if (!this.checkName(this.mydata.userObj.username) || !this.checkNum(this.mydata.userObj.usernum)) {
this.tip = '抱歉,姓名和电户号,数据有误!';
return;
}
//有确定和取消按键的模态框
uni.showModal({
title: '请选择',
content: `您确定要添加${mydata.userObj.username}吗?`,
cancelText:'取消添加',
confirmText:'确定添加',
//这里应当使用箭头函数,否则影响this.$api和this.tip的使用
success: res=> {
if (res.confirm) {
this.$api.HandleUnicloud(cloudName, mydata).then(v => {
this.tip = v.msg;
uni.showLoading({
title: this.tip
});
setTimeout(() => {
uni.hideLoading();
}, 1000);
});
} else if (res.cancel) {
this.tip = '选择了取消!'
}
}
});
}
十、写在最后
非常感谢,DCloud公司提供如此强大的生态系统,让我们去学习进步的效率大大的提升。
最后附上H5白~嫖建站的最后一关,跨域配置问题,将前端网页托管——参数配置——默认网址,复制粘贴到跨域配置——新增域名中,即可手机,PC端都能正常访问了。
目前uniCloud提供了,免费的阿里云空间,完全可以满足个人用户的建站使用。
只需要在https://unicloud.dcloud.net.cn/login申请账号就可以获得:
1、一个免费的云数据库,用于保存JSON格式的数据
2、一个免费的存储云函数的空间,用于保存可以在云端调用修改云数据库数据的函数,空间环境为nodejs,操作基于mongoDB,有所改动。
3、一个免费的云存储,用于保存图片、视频、文件等,并能够提供对应的访问地址
4、一个免费的网页托管,自动生成可访问的网址,只需处理跨域配置即可。
还没有人评论 快来占位置吧