小程序云开发点赞案例实现及环境vant插件配置等问题

最近在搞小程序的比赛,咋就是说浅记录一下学习小程序开发途中踩过的坑,遇到的让人高血压的问题,另外本文档是本人在b站学习新视觉课程所记录的,大家有需要可以去b站看看。本文档紧跟上个文档的内容,主要讲述了如何配置vant环境nodejs安装,及一些遇到的问题,如何解决与调试。

安装插件

安装nodejs 配置环境变量

vant weapp 插件

1.在miniprogram右键打开cmd输入下列命令安装插件
npm i @vant/weapp -S --production
2.点击工具 – 构建npm

使用 vant weapp 插件

  • 在app.json或index.json中引入组件
    “usingComponents”: {
    “van-button”: “@vant/weapp/button/index”
    }
  //app.json
  "sitemapLocation": "sitemap.json",
  //记得将v2 删掉
  //"style": "v2",
  "usingComponents": {
    "van-button": "@vant/weapp/button/index"
    // ...其他放这
    }
    

例如 点赞图标

//index.html
<view class="out">  
  <view class="list">    
    <view class="row" wx:for="{{8}}" wx:key="index">
      <navigator class="box" url="/pages/detail/detail">
        <view class="pic">
          <image class="img" mode="aspectFill" src="../../images/psmajor02.jpg2.jpg"/>
        </view>
        <view class="text">
          <view class="title">这里是标题文字这里是标题文字这里是标题文字这里是标题文字这里是标题文字这里是标题文字这里是标题文字这里是标题文字这里是标题文字</view>
          <view class="info">
            <view><van-icon name="clock-o" />12-12</view>
            <view><van-icon name="eye-o"/>88</view>
            <view><van-icon name="good-job-o" /> 12</view>
          </view>
        </view>
      </navigator>
    </view>


  </view>
</view>


//index.css
.out .box .info{font-size: 28rpx; color:#888; display: flex; justify-content: space-between;}
.out .box .info .van-icon{margin-right: 5rpx;}

CMS 内容模型管理

配置cms

  • 注册cms 点击云开发平台 更多 内容管理 开通 设置账号密码
  • 点击网址登录cms平台,输入账号密码
  • 创建项目 id是唯一标识符,可以diy
  • 内容模型 — 相当于创建数据库表 —单行字符串相当于列名

通过云函数获取指定数据

关于环境的报错
解决方法:提前配置环境变量env

  • 首先在app.js中配置env
//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: 'bruan-cloud-8gr3l2csc1dd6dac',
        traceUser: true,
      })
    }

    this.globalData = {}
  }
})

  • 在云函数中指定env
// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
  • 在页面调用callfuntion 时指定环境变量env
  getData(size=0){
    wx.cloud.callFunction({
      name:"artical_list_get",
      data:{
        size:size,
      },
      //关键
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    }).then(res=>console.log(res))
  },

渲染数据并且添加loading加载样式

  • 在index文件夹中的index.js–getData部分代码如下
 onLoad: function (options) {
    this.getData(0);
  },
  //独立开来写
  getData(size=0){
    wx.cloud.callFunction({
      name:"artical_list_get",
      data:{
        size:size,
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    }).then(res=>{
      console.log(res);
      this.setData({
        listArr:res.result.data
      })
    })
  • 云函数 article_list_get 代码如下
// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
  let size = event.size;
  // limit()限制页面 一页出现七个 
  // skip() 跳过多少个新闻
  return await db.collection("article_list").orderBy("_createTime","desc")
  .limit(7)
  .skip(size)
  .get();
}
  • loading 加载样式
 <view class="loading">
       <van-loading type="spinner" color="#1989fa" >
       <view wx:if="true">加载中...</view> 
       <view wx:if="">没有更多了~</view>
       </van-loading>
    </view>
  • app.json中的配置项
"usingComponents": {
    "van-button": "@vant/weapp/button/index",
    "van-icon": "@vant/weapp/icon/index",
    "van-loading": "@vant/weapp/loading/index"
    }

触底并且加载更多 loading样式

触底事件处理函数

   /**
   * 页面的初始数据
   */
  data: {
    listArr:[],
  },
  getData(size=0){
    wx.cloud.callFunction({
      name:"artical_list_get",
      data:{ 
        size:size,
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    }).then(res=>{
      console.log(res);
      this.setData({
        listArr:res.result.data
      })
    })
  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
    this.getData(this.data.listArr.length);
  },

此时还无法进行有效的下拉操作,会出现断层,需要对新老数据进行一个叠加连接。

getData(size=0){
    wx.cloud.callFunction({
      name:"artical_list_get",
      data:{ 
        size:size,
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    }).then(res=>{
      //新老数据链接
      let oldData = this.data.listArr;
      let newData = oldData.concat(res.result.data);
      console.log(res);
      this.setData({
        listArr:newData
      })
    })
  },

触底加载更多时状态的转变,即出现的是加载更多。。还是加载完成
解决:在getData中判断得到的数组长度是否小于0,在对定义的全局变量做改变

  data: {
    listArr:[],
    //全局变量loading
    loading : "true",
  },

 getData(size=0){
    wx.cloud.callFunction({
      name:"artical_list_get",
      data:{ 
        size:size,
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    }).then(res=>{
      if(res.result.data<=0){
        this.setData({
          loading:false,
        })
      } 
      let oldData = this.data.listArr;
      let newData = oldData.concat(res.result.data);
      console.log(res);
      this.setData({
        listArr:newData
      })
    })
  },

前端html界面loading样式需要做出判断

  
    <view class="loading">
       <van-loading type="spinner" color="#1989fa" >
       <view wx:if="{{loading}}">加载中...</view> 
       <view wx:else="">没有更多了~</view>
       </van-loading>
    </view>

util工具方法修改时间戳

common.js 常用工具类代码

module.exports={
 //数量变化值
 getNumber(num){
   if(num<1000){
     return num
   }else if(num>=1000 && num<10000){
     let n =(num/1000).toFixed(1)+"k"
     return n
   }else if(num>=10000 && num<100000){
     let n =(num/10000).toFixed(1)+"w"
     return n
   }else if(num>=100000){
     return "10w+"
   }else{
     return 0
   }
 },
 //多功能时间戳转格式方法
 getTime(t,type=0){
   let time = new Date(t);
   let year = time.getFullYear()+"";
   let month =time.getMonth()+1;
   month = month< 10 ? "0"+month:month+"";
   let day =time.getDate();
   day = day<10 ? "0"+day:day+"";
   let hours=time.getHours();
   hours = hours<10 ? "0"+hours :hours+"";
   let min = time.getMinutes();
   min=min<10 ? "0"+min :min+"";
   let second = time.getSeconds();
   second = second<10? "0"+second :second+"";
   let arr=[
     `${year}-${month}-${day}`,
     `${year}${month}${day}`,       
     `${year}-${month}-${day} ${hours}:${min}:${second}`,
     `${year}${month}${day}${hours}${min}${second}`,
     `${month}-${day}`,
     `${month}${day}`,
     `${hours}:${min}:${second}`,
     `${hours}${min}${second}`,
   ]
   return arr[type]
 }
}

工具类的引入

// miniprogram/pages/index/index.js
import common from "../../util/common"
Page({

 /**
  * 页面的初始数据
  */
 data: {
   listArr:[],
   loading : "true",
 },

还是在getData中对数据进行预处理

getData(size=0){
   wx.cloud.callFunction({
     name:"artical_list_get",
     data:{ 
       size:size,
     },
     config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
   }).then(res=>{
     // 修改时间戳 还有 格式化数字
     res.result.data.forEach(item=>{
       let hits = item.hits?item.hits:0
       item.hits = common.getNumber(hits)
       item._createTime=common.getTime(item._createTime,4)
     })
     if(res.result.data<=0){
       this.setData({
         loading:false,
       })
     } 
     let oldData = this.data.listArr;
     let newData = oldData.concat(res.result.data);
     console.log(res);
     this.setData({
       listArr:newData
     })
   })
 },

列表页跳转到详情页

如何拿取id等信息实现前后交互

代码如图

//这里定义 id = _id 传到js文件中 将id在js中定为全局变量以保存其值
<navigator class="box" url="/pages/detail/detail?id={{item._id}}">
       <view class="pic">
         <image class="img" mode="aspectFill" src="{{item.picture}}"/>
       </view>
       <view class="text">
         <view class="title">{{item.title}}</view>
         <view class="info">
           <view><van-icon name="clock-o" />{{item._createTime}}</view>
           <view wx:if="{{item.hits}}"><van-icon name="eye-o"/>{{item.hits}}</view>
           <view><van-icon name="good-job-o" /> 12</view>
         </view>
       </view>
     </navigator>
// detail.js
let id;

Page({
//页面加载时拿取数据
/**
  * 生命周期函数--监听页面加载
  */
 onLoad: function (options) {
   id = options.id;
   console.log(id);
   this.getDetail();
 },
 /**
  * 页面的初始数据
  */
 data: {
   detail:{}
 },
 getDetail(){
   wx.cloud.callFunction({
     name:"article_list_get_one",
     data:{
       id:id
     }
   }).then(res=>{
     console.log(res);
     this.setData(res=>{
       this.setData({
         detail:res.result.data
       })
     })
   })
 },
//云函数
// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
  let id = event.id;
  return await db.collection("article_list").doc(id).get()
}

富文本编辑器,用rich-text进行格式转换

<rich-text nodes="{{detail.content}}"></rich-text>

使用正则表达式修改富文本内的图片

图像显示不全的问题

getDetail(){
    wx.cloud.callFunction({
      name:"article_list_get_one",
      data:{
        id:id
      }
    }).then(res=>{
      console.log(res);
      // 使用正则表达式替换
      res.result.data.content=
      res.result.data.content.replace(/<img /,"<img style='max-width:100%'")
      this.setData({
          detail:res.result.data 
      })
    })
  },

wxs的语法

将util中常用的工具文件转移到新搭建的wxs文件夹中
不能使用es6格式
++要用 :funtion
var 不能用let
Date() --> getDate(t)++

module.exports={
  //数量变化值
  getNumber:function(num){
    if(num<1000){
      return num
    }else if(num>=1000 && num<10000){
      var n =(num/1000).toFixed(1)+"k"
      return n
    }else if(num>=10000 && num<100000){
      var n =(num/10000).toFixed(1)+"w"
      return n
    }else if(num>=100000){
      return "10w+"
    }else{
      return 0
    }
  },
}
//多功能时间戳转格式方法
  getTime:function(t,type=0){
    var time = getDate(t);
    var year = time.getFullYear()+"";
    var month =time.getMonth()+1;
    month = month< 10 ? 0+month:month+"";
    var day =time.getDate();
    day = day<10 ? 0+day:day+"";
    var hours=time.getHours();
    hours = hours<10 ? 0+hours :hours+"";
    var min = time.getMinutes();
    min=min<10 ? 0+min :min+"";
    var second = time.getSeconds();
    second = second<10? 0+second :second+"";
    var arr=[
      year+"-"+month+"-"+day,      
      year+"-"+month+"-"+day+" "+hours+":"+min+":"+second,
    ]
    return arr[type]
  }

用户授权及其使用

// 点击点赞按钮
  clickLike(){
 //getUserInfo 已被禁用
    wx.getUserProfile({
      desc: '授权需要',
      success:res=>{
        console.log(res);
        //对于res对象的解构
        let {avatarUrl,nickName}=res.userInfo
        let posttime=Date.now();
    //id 是本来就有的全局变量
        console.log(nickName,avatarUrl,posttime,id);
      }
    })
   
  },

缓存

用缓存保存用户信息,就不用设置那么多变量了

 // 点击点赞按钮
  clickLike(){
    wx.getUserProfile({
      desc: '授权需要',
      success:res=>{
        wx.setStorageSync('userInfo', res.userInfo)      }
    })
  },

将用户信息存储到app.js中
需要在文件中声明app对象,并且调用方法

//定义app对象
const app = getApp();
Page({
    // 点击点赞按钮
      clickLike(){
        wx.getUserProfile({
         desc: '授权需要',
         success:res=>{
         //缓存机制
         wx.setStorageSync('userInfo', res.userInfo)      
          //存入全局变量中
         //setStorageSync 一刷新数据就会丢失
          app.globalData.userInfo=res.userInfo
      }
    })
  },

判断用户是否登录的全局函数

//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: 'bruan-cloud-8gr3l2csc1dd6dac',
        traceUser: true,
      })
    }
    this.globalData = {}
  },
  hasUserInfo(){
  //刚开始没有这个的,直接到下一步
    if(this.globalData.userInfo && this.globalData.userInfo.nickName){
      return true;
    }
    //判断缓存里面有没有记录
    let userInfo = wx.getStorageSync('userInfo');
    //如果有就把缓存赋值给全局变量
    if(userInfo&&userInfo.nickName){
    //重新赋值一次
      this.globalData.userInfo = userInfo;
      //返回真
      return true;
    }else{
      return false;
    }
  },
})

detail.js中

// pages/detail/detail.js
let id;
const app = getApp();
Page({

  /**
   * 页面的初始数据
   */
  data: {
    detail:{}
  },
  // 点击点赞按钮
  clickLike(){
    if(app.hasUserInfo()){
      console.log("可以点赞了");
    }else{
      wx.getUserProfile({
        desc: '授权需要',
        success:res=>{
          wx.setStorageSync('userInfo', res.userInfo)      
          app.globalData.userInfo=res.userInfo
        }
      })
    }
    
  },
  //发送到数据库里
  pushData(){
    let posttime=Date.now();
    wx.cloud.callFunction({
      data:{
          nickName,
          avatarUrl,
          posttime,
          artid:id
      },
      name:"article_liske_add"
    })
  },
  // 获取详细数据
  getDetail(){
    wx.cloud.callFunction({
      name:"article_list_get_one",
      data:{
        id:id
      }
    }).then(res=>{
      console.log(res);
      res.result.data.content=
      res.result.data.content.replace(/<img /,"<img style='max-width:100%'")
      this.setData({
          detail:res.result.data 
      })
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    id = options.id;
    console.log(id);
    this.getDetail();
  },
}

发送到数据库

云函数

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
const db = cloud.database();

// 云函数入口函数
exports.main = async (event, context) => {
//接收当前用户的openid
  const openid = cloud.getWXContext().OPENID
  //d对传入对象进行解构
  let {nickName,avatarUrl,posttime,artid}=event;
  //写入数据库
  return await db.collection("article_like").add({
    data:{
      nickName,avatarUrl,posttime,artid,openid
    }
  })
}

detail.js

//发送到数据库里
  pushData(){
    let posttime=Date.now();
    wx.cloud.callFunction({
      name:"article_like_add",
      data:{
          nickName:app.globalData.userInfo.nickName,
          avatarUrl:app.globalData.userInfo.avatarUrl,
          posttime,
          artid:id
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    })
  },

获取真实用户的点赞个数

<wxs module="public" src="../../wxs/public.wxs"></wxs>
<view class="detail">
  <view class="title">{{detail.title}}</view>
  <view class="content">
  <rich-text nodes="{{detail.content}}"></rich-text>
  </view>  
  <view class="info">
    <view class="row">作者:{{detail.author}}</view> 
    <view class="row">发布时间:{{public.getTime(detail._createTime,1)}}</view> 
    <view class="row" wx:if="{{detail.hits}}">点击量:{{public.getNumber(detail.hits)}}</view> 
  </view>
  <view class="recommend active" bindtap="clickLike">
    <view class="icon"><van-icon name="good-job" /></view>
    <--!    点赞数量     >
    <view class="num">{{detail.zanSize}}</view>
  </view>

  <view class="userinfo">
    <view class="text">- 赞过的用户 -</view>
    <view class="picgroup">
      <image wx:for="{{6}}" wx:key="index" src="../../images/2019_ps.jpg" mode="aspectFill"></image>
    </view>    
  </view>
</view>

articl_list_get_one云函数的index.js文件

// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
  let id = event.id;
  let res1 = await db.collection("article_list").doc(id).get();
  //通过id对比查找点赞数目
  let res2 = await db.collection("article_like").where({
    artid:id
  }).count();
  res1.data.zanSize = res2.total;
  return res1;
}

更新点赞的头像,点赞后的用户可以高亮显示

节约资源可以用field函数做映射
点我查看field文档

示例代码
只返回 description, done 和 progress 三个字段:

db.collection('todos').field({
  description: true,
  done: true,
  progress: true,
})
  .get()
  .then(console.log)
  .catch(console.error)

articl_list_get_one文件中

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env:"bruan-cloud-8gr3l2csc1dd6dac"
})
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
  let openid = cloud.getWXContext().OPENID;
  let id = event.id;
  let res1 = await db.collection("article_list").doc(id).get();
  //通过id对比查找点赞数目
  let res2 = await db.collection("article_like").where({
    artid:id
  }).count();
  //获取点赞用户头像
  let res3 = await db.collection("article_like").where({
    artid:id
  }).field({
    avatarUrl:true
  }).orderBy("posttime","desc").limit(5).get();
  //判断是否已经点赞过
  let res4 = await db.collection("article_like").where({
    openid:openid,    
    artid:id
  }).count();
  if(res4.total){
    res1.data.onlike = true
  }else{
    res1.data.onlike = false
  }
  res1.data.zanSize = res2.total;
  res1.data.userArr = res3.data.reverse();
  return res1;
}
<wxs module="public" src="../../wxs/public.wxs"></wxs>
<view class="detail">
  <view class="title">{{detail.title}}</view>
  <view class="content">
  <rich-text nodes="{{detail.content}}"></rich-text>
  </view>  
  <view class="info">
    <view class="row">作者:{{detail.author}}</view> 
    <view class="row">发布时间:{{public.getTime(detail._createTime,1)}}</view> 
    <view class="row" wx:if="{{detail.hits}}">点击量:{{public.getNumber(detail.hits)}}</view> 
  </view>
  <view class="recommend {{detail.onlike? '':'active'}}" bindtap="clickLike">
    <view class="icon"><van-icon name="good-job" /></view>
    <view class="num">{{detail.zanSize}}</view>
  </view>

  <view class="userinfo">
    <view class="text">- 赞过的用户 -</view>
    <view class="picgroup">
      <image wx:for="{{detail.userArr}}" wx:key="index" src="{{item.avatarUrl}}" mode="aspectFill"></image>
    </view>    
  </view>
</view>

点赞时头像的变动,还有取消的变动,数字等

detail 文件中的 点赞

 //发送到数据库里
  pushData(){

    let onlike = this.data.detail.onlike;
    let zanSize = this.data.detail.zanSize;
    let userArr = this.data.detail.userArr;
    if(onlike){
      zanSize--
      userArr.forEach((item,index)=>{
        if(item.avatarUrl==app.globalData.userInfo.avatarUrl){
          // 已经有头像了就把他去掉 
          userArr.splice(index,1)
        }
      })
    }else{
      zanSize++
      userArr.push({avatarUrl:app.globalData.userInfo.avatarUrl})
      // 截取前5个
      if(userArr.length>=5){
        userArr=userArr.slice(1,6)
      }
    }
    //动态更新
    this.setData({
      "detail.onlike":!onlike,
      "detail.zanSize":zanSize,
      "detail.userArr":userArr,
    })
    //传入数据库
    let posttime=Date.now();
    wx.cloud.callFunction({
      name:"article_like_add",
      data:{
          nickName:app.globalData.userInfo.nickName,
          avatarUrl:app.globalData.userInfo.avatarUrl,
          posttime,
          //将文章id传入到点赞表中的artid
          artid:id
      },
      config:{ env: 'bruan-cloud-8gr3l2csc1dd6dac' },
    })
  },

美化UI界面骨架屏加载效果

<wxs module="public" src="../../wxs/public.wxs"></wxs>


<view class="detail">
  <van-skeleton title row="8" loading="{{loading}}">
    <view class="title">{{detail.title}}</view>
    <view class="content">
    <rich-text nodes="{{detail.content}}"></rich-text>
    </view>  
    <view class="info">
      <view class="row">作者:{{detail.author}}</view> 
      <view class="row">发布时间:{{public.getTime(detail._createTime,1)}}</view> 
      <view class="row" wx:if="{{detail.hits}}">点击量:{{public.getNumber(detail.hits)}}</view> 
    </view>
    <view class="recommend {{detail.onlike? '':'active'}}" bindtap="clickLike">
      <view class="icon"><van-icon name="good-job" /></view>
      <view class="num">{{detail.zanSize}}</view>
    </view>

    <view class="userinfo" >
      <view class="text">- 赞过的用户 -</view>
      <view class="picgroup">
        <image wx:for="{{detail.userArr}}" wx:key="index" src="{{item.avatarUrl}}" mode="aspectFill"></image>
      </view>    
    </view>
    
  </van-skeleton> 
</view>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值