为什么选择mpvue

在比较了原生开发小程序和wepy以及mpvue之后,由于mpvue是一个基于Vue的框架,里面可以使用Vue的各种语法,由于自己也学习了Vue所以学习成本也不高,可以说是无缝对接了。

总体概述

小程序使用的是前后分离的开发模式,后端构造接口,然后前端请求接口拿到数据后进行页面的渲染。后台采用的是腾讯云官方提供的例子。采用的是Node.jsMysql。下载之后需要做一些简单的配置,网上也有很多教程。这里后端大部分代码不需要自己写,这需要写一些自己需要用到的接口。小程序前端封装了需要经常用到的函数,在utils目录下,所以在代码中如果看到utils就表示使用的是utils中的方法。

目录结构

小程序的主要代码都写在src目录下。

补充一点

由于现在豆瓣的图书API已经不能用了,但是在网上看到了一片文章,我就是使用的这种方法来获取图书的详情,但是获取的图书资料不是和完整,但也还是凑合着用吧,后端代码实现见:server/controllers/addbook.js

下面给大家讲一讲主要页面的代码

一、个人中心页面

核心代码;这里采用了小程序提供的wafer2-client-sdk库,在使用之前我们要先引入import qcloud from "wafer2-client-sdk"

async login() {
    let user = wx.getStorageSync("userinfo");
    if (!user) {
    wx.showLoading({
      title: "登录中",
      mask: true
    })
    qcloud.setLoginUrl(config.loginUrl);
    qcloud.login({
      success: (res) => {
        wx.hideLoading()
        console.log("success:", res);
        wx.setStorageSync("userinfo", res);
        this.userinfo = res
        utils.showSuccess("登录成功");
      },
      fail: function(err) {
        console.log("fail:", err);
      }
    });
}
}
复制代码

在登录成功之后我们把数据存储到本地,下次进入小程序的时候先判断本地是否有数据,如果有就直接获取,

  onShow() {
    let userinfo = wx.getStorageSync("userinfo")
    if (userinfo) {
      this.userinfo = userinfo
    }
  }
复制代码

登录成功之后会有添加图书的按钮

    scanBook() {
      wx.scanCode({
        success: res => {
          console.log(res)
          if(res.result) {
            this.addBook(res.result)      
          }
        }
      });
    },
    async addBook(isbn) { // 扫码成功后添加书籍
      const res = await utils.post('/weapp/addbook', {
        isbn,
        openid: this.userinfo.openId
      })
      console.log(res)
      if (res.code === 0) {
        utils.showModal('提示',`添加成功${res.title}`)
      } else {
        utils.showModal('提示', `添加失败${res.msg}`)
      }
    },
复制代码

这里调用了微信小程序自带的API,得到扫描的结果之后向后台发送数据(server.controllers/addbooks.js),后台得到ISBN编码后查询结果,然后存入数据库。存入数据库的信息包括isbn, openid, title, image, alt, publisher, summary, price, rate, tags, author

二、图书列表页面

获取图书列表代码

    async getList(init) { // 获取图书列表
      if (init) { // init代表初始化数据的时候
        this.page = 0
        this.more = true
      }
      wx.showNavigationBarLoading()
      let res = await utils.get('/weapp/booklist', {page: this.page})
      if (res.list.length < 10 && this.page > 0) {
        this.more = false

      }
      if (init) {
        this.books = res.list
        wx.stopPullDownRefresh()
      } else {
        this.books = this.books.concat(res.list)
      }
      wx.hideNavigationBarLoading()
    },
    
复制代码

这里采用的是分页查询(后端:server/controllers/booklist),每次只加载十条数据然后当触发onReachBottom()事件后就把当前的数据拼接上获取到的数据。这里在获取图书列表的时候会使用联表查询:根据图书信息中的openid去查找对应的用户信息。

.select('books.*', 'cSessionInfo.user_info')
.join('cSessionInfo', 'books.openid', 'cSessionInfo.open_id')
复制代码

这里的评分是一个单独的组件src/components/Rate.vue

  <div class='rate'>
    <span>☆☆☆☆☆</span>
    <div class="hollow" :style='style'>
      ★★★★★
    </div>
  </div>
复制代码

设置hollow为绝对定位,然后根据图书的评分设置它的宽度。

三、图书详情页面

在进入图书详情页的时候会把当前图书的 id做为参数传给下一个页面,在进入下一个页面的时候可以通过 this.$root.$mp.query.id获取到。

在进入图书详情页之后先通过this.$root.$mp.query获取当前图书的id,然后在数据库中根据id查找图书的详情信息。然后根据id在数据库评论表中查找评论。这里在查找的时候也会使用联表查询获取图书添加者的信息(根据图书信息的openid获取用户信息)。

一本书一位用户只能评价一次,如果用户评价了就不能再次评价,相应的评论框也会被隐藏。

判断用户是否可以评价

  computed: {
    showAdd() { // 是否展示发表评论按钮
      if (!this.userinfo.openId) { // 未登录
        return false
      }
      if (this.comments.some(v => v.openid = this.userinfo.openId)) { // 已经评论了
        return false
      }
      return true
    }
  },
复制代码

如果用户还没有评价则显示评价框:

获取手机型号

getPhone(e) {
  if (e.target.value) {
    let systemInfo = wx.getSystemInfoSync();
    this.phone = systemInfo.model;
  } else {
    this.phone = "";
  }
},
复制代码

获取地址位置

getGeo(e) {
  if (e.target.value) {
    wx.getLocation({
      success: geo => {
        console.log(geo)
        wx.request({
          url: config.baiduURL,
          data: {
            ak: config.baiduAK,
            location: `${geo.latitude},${geo.longitude}`,
            output: "json"
          },
          success: res => {
            if (res.data.status === 0) {
              this.location = res.data.result.addressComponent.city;
            } else {
              this.location = "外太空";
            }
          }
        });
      }
    });
  } else {
    this.location = "";
  }
},
复制代码

需要注意的是,使用微信自定义的API只能获取到经纬度,我们通过百度地图的开放接口申请小程序,来进行逆地址解析。

四、评论页面

在这个页面你可以看到你发表的评论以及添加的书籍,这里根据你的openid去后台数据库查找,然后展示在页面上。点击评论可以进入这条评论对应的书籍,但是在图书详情页不会,这主要添加了一个标识来判断当前处于的页面。

最后

感谢蜗牛老师。如果你觉得还不错的话请你点个赞呢。

GitHub地址:github.com/CCZX/librar…