最近一直忙着搞学校的icode比赛所以博客的更新就搁置了qwq,这个icode比赛我们是做一个小程序,而我是负责小程序的前端部分,这篇文章也是来记录一下第一次小程序的经历,技术性的东西估计不会讲太多,可能主要讲本项目如何使用腾讯云的COS对象存储以及一些开发中遇到的坑……


小程序介绍

这个小程序是一个用来服务于修勾的平台,主要用户功能有发布、收藏、删除领养公告以及领养自己喜欢的修勾,以及本项目的一大亮点——“拍照识修勾”即用户拍照后平台进行分析得出相似度最高的修勾品种,当然这一困难part主要是后端方面的工作(想看后端介绍的友友可以去友链里面勋哥的博客看),而我就负责前端的部分,具体小程序以及前端代码的github地址会在项目结束后会放在文章的最后……

开发实记

var that = this的声明

如若需要修改data里面的值并渲染到页面一般需要使用this.setData(),但是我们项目起初在调用wx.request()这个API时,在wx.request()里面使用this.setData()会报错,经过查询才知道要在wx.request()前面加上一下声明

1
var that = this;

而原因和this的作用域有关:

  • 在Page({})里面,this关键字指代Page({})整个对象,因此可以通过this关键字访问或者重新设置Page({})里data的变量,但是在wx.request()这个API后this的指向就发生改变就无法使用this来获取Page({})对象
  • 而解决方法就是在wx.request()外面先把this存在某个变量中即上述声明,此时that指代Page({})整个对象,也就能在wx.request()中使用that来访问Page({})对象

腾讯云COS对象存储介绍

在小程序中难免会碰到上传图片之类的操作,我们这个项目主要是在用户头像、公告发布、拍照识别等会用到图片上传,因为我们在数据库中图片是打算用一个字符串来存储(即图片链接),所以最后选择了腾讯云的COS对象存储,再将得到的图片链接传给后端,接下来就讲讲前期的准备工作

  1. 进入腾讯云官网(https://cloud.tencent.com ),产品栏找到存储中的对象存储,进入之后点击“立即使用”登录,这里我用的是小程序公众号的方式登录,然后就进入对象存储的控制台界面

  2. 创建存储桶

  3. 进入具体的某个存储桶后可以进行文件的上传,也可以创建文件夹对上传的文件进行分类存放,上传后就可以可以得到对应图片的url链接

  4. 腾讯云对象存储除了提供多种 API 接口,还提供了丰富多样的 SDK 供开发者使用,这个项目用的就是其中的小程序SDK(https://cloud.tencent.com/document/product/436/31953

腾讯云COS对象存储的小程序SDK使用

  1. 首先是安装小程序SDK,我用的是官网中手动安装的方式(具体可查看官网),并将cos-wx-sdk-v5.js放在utils的目录下

  2. 小程序里请求 COS 需要登录到 微信公众平台,选择开发 > 开发设置 > 服务器域名,配置域名白名单。SDK 使用到了两个接口:

    • cos.postObject 使用 wx.uploadFile 方法。

    • 其他方法使用 wx. request 方法。

    需要在对应白名单里,配置 COS 域名,白名单域名格式有两种:

    • 如果是标准请求,可以配置存储桶域名作为白名单域名,例如:https://examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com本项目使用这个

    • 如果小程序使用的存储桶多,可以选择后缀式请求 COS,只需要在 SDK 实例化时传入ForcePathStyle: true,这种方式需要配置地域域名作为白名单,例如:cos.ap-guangzhou.myqcloud.com

  3. 初始化及其配置:官网介绍了四种方式,本项目使用的是比较简便的格式4,在需要使用上传图片的页面js中进行cos的初始化及其配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var COS = require('../../../utils/cos-wx-sdk-v5.js'); //注意路径按照自己的更改

    // 创建一个 COS SDK 实例
    // SECRETID 和 SECRETKEY 请登录 https://console.cloud.tencent.com/cam/capi 进行查看和管理
    var cos = new COS({
    SecretId: 'SECRETID',
    SecretKey: 'SECRETKEY',
    SimpleUploadMethod: 'putObject', // 强烈建议,高级上传、批量上传内部对小文件做简单上传时使用putObject,sdk版本至少需要v1.3.0
    });
  4. 上传函数实现

    • 第一种:直接点击按钮上传

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      UpLoadImg(){
      var that = this;
      // 选择图片上传
      wx.chooseMedia({ //此API可以查看微信官方文档的具体参数信息
      count: 1, // 上传1张图片
      mediaType: ['image'],
      sourceType: ['album','camera'], // 拍摄图片或从相册选择图片
      success(res){
      // 拿到本地的临时文件路径filePath,多张图片可以用for循环遍历上传
      var filePath = res.tempFiles[0].tempFilePath;
      // 截取filePath最后一个斜杆的后面部分作为cloudPath
      var cloudPath = filePath.substr(filePath.lastIndexOf('/') + 1)
      // 使用腾讯云COS对象存储
      cos.postObject({
      Bucket: 'Bucketname', //对象储存桶的名称
      Region: 'ap-guangzhou', //所属地域
      Key: 'dir/' + cloudPath, //存储在dir文件夹里面,如果没有区分文件夹就直接填cloudPath
      FilePath: filePath, // 本地的临时文件路径
      onProgress: function (info) {
      console.log('进度条', JSON.stringify(info));
      }
      }, function (err, data) {
      // 这里用的是回调函数的形式,也可以用promise方式
      if (err) {
      console.log('上传失败', err);
      } else {
      // 上传成功赋值toIdentifyUrl
      that.setData({
      // 最终的图片地址toIdentifyUrl在data里面有声明
      // app.globalData.cdnHost是图片链接的公共前缀我放在app.js里面了
      toIdentifyUrl: app.globalData.cdnHost + 'dir/' + cloudPath
      })
      }
      });
      }
      })
      }
    • 第二种:结合WeUI的mp-uploader组件进行上传(mp-uploader自带图片上传的相关参数)

      WeUI的引入这里就不赘述了,首先是wxml的mp-uploader部分

      1
      2
      <!-- photo是最终存放上传成功图片的列表,一般一开始是空的 -->
      <mp-uploader files="{{photo}}" max-count="1" max-size="{{10 * 1024 * 1024}}" title="照片:" tips="最多上传一张图片" size-type="{{sizeType}}" sourceType="{{sourceType}}" delete="{{true}}" select="{{selectFile}}" upload="{{uplaodFile}}" binddelete="delimg" bindfail="uploadError" bindsuccess="uploadSuccess"></mp-uploader>

      然后就是涉及到的上传图片的js代码,主要mp-uploader中5个函数的实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      var COS = require('../../../utils/cos-wx-sdk-v5.js'); // 图片上传所需接口
      const app = getApp();

      // 创建一个 COS SDK 实例
      // SECRETID 和 SECRETKEY 请登录 https://console.cloud.tencent.com/cam/capi 进行查看和管理
      var cos = new COS({
      SecretId: 'SECRETID',
      SecretKey: 'SECRETKEY',
      SimpleUploadMethod: 'putObject', // 强烈建议,高级上传、批量上传内部对小文件做简单上传时使用putObject,sdk版本至少需要v1.3.0
      });

      Page({
      data: {
      photo: [],
      //mp-uploader
      sizeType: ['original'], //压缩上传,可以是['original', 'compressed']
      sourceType: ['album', 'camera'], //相册,或拍照
      maximgs: 1,
      },
      onLoad() {
      this.setData({
      //通过bind(this)将函数绑定到this上,以后函数内的this就是指全局页面
      //setdata以后,这两个函数就可以传递给mp-uploader了
      selectFile: this.selectFile.bind(this),
      uplaodFile: this.uplaodFile.bind(this)
      })
      },
      // 图片上传相关函数
      // Func01:uplaodFile,必须返回Promise
      uplaodFile(files) {
      //Promise的callback里面必须resolve({urls})表示成功,否则表示失败
      return new Promise((resolve, reject) => {
      const tempFilePaths = files.tempFilePaths;
      const that = this;
      let finished = {
      urls: []
      } //本次上次成功的URLs存入这个变量,被success方法的e.detail承接

      for (var i = 0; i < tempFilePaths.length; i++) {
      let filePath = tempFilePaths[i] //原名
      let cloudPath = new Date().getTime() + '-' + filePath.substr(filePath.lastIndexOf('/') + 1) //云存储文件名
      cos.postObject({
      Bucket: 'BucketName', //对象储存桶的名称
      Region: 'ap-guangzhou', //所属地域
      Key: 'dir/' + cloudPath, //存储在dir文件夹里面
      FilePath: filePath,
      onProgress: function (info) {
      console.log('进度条', JSON.stringify(info));
      }
      }, function (err, data) {
      // 这里用的是回调函数的形式,也可以用promise方式
      if (err) {
      console.log('上传失败', err);
      } else {
      finished.urls.push({
      url: app.globalData.cdnHost + 'dogs/' + cloudPath
      }) //成功一个存一个到本次上传成功列表
      //如果本次上传的文件都完成 或全局已经存满1张,resolve退出
      if (finished.urls.length === tempFilePaths.length || that.data.files.length + finished.urls.length == this.data.maximgs) {
      resolve(finished)
      }
      }
      });
      }
      })
      },
      // Func02:uploadSuccess,上传成功函数
      uploadSuccess(e) {
      console.log('upload success', e.detail)
      // 将新上传的urls接到目前的photo上
      this.data.photo = this.data.photo.concat(e.detail.urls)
      this.setData({
      photo: this.data.photo
      })
      wx.hideLoading()
      },
      // Func03:delimg删除图片
      // detail为{index, item},index表示删除的图片的下标,item为图片对象。
      delimg(e) {
      this.data.photo.splice(this.data.photo.findIndex(item => item == e.detail.item), 1)
      },
      // Func04:uploadError,上传失败函数
      uploadError(e) {
      console.log('upload error', e.detail)
      wx.hideLoading()
      },
      // Func05:selectFile,mpuploader选择图片时的过滤函数,返回true表示图片有效
      selectFile(files) {
      wx.showLoading({
      title: '',
      })
      }
      })

项目源码github地址

2023-3-21 13:55 项目基本完成,过段时间开源项目前端代码……
2023-4-23 8:31

  1. 前端项目代码github链接:

    https://github.com/2aurora2/PuppyHome_WeChatApp

  2. B站演示视频链接:

    https://www.bilibili.com/video/BV1Fv4y1J7va/?spm_id_from=333.999.0.0&vd_source=4eacc3ec90d2d047330b4cb99502e3a4

实用CSS工具

  1. All elements made with CSS and HTML (uiverse.io)
  2. Flex Cheatsheet (yoksel.github.io)
  3. Neumorphism/Soft UI CSS shadow generator