小程序(2):云开发

2019-08-22 22:55:37 浏览数 (1)

所谓serverless就是无后台开发。通俗地说就是踢开后端闹革命。只需要一个前端就可以操作数据库小程序云开发就是这个概念的尝鲜者。云开发也是小程序近年最大的改变之一。

云开发文档 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html

云函数,数据库和文件储存构成了云开发的核心三大件。

腾讯是这么说的:一个前端凭借云开发,就能够搞定一个两亿级别的应用。(商业案例:腾讯云相册)

在微信开发者工具中点击"云开发",开通后可以进入到云开发的控制台。

微信给你免费送了一些有用的功能。那就是你的后台了。

运维中心

凭借运维中心,运维人员也可以踢开了。

听到这些广告词,是不是心动了呢。

数据库

数据库也是一个黑盒,但是表现很像mongodb。本质上应该是一个文档型数据库。

云开发提供了一个 JSON 数据库,顾名思义,数据库中的每条记录都是一个 JSON 格式的对象。一个数据库可以有多个集合(相当于关系型数据中的表),集合可看做一个 JSON 数组,数组中的每个对象就是一条记录,记录的格式是 JSON 对象。 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-server-api/database/

怎么用呢?

新建一个基于云开发的小程序项目。

发现目录结构变了,原来的小程序结构放到了miniprogram文件夹:

增加了一个cloudfunctions文件夹。

你可以在页面中const db = wx.cloud.database()拿到数据库。

调用时你可以

代码语言:javascript复制
db.add({
    // balabala
})

add可以替换为get等等。

代码语言:javascript复制
    getbooks(){
        // 小程序端直接读库
        db.collection('books').get({
            success:(res)=>{
                console.log(res)
                this.setData({
                    books:res.data
                })
            }
        });
    },

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-client-api/database/

前端不再去写什么http请求了。以下实现一个才子书列表的基本管理。

代码语言:javascript复制
<scroll-view>
    <view class="title">才子书</view>
    <input bindinput="input" wx:value="{{addContent}}" class="add-book" />
    <button bindtap="addbook" type="primary">添加</button>

    <view wx:for="{{books}}" >
        <view>
        <text>{{item.name}}-{{item.author}}-{{item._id}}    </text>
        <text class="delete" data-id="{{item._id}}" bindtap="delete">删除</text>
        </view>
    </view>
</scroll-view>
代码语言:javascript复制
const db = wx.cloud.database()
Page({
    data: {
        books: [],
        addContent: ''
    },
    onLoad() {
        this.getbooks();
    },

    delete(e) {
        const { id } = e.currentTarget.dataset;

        db.collection('books').doc(id).remove({
            success: (res) => {
                console.log(res)
                this.getbooks();
            }
        })
    },

    getbooks() {
        // 小程序端直接读库
        db.collection('books').get({
            success: (res) => {
                // console.log(res)
                this.setData({
                    books: res.data
                })
            }
        });
    },

    input(e) {
        this.setData({
            addContent: e.detail.value
        })
    },

    addbook() {
        // 加库
        db.collection('books').add({
            data: {
                name: this.data.addContent,
                author: 'djtao'
            },
            success: (res) => {
                this.getbooks();
                this.setData({
                    addContent: ''
                })
            }
        });
    }

})

注意你的才子书数据库,应做如下设置

实际上小程序最多只允许用户操作自己创建的数据。允许删除的列表建议放另外一个collection。

云函数

云函数是一系列nodejs的npm项目。可以使用npm安装自己需要的依赖。帮助实现一些额外功能。能力包括:

  • 服务器
  • 储存
  • 工具插件引入
基本使用

接下来体验一下云函数的"魅力",新建一个me页面。

然后在开发者工具编辑器中"新建nodejs云函数",命名为login。

新建之后有以下配置,其实就是一个npm项目:

代码语言:javascript复制
// 云函数模板
// 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署”

const cloud = require('wx-server-sdk')

// 初始化 cloud
cloud.init()

/**
 * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端
 *
 * event 参数包含小程序端调用传入的 data
 * 暴露云函数的入口
 */
exports.main = (event, context) => {
  console.log(event)
  console.log(context)

  // 可执行其他自定义逻辑
  // console.log 的内容可以在云开发云函数调用日志查看

  // 获取 WX Context (微信调用上下文),包括 OPENID、APPID、及 UNIONID(需满足 UNIONID 获取条件)
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

exports.main是暴露出来的云函数入口,我们稍微改一下:

代码语言:javascript复制
exports.main = async (event, context) => {
  const {a,b}=event;
  return await {
    sum:a b
  }
}

写完之后就可以部署了。

怎么使用呢?通过wx.cloud.callFunction调用

代码语言:javascript复制
Page({
    data: {},
    onLoad() {
        wx.cloud.callFunction({ // 云函数名称
            name: 'login',
            // 传给云函数的参数 data:
            data: { a: 1, b: 2, },
            success(res) {
                console.log(res.result.sum) // 3
            },
            fail(err) {
                console.error(err)
            }
        });
    }
})

好了,现在进入到me页面,打印出来的就是1 2的结果3。

实际上云函数做的东西多的多。

完善云函数login

小程序最重要的就是登录。现在就把登录功能给做了。

登录最紧要就是获取openid。

获取openid
代码语言:javascript复制
const cloud = require('wx-server-sdk')
cloud.init()
exports.main = (event, context) => {
  const wxContext = cloud.getWXContext()
  return {
event,
    openid: wxContext.OPENID,
  }
}

打开云开发控制台,就可以看到登录的调用情况。

代码语言:javascript复制
Page({
    data: {
        userInfo: {}
    },
    onLoad(){
            // 获取登录态
        wx.getSetting({
            success: res => {
              if (res.authSetting['scope.userInfo']) {
                // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
                wx.getUserInfo({
                  success: res => {
                    this.setData({
                      avatarUrl: res.userInfo.avatarUrl,
                      userInfo: res.userInfo
                    })
                  }
                })
              }
            }
          })
    },
        // 点击按钮登录
    onGetUserInfo(e) {
        // console.log('coGetUserInfo', e)
        if (e.detail.userInfo) {
            this.setData({
                avatarUrl: e.detail.userInfo.avatarUrl,
                userInfo: e.detail.userInfo
            })
        }
    }
})
持久化储存openid
代码语言:javascript复制
wx.setStorageSync('userInfo',userInfo)

所以流程就是:获取openid,然后,获取用户信息。

代码语言:javascript复制
    onLogin(){
          let _this=this;
          // 调用云函数
          wx.cloud.callFunction({
            name: 'login',
            data: {},
            success: res => {
              console.log('[云函数] [login] user openid: ', res.result.openid)
              app.globalData.openid = res.result.openid;

              wx.getUserInfo({
                success: res => {
                  _this.setData({
                    avatarUrl: res.userInfo.avatarUrl,
                    userInfo: res.userInfo
                  })
                }
              })

            },

            fail: err => {
              console.error('[云函数] [login] 调用失败', err)
              wx.showToast({
                title: '获取用户信息失败',
                icon: 'none',
                image: '',
                duration: 1500,
                mask: false,
                success: (result) => {

                },
                fail: () => {},
                complete: () => {}
              });
            }
          })
    },
案例:扫码添加图书信息。

需求:

  1. 用户扫码(isbn)
  2. 根据isbn去豆瓣找信息
  3. 爬取图书信息,存储到云数据库。

我们的测试条形码是:

调起扫码

先让微信客户端调起扫码功能。

代码语言:javascript复制
    callLogin(){
        wx.scanCode({
            success (res) {
              console.log(res)
            }
          })
    }

点击扫码调用这个函数,其中result就是这个结果。

获取豆瓣读书信息

下一步就是根据扫码结果进行查询。

豆瓣的公开接口是:https://book.douban.com/subject_search?search_text=

遗憾的是,你在postman看不到任何跟搜索结果有关的信息。(被加密了)

这时候可以用一个叫做doubanbook的npm包来解析这串解密数据。

新增一个getBookInfo云函数,

给他装上依赖:

代码语言:javascript复制
npm i axios doubanbook -s
代码语言:javascript复制
// 云函数入口文件
const cloud = require('wx-server-sdk');
const doubanbook=require('doubanbook');
const axios=require('axios');

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()
  const {isbn}=event;
  const url=`https://book.douban.com/subject_search?search_text=${isbn}`;
  let res=await axios.get(url);
  let reg=/window.__DATA__ = "(.*)"/;
  let searchData=null;
  if(reg.test(res.data)){
    searchData=doubanbook(RegExp.$1)[0];
  }

  return {
    searchData
  }
}

小程序端调用:

代码语言:javascript复制
    addBook(isbn){
        let res=wx.cloud.callFunction({
            name:'getBookInfo',
            data:{
                isbn
            },
            success(data){
                console.log(data)
            }
        })
    },

在本地调试一下,就拿到结果了。

好了,把展示界面简单写一写:扫码的结果就出来了。

所以,云函数本质上是一个小小的nodejs服务。所以nodejs是基础。

继续爬?

入库前想一想,我们想要的数据是什么?

当前拿到的数据还是非常有限的。有了链接,那意味着可以继续爬。详情链接是没有加密的。

用cheerio来爬吧!

代码语言:javascript复制
  // 详情页数据
  const detailData=await axios.get(searchData.url);
  const $=cheerio.load(detailData.data);
  // 以jq形式调用数据
  const summary=$('#link-report .intro').text();
  const info=$('#info').text().split('n').map(v=>v.trim()).filter(v=>v);
  const auhtor=info[1];


  return {
    searchData,
    creatTime:new Date().getTime(),
    detailData,
    auhtor,
    summary,
    info,
  }

实际上你把爬虫写在这里是比较累人的。很有可能超时。

入库

拿到数据就考虑入库了。这里只考虑入库书名和作者。

入库的时候增加判断openid:

代码语言:javascript复制
    addBooktoList() {
        // 加库
        // console.log(app.globalData.openid)
        db.collection('books').add({
            data: {
                name: this.data.bookInfo.title,
                author: 'djtao',
                openid:wx.getStorageSync('userInfo').openid
            },
            success: (res) => {
                console.log(res)
                wx.showToast({
                    title: '成功',
                    icon: 'none',
                    image: '',
                    duration: 1500,
                    mask: false,
                    success: (result) => {

                    },
                    fail: () => {},
                    complete: () => {}
                });

            }
        });
    }

0 人点赞