微信小程序
云开发简介
- 小程序:云开发是微信团队联合腾讯云推出的专业的小程序开发服务。
- 开发者可以使用云开发快速开发小程序、小游戏、公众号网页等,并且原生打通微信开放能力。
- 开发者无需搭建服务器,可免鉴权直接使用平台提供的
API
进行业务开发小程序云开发又简称tcb
,是微信官方给我们提供的基于腾讯云的云服务器。 - 目前云开发包含:云数据库,云函数,云存储,云调用。
云开发优势
- 无需搭建服务器快速构建小程序、公众号
- 无需搭建服务器,只需使用平台提供的各项能力,即可快速开发业务
- 免登陆、免鉴权调用微信开放服务
- 无需管理证书、签名、私钥、直接调用微信
API
。复用微信私有协议及链路,保证业务安全性
- 无需管理证书、签名、私钥、直接调用微信
- 统一开发多端应用
- 支持环境共享,一个后端环境可开发多个小程序、公众号、网页等,便捷复用业务代码与数据
- 不限开发语言和框架
- 开发者可以使用任意语言和框架进行代码开发,构建为容器后,快速将其托管至云开发
- 按量计费,成本更低
- 支持按量计费模式,后端资源根据业务流量自动扩容,先使用后付费,无需支付闲置成本
能力概览
- 存储数据与文件
- 云数据库:文档型数据库、稳定可靠;支持在小程序端和云函数中调用
- 存储:云端文件存储,自带
CDN
加速,支持在前端直接上传/下载,可在云开发控制台可视化管理
- 运行后端代码
- 云函数:在云函数运行的代码,微信私有协议天然鉴权,开发者只需编写自身业务逻辑代码。
- 云托管:支持托管服务容器,不限框架和语言,常驻运行、天然鉴权,可快速进行业务迁移
- 扩展能力
- 静态网站:快速部署网站,支持自定义域名、网站防刷等配置
- 内容管理(
CMS
):一键部署,可视化管理文本、Markdown
、图片等多种内容,使用云数据库读取数据并使用数据
- 打通微信生态
- 云调用:云函数内免鉴权调用小程序开放接口,包括服务端调用、获取开发数据等能力
- 微信支付:免鉴权、免签名计算、免
access_token
,在云函数内原生调用微信支付接口 - 环境共享:跨账号资源和能力复用,可授权云开发资源给其他小程序/公众号使用
云开发和传统服务器对比
—— | 云开发 | 传统服务器 |
---|---|---|
开发语言 | node.js | java ,python ,php |
难易程度 | 简单 | 复杂 |
开发周期 | 1-5 周 | 1-5 月 |
部署难易 | 基本上不用部署 | 部署费事费力 |
是否需要域名 | 不需要 | 需要 |
是否需要备案 | 不需要 | 需要 |
是否支持 https | 不需要 | 需要 |
适合公司 | 中小型公司 | 大公司 |
学习难易 | 容易上手 | 学习起来比较久 |
费用 | 免费版基本够用 | 200-2000 /年 |
云开发环境的创建与初始化
-
必须注册小程序后才可以开通云开发(要有AppId)
-
一个小程序可以创建两个云开发环境
-
和创建普通小程序一样, 需要注意的就是这里必须要填写自己的
appid
,不可以用测试号 -
如果你不使用自己的
appid
创建项目,就会出现一些报错现象 -
所以一定要先去注册一个小程序,然后用自己的
appid
。
开通云开发
-
点击下图箭头所示,如果你第一步创建项目时,没有使用自己的
appid
这里不会有下图箭头所示的云朵 -
给云开发环境取名
-
等待创建
-
创建成功
-
获取云开发环境
id
初始化云开发环境(重要)
-
在
app.js
里写入环境id
,注意这里要用你自己的云开发环境id
-
初始化云开发环境前,先去云开发控制台,拿到云开发环境
id
,如下图 -
这里的环境
id
建议直接复制,不要手写,很容易写错。 -
拿到环境
id
以后,就去app.js
里做云开发环境初始化,如下-
在
app.js
中// app.js App({ onLaunch() { // 初始化云开发环境 wx.cloud.init({ env: 'cloud1-5g4o3xfv164a262d' // 云开发环境ID }) }, })
-
云开发~云数据库
-
在数据库里新建集合(数据表)
-
我们这里以新建一个水果列表为例
-
然后点击添加记录
-
最后添加展现的结果视图
-
-
数据库权限管理
-
要想让用户查询到我们创建的水果数据,需要把权限改为所有用户可读,仅创建者可读写。(相当于:张三创建的只有张三可以修改,李四创建的只有李四可以修改,但是张三可以查询李四创建的,李四也可以查询张三创建的)
-
数据库的增删改查
-
查询
get()
-
传统写法
-
目录结构
-
在
app.js
中初始化云开发环境// app.js App({ onLaunch() { // 初始化云开发环境 wx.cloud.init({ env: 'cloud1-5g4o3xfv164a262d' // 云开发环境ID }) }, })
-
在页面
index
里面的index.js
中// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { fruits:[] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 queryFruits() { // 查询所有商品(传统写法) db.get({ success:(res)=>{ // console.log(res.data); this.setData({fruits:res.data}) } }) } })
-
这个时候可以在控制台的
AppData
中可以看到(这里我在数据库里面添加了两条记录,苹果和香蕉) -
这个时候就可以渲染页面了
-
在页面
index
里面的index.wxml
中<view> <view class="fruits-item"> <text>商品名称</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <text>删除</text> </view> </view>
-
在页面
index
里面的index.wxss
中.fruits-item { display: flex; height: 100rpx; align-items: center; text-align: center; border-bottom: 1px dotted; } .fruits-item text { flex: 1; }
-
页面渲染结果
-
-
ES6
简洁写法-
在页面
index
里面的index.js
中。(其余不变,和上面的一样)// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 queryFruits() { // 查询所有商品(Promise写法) db.get().then(res => this.setData({ fruits: res.data })) } })
// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(async/await写法) const { data } = await db.get() this.setData({ fruits: data }) } })
-
数据库的增删改查
-
条件查询
where()
-
在页面
index
里面的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> </view> <view class="fruits-item"> <text>商品名称</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <text>删除</text> </view> </view>
-
在页面
index
里面的index.wxss
中.fruits-item { display: flex; height: 100rpx; align-items: center; text-align: center; border-bottom: 1px dotted; } .fruits-item text { flex: 1; } .search { display: flex; justify-content: center; height: 160rpx; align-items: center; } .search input { border: 1px solid; width: 400rpx; margin-right: 40rpx; padding-left: 24rpx; }
-
在页面
index
里面的index.js
中// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { name:'', fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const {data} = await db.where({ name:this.data.name.trim() }).get() // console.log(data); this.setData({fruits:data}) } })
-
页面展示结果
-
数据库的增删改查
-
查询单条数据
doc()
-
doc
是用来查询单条数据的。比如商品详情页。 -
doc
里面用到的参数就是我们数据里的_id
字段-
这里新建了一个商品详情
fruitDetail
-
目录结构展示
-
在
app.js
中添加fruitDetail
页面{ "pages": [ "pages/index/index", "pages/fruitDetail/index" ], "window": { "backgroundTextStyle": "light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "Weixin", "navigationBarTextStyle": "black" }, "style": "v2", "sitemapLocation": "sitemap.json" }
-
在
index
页面中的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> </view> <view class="fruits-item"> <text>商品名称</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" data-_id="{{item._id}}" bindtap="queryOne" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <text>删除</text> </view> </view>
-
在
index
页面中的index.js
中// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { name: '', fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) } })
-
在
index
页面中的index.wxss
中.fruits-item { display: flex; height: 100rpx; align-items: center; text-align: center; border-bottom: 1px dotted; } .fruits-item text { flex: 1; } .search { display: flex; justify-content: center; height: 160rpx; align-items: center; } .search input { border: 1px solid; width: 400rpx; margin-right: 40rpx; padding-left: 24rpx; }
-
在
fruitDetail
页面的index.js
中// pages/fruitDetail/index.js Page({ /** * 页面的初始数据 */ data: { fruit:{} }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // console.log(options.fruit); const fruit = JSON.parse(options.fruit) this.setData({fruit}) }, })
-
在
fruitDetail
页面的index.wxml
中<label for=""> 名称:<input type="text" value="{{fruit.name}}" /> </label> <label for=""> 价格:<input type="text" value="{{fruit.price}}" /> </label> <label for=""> 数量:<input type="text" value="{{fruit.num}}" /> </label>
-
在
fruitDetail
页面的index.wxss
中label { display: flex; justify-content: center; } input { border-bottom: 1px solid; padding-left: 24rpx; font-size: 24rpx; }
-
页面渲染结果
-
数据库的增删改查
-
添加数据
add()
-
效果展示图
-
目录结构展示
-
在页面
index
里面的index.js
中// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { // console.log(e.detail); const {_id} = await db.add({ data:e.detail }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) } })
-
在页面
index
里面的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> <text bindtap="showModal" class="btn">添加</text> </view> <view class="fruits-item"> <text>商品名称</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" data-_id="{{item._id}}" bindtap="queryOne" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <text>删除</text> </view> </view> <i-modal title="添加商品" show="{{isShow}}" bindadd="add" bindclose="close" ></i-modal>
-
在页面
index
里面的index.wxss
中.fruits-item { display: flex; height: 100rpx; align-items: center; text-align: center; border-bottom: 1px dotted; } .fruits-item text { flex: 1; } .search { display: flex; justify-content: center; height: 160rpx; align-items: center; } .search input { border: 1px solid; width: 400rpx; margin-right: 40rpx; padding-left: 24rpx; } .btn { margin-left: 30rpx; }
-
在页面
fruitDetail
里面的index.js
中// pages/fruitDetail/index.js Page({ /** * 页面的初始数据 */ data: { fruit:{} }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // console.log(options.fruit); const fruit = JSON.parse(options.fruit) this.setData({fruit}) }, })
-
在页面
fruitDetail
里面的index.wxml
中<label for=""> 名称:<input type="text" value="{{fruit.name}}" /> </label> <label for=""> 价格:<input type="text" value="{{fruit.price}}" /> </label> <label for=""> 数量:<input type="text" value="{{fruit.num}}" /> </label>
-
在页面
fruitDetail
里面的index.wxss
中label { display: flex; justify-content: center; } input { border-bottom: 1px solid; padding-left: 24rpx; font-size: 24rpx; }
-
在自定义组件
i-modal
里面的index.js
中Component({ /** * 组件的属性列表 */ properties: { title:String, show:Boolean }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { add() { const {name,price,num} = this.data price = Number.parseInt(price) num = Number.parseInt(num) // 子组件给父组件传值 this.triggerEvent('add',{name,price,num}) }, close() { this.triggerEvent('close') } } })
-
在自定义组件
i-modal
里面的index.wxml
中<view class="i-model" wx:if="{{show}}"> <view class="tltle">{{title}}</view> <view class="i-model-item"> 商品名称:<input class="input" type="text" model:value="{{name}}" /> </view> <view class="i-model-item"> 商品价格:<input class="input" type="text" model:value="{{price}}" /> </view> <view class="i-model-item"> 商品数量:<input class="input" type="text" model:value="{{num}}" /> </view> <view class="btn-group"> <text class="btn" bindtap="add">添加</text> <text class="btn" bindtap="close">取消</text> </view> </view>
-
在自定义组件
i-modal
里面的index.wxss
中page { height: 100vh; position: relative; } .i-model { width: 550rpx; min-height: 400rpx; background: rgba(0, 0, 0, 0.3); position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%); border-radius: 20rpx; } .tltle { text-align: center; line-height: 60rpx; color: white; } .i-model-item { display: flex; height: 100rpx; align-items: center; color: white; justify-content: center; } .i-model-item .input { border-bottom: 1px solid white; padding-left: 26rpx; font-size: 26rpx; } .btn { font-size: 28rpx; display: block; height: 60rpx; background: #fe551d; width: 200rpx; line-height: 60rpx; text-align: center; border-radius: 20rpx; margin: 0 auto 30rpx auto; color: white; cursor: pointer; } .btn-group { display: flex; justify-content: space-evenly; } .btn:last-child { background: #ddd; }
数据库的增删改查
-
更新数据
update()
-
修改数据库里已存在的数据,结合
doc
进行修改单条数据-
上面是代码不变,我们修改单条数据先点击跳转到详情页在修改
-
页面效果展示
-
以上的代码不变。这里只修改一下
fruitDetail
页面内容 -
在页码
fruitDetail
里面的index.wxml
中<label for=""> 名称:<input type="text" value="{{fruit.name}}" bindinput="updateValue" data-key="name" /> </label> <label for=""> 价格:<input type="text" value="{{fruit.price}}" bindinput="updateValue" data-key="price" /> </label> <label for=""> 数量:<input type="text" value="{{fruit.num}}" bindinput="updateValue" data-key="num" /> </label> <button bindtap="edit">修改</button>
-
在页码
fruitDetail
里面的index.js
中// pages/fruitDetail/index.js Page({ /** * 页面的初始数据 */ data: { fruit: {} }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // console.log(options.fruit); const fruit = JSON.parse(options.fruit) this.setData({ fruit }) }, // 更新input中的值 input中的value === data updateValue(e) { const {key} = e.currentTarget.dataset // console.log(key); const {value} = e.detail const {fruit} = this.data fruit[key] = value this.setData({fruit}) }, // 修改 async edit() { const {fruit} = this.data const {_id,_openid,...data} = fruit // 获取数据库连接 const db = wx.cloud.database().collection('fruits') const {stats} = await db.doc(_id).update({data}) // 不可以修改苹果和香蕉 if(stats.updated === 0) { wx.showToast({ title: '修改失败', icon:'error' }) }else{ wx.redirectTo({ url: '/pages/index/index', }) } } })
-
数据库的增删改查
-
删除数据
remove()
-
删除数据,结合doc删除单条数据
-
页面效果展示
-
其余代码不变和上面一样。
-
在页面
index
里面的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> <text bindtap="showModal" class="btn">添加</text> </view> <view class="fruits-item"> <text>商品名称</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" data-_id="{{item._id}}" bindtap="queryOne" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <!-- 这里不使用 bindtap 因为使用会造成冒泡事件 --> <!-- 所以使用 catchtap 防止产生冒泡 --> <text catchtap="del" data-_id="{{item._id}}">删除</text> </view> </view> <i-modal title="添加商品" show="{{isShow}}" bindadd="add" bindclose="close" ></i-modal>
-
在页面
index
里面的index.js
中// 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { // console.log(e.detail); const {_id} = await db.add({ data:e.detail }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } } })
-
数据库的增删改查
- 增删改查综合案例
- 能查看商品列表
- 更动态添加商品
- 能进入商品详情页
- 能删除某个商品
- 能修改某个商品的价格
- 注意:更新和删除时的权限问题
- 如果这条商品不是你创建的,当你对这条商品做删除或者更新操作时,虽然也会返回成功,但是可以看到我们更新或者删除的条数是
0
- 其实这个时候也意味着没有更新或者删除成功,这里是因为操作权限的问题,因为这条数据不是你创建的。所以你只能对这条数据做查询操作,而不能做修改和删除操作。要想解决这个问题,就要借助云函数了。
- 如果这条商品不是你创建的,当你对这条商品做删除或者更新操作时,虽然也会返回成功,但是可以看到我们更新或者删除的条数是
数据库的增删改查
-
数据库排序
orderBy
-
orderBy
方法在做排序的时候,接受两个参数- 根据那个字段排序
- 排序规则(升序或者降序)。升序用
asc
,降序用desc
-
目录结构新增了一个降序和升序的图标,工具文件夹添加了处理时间的
dayjs
库,其余不变 -
在页面
index
里面的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> <text bindtap="showModal" class="btn">添加</text> </view> <view class="fruits-item"> <view style="display: flex;align-items: center;"> 商品名称 <image src="{{by==='asc'?'/images/down.png':'/images/up.png'}}" class="icon" bindtap="orderBy"></image> </view> <text>时间</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" data-_id="{{item._id}}" bindtap="queryOne" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.time}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <!-- 这里不使用 bindtap 因为使用会造成冒泡事件 --> <!-- 所以使用 catchtap 防止产生冒泡 --> <text catchtap="del" data-_id="{{item._id}}">删除</text> </view> </view> <i-modal title="添加商品" show="{{isShow}}" bindadd="add" bindclose="close" ></i-modal>
-
在页面
index
里面的index.js
中(这里我是根据价格排序的)// 处理时间的库 // 网址:https://dayjs.fenxianglu.cn/ import dayjs from '../../utils/dayjs.min' // 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) } })
-
页面效果展示
数据库的增删改查
- 返回指定条数的数据
limit
limit
用来指定查询结果集数量上限,比如我们有100条数据,只想返回前20条,我们可以通过limit(20)
来指定只返回20
条数据。- 注意:
limit
在小程序端默认及最大上限为20
,在云函数端默认及最大上限为100
- 上面代码不变,具体代码看下面分页
数据库的增删改查
-
分页方法
skip
-
skip
指定查询返回结果时从指定序列后的结果开始返回,常用于分页。比如我们有100条数据,想从第10条开始返回数据,可以通过skip(10)
来实现 -
比如我们有
100
条数据,每次返回20
条数据。那么就可以分5
页返回。- 第1页
limit(20).skip(0)
- 第2页
limit(20).skip(20)
- 第3页
limit(20).skip(40)
- 第4页
limit(20).skip(60)
- 第5页
limit(20).skip(80)
- 第1页
-
上面代码不变
-
在页面
index
里面的index.wxml
中<view> <view class="search"> <input type="text" model:value="{{name}}" placeholder="输入商品名称" /> <text bindtap="seach">搜索</text> <text bindtap="showModal" class="btn">添加</text> </view> <view class="fruits-item"> <view style="display: flex;align-items: center;"> 商品名称 <image src="{{by==='asc'?'/images/down.png':'/images/up.png'}}" class="icon" bindtap="orderBy"></image> </view> <text>时间</text> <text>商品价格</text> <text>商品数量</text> <text>小计</text> <text>操作</text> </view> <view class="fruits-item" data-_id="{{item._id}}" bindtap="queryOne" wx:for="{{fruits}}" wx:key="index"> <text>{{item.name}}</text> <text>{{item.time}}</text> <text>{{item.price}}</text> <text>{{item.num}}</text> <text>{{item.num*item.price}}</text> <!-- 这里不使用 bindtap 因为使用会造成冒泡事件 --> <!-- 所以使用 catchtap 防止产生冒泡 --> <text catchtap="del" data-_id="{{item._id}}">删除</text> </view> </view> 查询指定条数的数据 <input type="text" placeholder="输入数字回车查询指定条数" model:value="{{num}}" /> <button bindtap="limit">查询</button> <view style="text-align: center; padding: 20rpx 0;"> <button bindtap="queryPage" data-page="1" size="mini">1</button> <button bindtap="queryPage" data-page="2" size="mini">2</button> <button bindtap="queryPage" data-page="3" size="mini">3</button> <button bindtap="queryPage" data-page="4" size="mini">4</button> <button bindtap="queryPage" data-page="5" size="mini">5</button> </view> <i-modal title="添加商品" show="{{isShow}}" bindadd="add" bindclose="close"></i-modal>
-
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库连接 const db = wx.cloud.database().collection('fruits') Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) } })
-
页面展示效果
Command
数据库操作符
-
Command
数据库操作符 -
上面学完了数据库的增删改查,但是这些都是最基础最简单的操作,如果我们想实现复杂的数据查询操作,该怎么办呢
- 比如查询价格大于
100
的商品? - 查询年龄小于
18
岁的学生? - 如何同时修改多条数据?
- 如何同时删除多条数据?
- 比如查询价格大于
-
我们如果想实现上面这些复杂的操作,就需要用到数据库里的
Command
数据库操作符 -
如下是我们的页面数据商品展示
Command
数据库操作符
-
gt
查询大于指定值的数据 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加gt
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where({ price:gt(5) }).get() console.log(data); // 苹果 火龙果 西瓜 圣女果 } })
Command
数据库操作符
-
gte
查询大于等于指定值的数据 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加gte
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt,gte} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where({ price:gte(10) }).get() console.log(data); // 火龙果 西瓜 圣女果 } })
Command
数据库操作符
-
lt
查询小于指定数值的数据 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加lt
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt,gte,lt} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where({ price:lt(10) }).get() console.log(data); // 苹果 香蕉 } })
Command
数据库操作符
-
lte
查询小于等于指定数值的数据 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加lte
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt,gte,lt,lte} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where({ price:lte(10) }).get() console.log(data); // 苹果 香蕉 火龙果 圣女果 } })
Command
数据库操作符
-
and
同时满足多个条件的查询 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加add
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt,gte,lt,lte,and,eq} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where(and([ {price:gte(5)}, {num:eq(5)} ])).get() console.log(data); // 苹果 } })
Command
数据库操作符
-
or
或者 -
上面数据库增删改查代码不变,只在页面
index
里面的index.js
中添加or
查询 -
在页面
index
里面的index.js
中// 处理时间的库 import dayjs from '../../utils/dayjs.min' // 获取数据库 const database = wx.cloud.database() // 获取数据库连接 const db = database.collection('fruits') // 获取操作符 const {gt,gte,lt,lte,and,eq,or} = database.command Page({ /** * 页面的初始数据 */ data: { isShow:false, name: '', fruits: [], by:'asc', num:'' }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.queryFruits() this.commandQuery() }, // 查询商品列表 async queryFruits() { // 查询所有商品(传统写法) // db.get({ // success:(res)=>{ // // console.log(res.data); // this.setData({fruits:res.data}) // } // }) // 查询所有商品(Promise写法) // db.get().then(res => this.setData({ // fruits: res.data // })) // 查询所有商品(async/await写法) const { data } = await db.get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({ fruits: data }) }, // 根据name查询商品 async seach() { // where 条件查询 const { data } = await db.where({ name: this.data.name.trim() }).get() // console.log(data); this.setData({ fruits: data }) }, // 根据_id查询 async queryOne(e) { // console.log(e); const {_id} = e.currentTarget.dataset const {data} = await db.doc(_id).get() // console.log(JSON.stringify(data)); const fruit = JSON.stringify(data) wx.navigateTo({ url: `/pages/fruitDetail/index?fruit=${fruit}`, }) }, // 添加数据 展示模态框 showModal() { const {isShow} = this.data this.setData({isShow:!isShow}) }, // 添加 async add(e) { const data = {...e.detail,time:new Date()} // console.log(e.detail); const {_id} = await db.add({ data }) if(_id) wx.showToast({ title: '添加成功', }) this.close() this.queryFruits() }, close() { this.setData({isShow:false}) }, // 删除 async del(e) { const {_id} = e.currentTarget.dataset try { const {stats} = await db.doc(_id).remove() wx.showToast({ title: stats.removed ===0?'删除失败':'删除成功', icon:stats.removed ===0?'error':'success' }) this.queryFruits() } catch (error) { wx.showToast({ title: '没有权限', icon:'error' }) } }, // 排序 async orderBy() { let {by} = this.data // asc 升序 desc 降序 by = by==='asc'?'desc':'asc' const {data} = await db.orderBy('price',by).get() data.map(item=>{ item.time = dayjs(item.time).format('HH:mm:ss') return item }) this.setData({fruits:data,by}) }, // 查询指定的条数的记录 async limit() { const {num} = this.data const {data} = await db.limit(Number.parseInt(num)).get() this.setData({fruits:data}) }, // 分页查询 async queryPage(e) { const {num} = this.data // 页码数 const {page} = e.currentTarget.dataset // 计算查询的起始位置 const startNum = (page-1)*num // 这里的num是字符串,改为number类型 const {data} = await db.limit(Number.parseInt(num)).skip(startNum).get() this.setData({fruits:data}) }, // 操作符查询 // 这里没有设置页面格式什么的 直接在页面加载时调用 然后通过控制台打印结果 async commandQuery() { const {data} = await db.where(or([ {price:gte(5)}, {num:eq(5)} ])).get() console.log(data); // 苹果 火龙果 西瓜 圣女果 } })
数据库的增删改查和Command
数据库操作符
- 以上编写的详细代码已经上传到
gitee
,查看地址:https://gitee.com/didoe/database.git
云开发~云函数
- 云函数即在云端(服务器端)运行的函数。在物理设计上,一个云函数可由多个文件组成,占用一定量的
CPU
内存等计算资源;各云函数完全独立;可分别部署在不同的地区。开发者无需购买、搭建服务器,只需编写函数代码并部署到云端即可在小程序端调用,同时云函数之间也可互相调用。 - 一个云函数的写法与一个在本地定义的
JavaScript
方法无异,代码运行在云端Node.js
中。当云函数被小程序端调用时,定义的代码会被放在Node.js
运行环境中执行。我们可以如在Node.js
环境中使用JavaScript
一样在云函数中进行网络请求等操作,而且我们还可以通过云函数后端SDK
搭配使用多种服务,比如使用云函数SDK
中提供的数据库和存储API
进行数据库和存储的操作,这部分可参考数据库和存储后端API
文档。 - 云开发的云函数的独特优势在于与微信登录鉴权的无缝整合。当小程序端调用云函数时,云函数的传入参数中会被注入小程序端用户的
openid
,开发者无需校验openid
的正确性因为微信已经完成了这部分鉴权,开发者可以直接使用该openid
。
云开发~云函数
-
其实通俗来讲,云函数也是运行在服务器上的,只不过和我们传统开发语言相比。微信官方为我们提供的傻瓜式的一键部署。也就是说你只需要把心思花在业务逻辑代码的编写上即可。无需关心写好如何部署,无需关心安全问题,无需关心鉴权问题。
-
云函数获取
openid
-
用云函数的话,只需要3步
- 编写云函数
- 一键部署云函数
- 调用云函数
-
来看下云函数代码,只需要10行代码,即可轻松搞定
// 云函数入口文件 const cloud = require('wx-server-sdk') cloud.init() // 云函数入口函数 exports.main = async (event, context) => { const wxContext = cloud.getWXContext() return { event, openid: wxContext.OPENID, appid: wxContext.APPID, unionid: wxContext.UNIONID, } }
-
云函数的优势
操作 云函数 云数据库 返回数据上限 100条 20条 更新数据 都可以更新 只有自己创建的才可以更新 删除数据 都可以删除 只有自己创建的才可以删除 运行环境 运行在云端 Node.js
环境运行在小程序本地 实现功能丰富度 非常丰富 只能实现数据库增删改查 -
云函数属于管理端,在云函数中运行的代码拥有不受限的数据库读写权限和云文件读写权限。需特别注意,云函数运行环境即是管理端,与云函数中的传入的
openId
对应的微信用户是否是小程序的管理员 / 开发者无关。 -
初始化云函数的环境
-
创建一个文件夹
cloud
(这个名字可以自定义,但是我们一般使用cloud
)和pages
平行 -
在
project.config.json
里面配置云函数所在目录为cloud
"cloudfunctionRoot": "cloud/"
-
然后点击保存,我们的
cloud
文件夹前面就有一个云朵(图标发生了变化),就代表我们云函数初始化成功啦。
-
-
新建云函数
-
云函数获取
openid
-
调用云函数有两种写法
-
传统的
success
和fail
wx.cloud.callFunction({ // name 必须和你创建的 Node.js 云函数名字一致 name:'queryFruits', success:(res) => { console.log(res.result.openid); } })
-
用
promise
写法then
和catch
wx.cloud.callFunction({ name:'queryFruits', }).then(res => { this.setData({openid:res.result.openid}) }).catch(res => { console.log(res); })
-
-
-
数据的导出
-
数据导出,做数据备份(点击打开云开发控制台,在数据库记录列表中)
-
-
数据的导入
-
数据导入,为了快速的大量的创建一些数据。
-
-
云函数获取数据
// 云函数入口文件 const cloud = require('wx-server-sdk') // 导入 cloud.init({ env:'cloud1-5g4o3xfv164a262d' }) // 云函数入口函数 // 导出 event 参数 exports.main = async (event, context) => { const {_id} = event return await cloud,cloud.database().collection('fruits').doc(_id).get() }
// 在页面index中的index.js里面 async queryOne(e) { const {_id} =e.currentTarget.dataset const {result} = await wx.cloud.callFunction({ name:'queryOne', data:{ _id } }) console.log(result.res); wx.navigateTo({ url: `/pages/fruitDetail/index?fruits=${JSON.stringify(result.data)}`, }) }
-
云函数修改数据
// 云函数入口文件 const cloud = require('wx-server-sdk') // 导入 cloud.init({ env:'cloud1-5g4o3xfv164a262d' }) // 云函数入口函数 // 导出 event 参数 exports.main = async (event, context) => { const {_id} = event return await cloud,cloud.database().collection('fruits').doc(_id).update() }
-
云函数删除数据
// 云函数入口文件 const cloud = require('wx-server-sdk') // 导入 cloud.init({ env:'cloud1-5g4o3xfv164a262d' }) // 云函数入口函数 // 导出 event 参数 exports.main = async (event, context) => { const {_id} = event return await cloud,cloud.database().collection('fruits').doc(_id).remove() }
// 在页面index中的index.js里面 // 删除 async del(e) { const {_id} = e.currentTarget.dataset const {result} = await wx.cloud.callFunction({ name:'del', data:{ _id } }) // console.log(result); if(result.starts.removed == 1) { wx.showToast({ title: '删除成功', icon:'success' }) } this.queryFruits() },