一、创建小程序
1.在任意地方新建一个空文件夹
2.打开微信小程序开发工具,新建项目,选择云开发
二、将上次的微信小程序开发写好的文件复制到本文件夹中,包括页面page、tabs、weapp、app.json,并解决覆盖后的报错,将一些没有用到的东西删除,比如接口,因为云开发直接调用数据库,不再需要在cmd中开启wx-database.json文件(json-server --watch database.json)
三、导入数据库
- 1、点击进入云开发
- 2、复制环境ID到app.js
- 3、设置权限
- 4、导入数据
- 1.创建集合
- 2.导入数据
导入成功:
四、云开发数据操作和云函数操作(home页面)
1.在cloufunctions文件夹中创建云函数,并在js文件中编写云函数入口文件
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db=cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
// const wxContext = cloud.getWXContext()
const res=await db.collection('slides').get()
return {
res
// event,
// openid: wxContext.OPENID,
// appid: wxContext.APPID,
// unionid: wxContext.UNIONID,
}
}
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db=cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
// const wxContext = cloud.getWXContext()
const res=await db.collection('categroies').get()
return {
res
// event,
// openid: wxContext.OPENID,
// appid: wxContext.APPID,
// unionid: wxContext.UNIONID,
}
}
- 云函数每次编辑过后需要上传并部署(该函数文件夹右击选择第三个,云端安装依赖),并在cloudfunctions同步云函数列表
2.在home.js中使用云函数
Page({
/**
* 页面的初始数据
*/
data: {
slides: [],
cates: []
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.getSilides()
this.getCategories()
},
getSilides() {
wx.cloud.callFunction({
name:'get_slides'
}).then(res=>{
this.setData({
slides:res.result.res.data
})
})
},
getCategories(){
wx.cloud.callFunction({
name:'get_categroies'
}).then(res=>{
this.setData({
cates:res.result.res.data
})
})
},
goDetail(e){
console.log(e);
wx.navigateTo({
url: "/pages/list/list?id="+e.target.dataset.id
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
if (this.getTabBar() && typeof this.getTabBar === 'function') {
this.getTabBar().setData({
active: 0
})
}
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
3.渲染到页面
- home.json
{
"usingComponents": {
"van-grid": "/weapp/weapp/dist/grid/index",
"van-grid-item": "/weapp/weapp/dist/grid-item/index"
}
}
- home.wxml
<view class="home">
<!-- 轮播图区域 -->
<swiper class="my-swiper" indicator-dots="{{true}}" autoplay="{{true}}">
<swiper-item wx:for="{{slides}}" wx:key="index">
<!-- block 只做逻辑上的判断不做DOM的渲染 -->
<block wx:if="{{item.link}}">
<navigator url="/pages/list/list">
<image src="{{item.image}}" mode="aspectFill" />
</navigator>
</block>
<block wx:else>
<image src="{{item.image}}" mode="aspectFill" />
</block>
</swiper-item>
</swiper>
<van-grid column-num="3">
<van-grid-item wx:key="index" icon="{{item.icon}}" text="{{item.name}}" wx:for="{{ cates }}" url="/pages/list/list?id={{item.id}}"/>
</van-grid>
</view>
五、跳转到list页面
- 1.home.wxml
<van-grid column-num="3">
<van-grid-item wx:key="index" icon="{{item.icon}}" text="{{item.name}}" wx:for="{{ cates }}" url="/pages/list/list?id={{item.id}}"/>
</van-grid>
- 2.云函数
- get_categories_id
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db=cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
// const wxContext = cloud.getWXContext()
const res=await db.collection('categroies')
.where({
id:event.id
})
.get()
return {
res
// event,
// openid: wxContext.OPENID,
// appid: wxContext.APPID,
// unionid: wxContext.UNIONID,
}
}
- get_shops
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db=cloud.database()
// 云函数入口函数
exports.main = async (event, context) => {
// const wxContext = cloud.getWXContext()
const res=await db.collection('shops')
.where({
categoryId:event.id
})
.skip((event.pageNo-1)*event.pageSize)
.limit(event.pageSize)
.get()
return {
res
// event,
// openid: wxContext.OPENID,
// appid: wxContext.APPID,
// unionid: wxContext.UNIONID,
}
}
- 3.使用云函数获取数据 list.js
Page({
/**
* 页面的初始数据
*/
data: {
id:0,
pageNo:0,
pageSize:10,
shops:[],
hasMore:false
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
// console.log(options.id);
// this.getCategoryById(options.id)
this.setData({
id:Number(options.id)
})
this.getCategoryById()
this.getShops()
},
// 根据id获取分类的内容
getCategoryById(){
wx.cloud.callFunction({
name:'get_categroies_id',
data:{
id:this.data.id
}
}).then(res=>{
wx.setNavigationBarTitle({
title: res.result.res.data[0].name,
})
})
},
// 获取商品
async getShops(){
// 节流
if(this.data.hasMore!==false) return
++this.data.pageNo
const res=await wx.cloud.callFunction({
name:'get_shops',
data:{
id:this.data.id,
pageNo:this.data.pageNo,
pageSize:this.data.pageSize
}
})
if(res.result.res.data.length>0){
this.setData({
shops:this.data.shops.concat(res.result.res.data)
})
}else {
this.setData({
hasMore:true
})
}
},
// 加载更多
getMore() {
this.getShops()
},
// 模拟打电话
makePhoneCall(e){
wx.makePhoneCall({
phoneNumber: e.target.dataset.phone //仅为示例,并非真实的电话号码
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh:async function () {
await this.setData({
pageNo:0,
shops:[],
hasMore:false
})
await this.getShops()
wx.stopPullDownRefresh()//停止当前页面下拉刷新
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
// 下拉后加载更多商品
this.getMore()
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
- 4.渲染到页面 list.json
{
"usingComponents": {
"van-card": "/weapp/weapp/dist/card/index"
},
"enablePullDownRefresh":true,
"backgroundColor":"#000"
}
list.wxml
<view class="list">
<van-card
wx:for="{{shops}}"
wx:key="index"
tag="{{item.score}}"
title="{{item.name}}"
thumb="{{ item.images[0] }}"
>
<view slot="desc">
<view bindtap="makePhoneCall" data-phone="{{item.phone}}">联系电话: {{item.phone}}</view>
<view>联系地址: {{item.address}}</view>
<view>营业时间: {{item.businessHours}}</view>
<view>设施:{{item.supportService}}</view>
</view>
</van-card>
<view wx:if="{{!hasMore}}" class="loadmore loading">
正在加载...</view>
<view wx:else class="loadmore">没有更多内容了</view>
</view>
list.wxss
.loadmore {
color: #888;
font-size: 30rpx;
line-height: 100rpx;
text-align: center;
}
.loadmore.loading::before {
content: '';
width: 40rpx;
height: 40rpx;
margin-top: -10rpx;
margin-right: 10rpx;
display: inline-block;
vertical-align: middle;
animation: loading 1s steps(12) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
background-size: 100%
}
@keyframes loading {
from {
transform: rotate(0deg)
}
to {
transform: rotate(-360deg)
}
}
六、授权登录
1.新建login页面
2.在微信公众平台的文档中找到用户信息,并将使用例子复制到login.wxml和login.js中
login.wxml
<!-- <view class="container">
<view class="userinfo">
<block wx:if="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<button wx:else open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
</block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
</view> -->
<view class="userinfo">
<block wx:if="{{!hasUserInfo}}">
<button bindtap="getUserProfile"> 登录授权 </button>
</block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
login.js
const db=wx.cloud.database()
Page({
data: {
userInfo: {},
hasUserInfo: false,
canIUseGetUserProfile: false,
},
onLoad() {
// if (wx.getUserProfile) {
// this.setData({
// canIUseGetUserProfile: true
// })
// }
const state=wx.getStorageSync('state')
const userInfo=JSON.parse(wx.getStorageSync('userInfo')||'{}')
if(!state){
this.setData({
hasUserInfo:true,
userInfo
})
}
},
getUserProfile(e) {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
// console.log("success");
db.collection('user').add({
data:{
phone:'18888888888'
}
}).then(res=>{
console.log(res);
})
wx.setStorageSync('state', 'state')
wx.setStorageSync('userInfo', JSON.stringify(res.userInfo))
setTimeout(()=>{
wx.switchTab({
url: '/pages/home/home',
},3000)
})
}
})
},
getUserInfo(e) {
// 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
})
3.创建数据集合user
4.在login.js利用user中的add模式将数据保存到内存中
const db=wx.cloud.database()
const state=wx.getStorageSync('state')
const userInfo=JSON.parse(wx.getStorageSync('userInfo')||'{}')
db.collection('user').add({
data:{
phone:'18888888888'
}
}).then(res=>{
console.log(res);
})
wx.setStorageSync('state', 'state')
wx.setStorageSync('userInfo', JSON.stringify(res.userInfo))
setTimeout(()=>{
wx.switchTab({
url: '/pages/home/home',
},3000)
})
七、登录拦截
- 若state存在内存中则不会拦截,若state不存在,则跳转到login页面进行登录 app.json
const state=wx.getStorageSync('state')
if(!state){
wx.redirectTo({
url: '/pages/login/login',
})
}
//app.js
App({
onLaunch: function () {
if (!wx.cloud) {
console.error('请使用 2.2.3 或以上的基础库以使用云能力')
} else {
wx.cloud.init({
// env 参数说明:
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
env: 'cloud1-6givj2tua364b003',
traceUser: true,
})
const state=wx.getStorageSync('state')
if(!state){
wx.redirectTo({
url: '/pages/login/login',
})
}
}
this.globalData = {}
}
})