微信小程序云开发_本地宝

672 阅读6分钟

一、创建小程序

1.在任意地方新建一个空文件夹

2.打开微信小程序开发工具,新建项目,选择云开发

image.png

二、将上次的微信小程序开发写好的文件复制到本文件夹中,包括页面page、tabs、weapp、app.json,并解决覆盖后的报错,将一些没有用到的东西删除,比如接口,因为云开发直接调用数据库,不再需要在cmd中开启wx-database.json文件(json-server --watch database.json)

三、导入数据库

  • 1、点击进入云开发

image.png

  • 2、复制环境ID到app.js

image.png

image.png

  • 3、设置权限

image.png

image.png

  • 4、导入数据
    • 1.创建集合

image.png - 2.导入数据

image.png 导入成功:

image.png

四、云开发数据操作和云函数操作(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中

image.png 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 = {}
  }
})

八、项目上线

image.png

image.png

image.png

image.png

image.png