目前市面上提供了一些免费开源的第三方小程序UI组件库,可以下载后放到项目文件夹中直接使用,比起开发者从头开始自定义组件更为方便、高效。本次考虑使用第三方UI组件来实现界面的视觉统一。本次以有赞第三方UI组件库Vant Weapp为例,介绍如何使用自定义组件配合云开发中的数据库基本功能实现一个生日管家小程序。

本项目一共三个页面,即首页、好友信息编辑页和好友信息展示页。

首页功能需求:1.包含“添加新朋友”按钮、搜索框和好友列表。2.点击“添加新朋友”按钮后跳转到好友信息编辑页,可以录入数据。3.搜索框可以根据好友姓名关键词查找指定好友。4.好友生日列表需要展示好友姓名、生日、距离下个生日还有多少天,并且点击好友头像可以跳转到好友信息展示页查看详情。

好友信息编辑页功能需求:1.以表单的形式要求用户录入好友的姓名、性别、生日、电话、关系等信息。2.“保存记录”按钮用于添加或更新好友数据到云数据库中。3.“取消表单”按钮用于取消本次填写,返回上一页。

好友信息展示页面功能需求:1.顶端展示好友的头像和姓名。2.中间列表展示好友的性别、电话、和用户本人关系、距离出生已经多少天、距离下个生日还有多少天。3.下方是“修改”按钮和“删除”按钮,分别用于跳转编辑页面和直接删除当前好友。

一、部署云数据库

1.打开云开发控制台,创建一个新的数据集,例如birthday。

2.检查birthday数据集的权限,确认是“仅创建者及管理员可读写”。

二、创建页面文件

本项目有三个页面文件,分别是index(首页)、edit(好友信息编辑页)和detail(好友信息展示页)。打开app.json文件,在pages属性中追加edit和detail页面的路径描述,保存后pages文件夹下会自动生成后面的两个页面文件。注:须将app.json文件中的"style":"v2" 手动删除,这句代码是表示使用小程序新版的基础组件样式,会对当前的UI组件库的部分组件造成样式干扰。

三、创建其他文件

接下来创建其他自定义文件:images:用于存放图片素材,已存在;utils:用于存放公共JS文件,需要手动创建;vant-weapp:用于存放有赞UI库的dist目录,需要手动创建。

以上三步具体操作略。

四:界面及主要代码

1.首页

<!--index.wxml-->
<!-- 添加新朋友按钮 -->
<van-button block type='default' bindtap='addFriend'>添加新朋友</van-button>
<!-- 搜索区域 -->
<van-search placeholder="请输入搜索关键词" show-action bind:search="onSearch" bind:cancel="onCancel" />
<!-- 好友列表 -->
<block wx:for='{{friendsList}}' wx:key='{{item._id}}'>
  <van-card centered desc="{{(item.date)}}" title="{{item.name}}" thumb-link='../detail/detail?id={{item._id}}&n2={{item.n}}' thumb="{{item.avatar}}">
    <view slot="footer">
      距离下个生日
      <text style='color:red;font-weight:bold;'>{{item.n}}天</text>
    </view>
  </van-card>
</block>
//index.js
var utils = require('../../utils/utils.js')
const db = wx.cloud.database()
const birthday = db.collection('birthday')
Page({
  /**
   * 页面的初始数据
   */
  data: {
  },
  /**
   * 自定义函数--添加好友信息
   */
  addFriend: function(options) {
    let id = 'new'
    wx.navigateTo({
      url: '../edit/edit?id=' + id
    })
  },
  /**
   * 自定义函数--取消搜索
   */
  onCancel: function(e) {
    //获取好友列表
    this.getFriendsList()
  },
  /**
   * 自定义函数--搜索关键词
   */
  onSearch: function(e) {
    //获取搜索关键词
    let keyword = e.detail
    //使用正则表达式模糊查询
    birthday.where({
      name: db.RegExp({
        regexp: keyword,
        options: 'i',
      })
    }).orderBy('date', 'asc').get({
      success: res => {
        this.processData(res.data)
      }
    })
  },
  /**
   * 自定义函数--获取好友列表
   */
  getFriendsList: function() {
    //查找好友列表,按照出生日期升序排列
    birthday.orderBy('date', 'asc').get({
      success: res => {
        this.processData(res.data)
      }
    })
  },
  /**
   * 自定义函数--处理数据(计算距离下个生日天数)
   */
  processData: function(list) {
    for (var i = 0; i < list.length; i++) {
      //获取不带年份的生日
      let date = list[i].date
      //计算相差几天
      let n = utils.getNextBirthday(date)
      list[i].n = n
    }
    this.setData({
      friendsList: list
    })
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {
    //获取好友列表
    this.getFriendsList()
  },
})
index.json文件:
{
  "usingComponents": {
    "van-search": "/vant-weapp/dist/search/index",
    "van-card": "/vant-weapp/dist/card/index",
    "van-button": "/vant-weapp/dist/button/index"
  }
}
2.好友信息编辑页

<!--pages/edit/edit.wxml-->
<form bindsubmit='onSubmit'>
  <!-- 第1行 -->
  <van-row>
    <van-col span="6">
      <label>姓名</label>
    </van-col>
    <van-col span="18">
      <input name='name' placeholder='请输入姓名' value='{{info.name}}'></input>
    </van-col>
  </van-row>
  <!-- 第2行 -->
  <van-row>
    <van-col span="6">
      <label>性别</label>
    </van-col>
    <van-col span="18">
      <radio-group name='gender'>
        <radio color='#DE6E6D' value='1' checked='{{info.gender==1}}' />男
        <radio color='#DE6E6D' value='2' checked='{{info.gender==2}}' />女
      </radio-group>
    </van-col>
  </van-row>
  <!-- 第3行 -->
  <van-row>
    <van-col span="6">
      <label>生日</label>
    </van-col>
    <van-col span="18">
      <picker name='birthday' mode='date' bindchange='dateChange' value='{{date}}'>
        <view>{{date}}</view>
      </picker>
    </van-col>
  </van-row>
  <!-- 第4行 -->
  <van-row>
    <van-col span="6">
      <label>电话</label>
    </van-col>
    <van-col span="18">
      <input name='tel' type='number' placeholder='请输入联系电话' value='{{info.tel}}'></input>
    </van-col>
  </van-row>
  <!-- 第5行 -->
  <van-row>
    <van-col span="6">
      <label>关系</label>
    </van-col>
    <van-col span="18">
      <input name='relationship' placeholder='描述你们的关系' value='{{info.relationship}}'></input>
    </van-col>
  </van-row>
  <!-- 第6行 -->
  <van-row>
    <van-col span="18" offset="3">
      <button form-type='submit'>保存记录</button>
    </van-col>
    <van-col span="18" offset="3">
      <button bindtap='cancelEdit'>取消修改</button>
    </van-col>
  </van-row>
</form>
// pages/edit/edit.js
const db = wx.cloud.database()
const birthday = db.collection('birthday')
Page({
  /**
   * 页面的初始数据
   */
  data: {
    date: '点击设置生日'
  },
  /**
   * 自定义函数--更新页面上显示的出生日期
   */
  dateChange: function(e) {
    this.setData({
      date: e.detail.value
    })
  },
  /**
   * 自定义函数--提交表单数据
   */
  onSubmit: function(e) {
    //获取表单中提交的全部数据
    let info = e.detail.value
    //追加一个不带年份的生日信息
    let date = info.birthday.substring(5)
    info.date = date
    // 获取好友id
    let id = this.data.id
    // 添加新朋友
    if (id == 'new') {
      //随机选择一个头像
      let i = Math.ceil(Math.random() * 9)
      info.avatar = '/images/avatar/00' + i + '.jpg'
      // 往云数据库中添加当前好友信息
      birthday.add({
        data: info,
        success: res => {
          // 成功后返回首页
          wx.navigateBack()
        },
        fail: err => {
          // 失败提示
          wx.showToast({
            title: '保存失败',
          })
        }
      })
    }
    // 好友已存在
    else {
      // 根据好友id更新数据
      birthday.doc(id).update({
        data: info,
        success: res => {
          // 成功后返回上一页
          wx.navigateBack()
        },
        fail: err => {
          // 失败提示
          wx.showToast({
            title: '保存失败',
          })
        }
      })
    }
  },
  /**
   * 自定义函数--取消修改并返回上一页
   */
  cancelEdit: function() {
    wx.navigateBack()
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    // 获取携带的参数id
    let id = options.id
    // 更新id数据
    this.setData({
      id: id
    })
    // 如果好友已存在
    if (id != 'new') {
      // 根据好友id从云数据库获取好友信息
      birthday.doc(id).get({
        success: res => {
          this.setData({
            info: res.data,
            date: res.data.birthday
          })
        }
      })
    }
  },
})
edit.json文件:
{
  "usingComponents": {
    "van-row": "/vant-weapp/dist/row/index",
    "van-col": "/vant-weapp/dist/col/index"
  }
}

3.好友信息展示页

<!--pages/detail/detail.wxml-->
<!-- 顶部头像和姓名 -->
<view class='avatarBox'>
  <image src='{{info.avatar}}'></image>
  <view>{{info.name}}</view>
</view>
<!-- 个人信息展示 -->
<van-cell-group>
  <van-cell title="性别" value="{{info.gender==1?'男':'女'}}" />
  <van-cell title="生日" value="{{info.birthday}}" />
  <van-cell title="电话" value="{{info.tel}}" />
  <van-cell title="关系" value="{{info.relationship}}" />
  <van-cell title="距离出生已经" value="{{n1}}天" />
  <van-cell title="距离下个生日还有" value="{{n2}}天" />
</van-cell-group>
<!-- 按钮区域 -->
<van-button block type='warning' bindtap='editFriend'>修改</van-button>
<van-button block type='danger' bindtap='deleteFriend'>删除</van-button>
 
// pages/detail/detail.js
const utils = require('../../utils/utils.js')
const db = wx.cloud.database()
const birthday = db.collection('birthday')
Page({
  /**
   * 自定义函数--编辑好友信息
   */
  editFriend: function() {
    //获取当前好友id
    let id = this.data.id
    //跳转到编辑页面并带参数id
    wx.navigateTo({
      url: '../edit/edit?id=' + id
    })
  },
  /**
   * 自定义函数--删除好友
   */
  deleteFriend: function() {
    //获取当前好友id
    let id = this.data.id
    //删除当前好友
    birthday.doc(id).remove({
      success: res => {
        //删除成功后返回上一页
        wx.navigateBack()
      }
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    //获取从首页传来的参数
    let id = options.id//好友id
    let n2 = options.n2//距离下个生日天数
    //更新页面数据
    this.setData({
      id: id,
      n2: n2
    })
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {
    //获取当前好友id
    let id = this.data.id
    //从云数据库查找当前好友信息
    birthday.doc(id).get({
      success: res => {
        //获取当前日期
        let today = utils.getToday()
        //获取当前年份
        let y = utils.getFullYear()
        //获取生日(带年份)
        let b_day = res.data.birthday
        //计算距离出生的天数
        let n1 = utils.dateDiff(b_day, today)
        //更新页面数据
        this.setData({
          info: res.data,
          n1: n1
        })
      }
    })
  },
})
detail.json文件:
{
  "usingComponents": {
    "van-button": "/vant-weapp/dist/button/index",
    "van-cell": "/vant-weapp/dist/cell/index",
    "van-cell-group": "/vant-weapp/dist/cell-group/index"
  }
}
4.其他代码:
utils.js文件:
//获取当前格式化日期
function getToday(){
  //获取当前日期对象
  var now = new Date()
  //获取当前年份(4位数)
  var y = now.getFullYear()
  //获取当前月份
  var m = now.getMonth() + 1
  //获取当前日期
  var d = now.getDate()
  //格式化当天日期
  var today = y + '/' + m + '/' + d
  return today
}
//获取当前年份(4位数)
function getFullYear() {
  //获取当前日期对象
  var now = new Date()
  //获取当前年份(4位数)
  var y = now.getFullYear()
  return y
}
//计算天数差  
function dateDiff(sDate1, sDate2) {
  sDate1 = sDate1.replace(/-/g, '/')
  sDate2 = sDate2.replace(/-/g, '/')
  var oDate1 = new Date(sDate1)
  var oDate2 = new Date(sDate2)
  var iDays = parseInt((oDate2 - oDate1) / 1000 / 3600 / 24)
  //把相差的毫秒数转换为天数  
  return iDays
}
//计算距离下个生日还有多少天
function getNextBirthday(b_day) {
  //获取当前日期
  var today = getToday()
  //获取当前年份
  var y = getFullYear()
  //计算日期差
  var n = dateDiff(today, y + '-' + b_day)
  //今年生日已经过完了
  if (n < 0) {
    //获得明年年份
    y++
    //计算日期差
    n = dateDiff(today, y + '-' + b_day)
  }
  return n
}
module.exports = {
  getToday:getToday,
  getFullYear:getFullYear,
  dateDiff: dateDiff,
  getNextBirthday: getNextBirthday
}
还有其他代码略。
小知识:onLoad()函数在页面第一次加载时触发,从跳转页面返回时不触发,可以传递参数。
onShow()函数在页面显示时调用,可多次调用 ,不能传递参数。
某页面同时有onLoad()和onShow()函数时,该页面第一次加载时onLoad()函数会先于onShow()执行;页面切换时onShow()会先于onLoad()执行。

二十、基于Vant Weapp的生日管家的更多相关文章

  1. 微信小程序(二十)-UI组件(Vant Weapp)-01按装配置

    1.官网 https://vant-contrib.gitee.io/vant-weapp/#/intro https://gitee.com/vant-contrib/vant-weapp 2.按装 ...

  2. 微信小程序(二十)-UI组件(Vant Weapp)-02使用

    1.按钮使用 https://vant-contrib.gitee.io/vant-weapp/#/button 1.全局引入,在app.json中引入组件 "usingComponents ...

  3. 通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享

    今天这篇博文的主要目的是分享一下我设计Saga的实现思路来抛砖引玉,其实Saga本身非常的类似于一个简单的工作流体系,相比工作流不一样的部分在于它没有工作流的复杂逻辑处理机制(比如会签),没有条件分支 ...

  4. Android笔记二十四.Android基于回调的事件处理机制

        假设说事件监听机制是一种托付式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源和事件监听器是统一的,或者说事件监听器全然消失了,当用户在GUI控件上激发某个事件时,控 ...

  5. SQL注入之Sqli-labs系列第二十一关(基于复杂性的cookie POST报错注入)和二十二关(基于双引号的cookie POST报错注入)

    开始挑战第二十一关(Cookie Injection- Error Based- complex - string) 和二十二关(Cookie Injection- Error Based- Doub ...

  6. WCF学习之旅—TcpTrace工具(二十六)

    止文(WCF学习之旅—TcpTrace工具(二十五))介绍了关于TcpTrance的一种使用方式,接下来介绍第二种使用方式. 三.通过ListenUri实现基于tcpTracer的消息路由 对于路由的 ...

  7. 无废话ExtJs 入门教程二十[数据交互:AJAX]

    无废话ExtJs 入门教程二十[数据交互:AJAX] extjs技术交流,欢迎加群(521711109) 1.代码如下: 1 <!DOCTYPE html PUBLIC "-//W3C ...

  8. Bootstrap<基础二十四> 缩略图

    Bootstrap 缩略图.大多数站点都需要在网格中布局图像.视频.文本等.Bootstrap 通过缩略图为此提供了一种简便的方式.使用 Bootstrap 创建缩略图的步骤如下: 在图像周围添加带有 ...

  9. Web 开发人员和设计师必读文章推荐【系列二十九】

    <Web 前端开发精华文章推荐>2014年第8期(总第29期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

  10. Web 前端开发人员和设计师必读文章推荐【系列二十八】

    <Web 前端开发精华文章推荐>2014年第7期(总第28期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...

随机推荐

  1. 注册全局图标ts写法

    https://element-plus.gitee.io/zh-CN/component/icon.html#使用图标 仓库地址:https://github.com/Megasu/element- ...

  2. Win7共享账号切换程序

    服务器共享目录需要多账号登录时,需要重启电脑才可切换不同账号登 为了不重启电脑就可立即切换不同账号登,特意写了此款软件, 下载: 链接:https://pan.baidu.com/s/1g_4SCXl ...

  3. python环境配置命令

    在Python中,创建新的环境通常指的是创建一个隔离的Python环境,以便在该环境中安装和管理不同版本的库,而不会影响到系统中其他Python环境的库.这通常用于解决不同项目之间的依赖冲突.下面是一 ...

  4. Assets, Resources and AssetBundles(五):AssetBundle usage patterns

    这是系列文章中的第五章,内容涉及"Unity5"中的资产.资源和资源管理. 本系列的前一章介绍了AssetBundles的基本原理,其中包括各种加载API的低级行为.本章讨论了在实 ...

  5. javaWeb基础之Tomcat

    一.Tomcat:web服务器软件 1. 下载:http://tomcat.apache.org/ 2. 安装:解压压缩包即可. * 注意:安装目录建议不要有中文和空格 3. 卸载:删除目录就行了 4 ...

  6. Cline技术分析:prompt如何驱动大模型对本地文件实现自主变更

    prompt如何驱动大模型对本地文件实现自主变更 在AI技术快速发展的今天,编程方式正在经历一场革命性的变革.从传统的"人写代码"到"AI辅助编程",再到&qu ...

  7. Bagging、Boosting、Stacking的原理

      Bagging.Boosting.Stacking是常见集成学习的形式,它们都是通过对多个学习器进行有机组合,达到比单个学习器性能更好的目标. 一.Bagging 1.算法概述   Bagging ...

  8. 我的get请求为什么没有乱码??

    请求的方式有GET和POST两种放方式.这里主要说明GET请求的中文问题. 傻傻的我以为GET不能提交中文,需要改编码,但是我错了.改了编码反而乱码了??? 原因: Tomcat8 以后tomcat的 ...

  9. SpringBoot整合Web层技术

    目录 1 SpringBoot整合Web层技术 1.1 SpringBoot整合Servlet 1.1.1 方式一 通过注解扫描完成Servlet组件的注册 1.1.1.1 创建Servlet 1.1 ...

  10. 【工具】浏览器插件|Edge浏览器划词翻译插件(可用于翻译PDF文件,截图翻译)

    本文体验版本:Edge v10.1.0 偶然安装了一个国人自13年开发至今的划词翻译浏览器插件,曾经开源,现在闭源. 功能全面到令人落泪. 全面到反手把小绿鲸扔了-- 官方介绍是支持一站式划词 / 截 ...