zoukankan      html  css  js  c++  java
  • 小程序 第一个学习示例(TodoList)

    1. 概述

    1.1 说明

    在微信开发者工具环境下开发一个简易的TodoList功能,以便能够进行学习与熟练小程序相关功能与信息.。

    示例中,初步计划包含以下功能:

      • 1.能够进行新增计划信息
      • 2.计划信息可分为已完成与未完成两种状态信息
      • 3.数据信息可列表显示
      • 4.可以对列表中数据进行标记完成与删除操作
      • 5.可进行分页操作(此处仅为一数据示例)

      备注:目前数据未进行缓存处理,仅为数据操作展示。

    1.2 图例

       

    1.3 图例说明

      1.3.1 列表

      使用三个状态分别控制不同的列表信息,点击不同的状态加载不同的数据:

      • 全部 -- 所有的数据信息都加载至此状态对应列表
      • 已完成 -- 所有已完成状态的数据信息列表
      • 未完成 -- 所有未完成状态的数据信息列表

      1.3.2 新增

      点击列表上的添加按钮显示出新增内容区域,新增内容有确定添加和取消两种功能:

      • 确定添加 -- 把输入至文本框中的内容添加至列表中,状态为未完成,添加完成后关闭新增内容区域
      • 取消 -- 直接关闭新增内容区域

      1.3.3 滑动操作

      点击到某一数据信息,向左进行滑动显示出来对应的操作按钮(删除或标记完成),使用position进行控制相关显示信息;

      设计原理:内容信息与按钮在同一行显示,使用z-index控制堆叠.按钮的z-index小于内容的z-index.

      • 未完成 -- 滑动后显示出删除按钮与标记完成按钮,此时的最大滑动宽度为删除按钮与标记按钮之和
      • 已完成 -- 滑动后显示出删除按钮,此时的最大滑动宽度为删除按钮的宽度.

      1.3.4 按钮操作

      • 删除 -- 列表中删除对应的数据行
      • 标记完成 -- 列表中对应行数据的状态由未完成更改为完成.

    1.4 代码结构

    2. 代码

      码云: https://gitee.com/ajuanK/wxSimpleTodoList.git

    2.1 页面设计(index.wxml)

    <!--index.wxml-->
    <wxs src="./../../wxs/subString.wxs" module="tools"/>
    <view class="container">
      <view class="userinfo">
        <view class="addDiv {{addShow?'':'hide'}}">
          <view class="addDivContent">
            <input bindinput='bindAddText' placeholder="请输入内容" focus="{{inputFocus}}" value="{{addText}}" class="addDivInput" />
            <view class="addDivButton">
              <button class="addDivButtonMargin" bindtap="addTodo" type="primary" size="mini">确定添加</button>
              <button bindtap="cancelTodo" type="default" size="mini">取消</button>
            </view>
          </view>
        </view>
        <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
        <block wx:else>
          <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
          <text class="userinfo-nickname">{{userInfo.nickName}}</text>
        </block>
        <view class="listDivTop">
          <view class="listDivType">
            <view class="{{(todoTabId=='tab1'?'listDivTypeSelected':'')}}" data-id="tab1" bindtap="onChangeSelect">全部</view>
            <view class="{{(todoTabId=='tab2'?'listDivTypeSelected':'')}}" data-id="tab2" bindtap="onChangeSelect">已完成</view>
            <view class="{{(todoTabId=='tab3'?'listDivTypeSelected':'')}}" data-id="tab3" bindtap="onChangeSelect">未完成</view>
          </view>
          <view>
            <button type="primary" size="mini" bindtap="addDivShow">添加</button>
          </view>
        </view>
        <view class="listDivContent">
          <view class="items">
            <view wx:for="{{todoDtBind}}" wx:key="{{index}}" class="listDivItem">
              <view bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" data-state="{{item.state}}" data-index="{{index}}" style="{{item.txtStyle}}" class="inner txt">
                <view class="listDivRow">
                  <view>{{index+1}}.{{tools.sub(item.content)}}</view>
                  <view class="itemTime">{{item.addTime}}</view>
                </view>
    
              </view>
              <view wx:if="{{item.state==2}}" data-index="{{index}}" bindtap="finishItem" class="inner finish">标记完成</view>
              <view data-index="{{index}}" bindtap="delItem" class="inner del">删除</view>
            </view>
          </view>
        </view>
      </view>
    </view>

    2.2 逻辑处理

    2.2.1 页面逻辑处理(index.js)

    //index.js
    //获取应用实例
    const app = getApp()
    
    Page({
      data: {
        addShow: false, //添加输入面板是否显示
        inputFocus: false,//是否选中
        addText: '',//新增内容
        todoTabId: 'tab1',//tab选中
        totalCount: 70,//总数据
        pageSize: 20,//显示行数
        pageNum: 1,//页码
        todoDtBind: [],//绑定的数据集合
        todoList: [],//数据集合(所有的)
        delBtnWidth: 60, //删除按钮宽度
        finishBtnWidth: 80, //删除按钮宽度
        startX: "", //触摸开始滑动的位置
        userInfo: {},
        hasUserInfo: false,
        canIUse: wx.canIUse('button.open-type.getUserInfo')
      },
      //事件处理函数
      bindViewTap: function() {
        wx.navigateTo({
          url: '../logs/logs'
        })
      },
      onShow: function() {
        this.setData({
          pageNum: 1
        })
        this.getBindDtInfo("正在加载中");
        this.setBindDtInfo(this.data.todoTabId);
      },
      /**
       * 获取绑定数据
       * @param msg:加载信息
       */
      getBindDtInfo: function(msg) {
        wx.showLoading({
          title: msg,
        })
        setTimeout(function() {
          wx.hideLoading()
        }, 2000)
        var vNum = this.data.pageNum;
        var count = vNum * this.data.pageSize;//页码乘以行数得到的理论条数
        var showCount = 0;//显示条数
        if (count <= this.data.totalCount) {
          showCount = count;
        } else {
          showCount = this.data.totalCount;
          vNum = vNum - 1;
        }
        let objItem = {};
        let dtInfo = [];//创造数据
        for (var i = 0; i < showCount; i++) {
          objItem = {
            id: i + 1,
            content: '计划工作项目' + (i + 1).toString(),
            addTime: this.getStrDate(Date.parse(new Date()) / 1000),
            state: (i < 6) ? 2 : 1,//前6行显示为未完成
            txtStyle: ''
          }
          dtInfo.push(objItem)
        }
        this.setData({
          todoList: dtInfo,
          pageNum: vNum
        });
      },
      /**
       * 页面上拉触底事件
       */
      onReachBottom: function() {
        if (this.data.todoList.length <= this.data.totalCount) {
          let vNum = this.data.pageNum + 1;
          this.setData({
            pageNum: vNum
          })
          this.getBindDtInfo("正在加载中");
          this.setBindDtInfo(this.data.todoTabId);
        } else {
          wx.showToast({
            title: '没有更多数据',
            icon: 'none',
            duration: 2000
          })
        }
      },
      /**
       * 通过时间戳获取时间表达式
       */
      getStrDate: function(vTime) {
        var res = /^d+$/;
        if (!res.test(vTime)) {
          return vTime;
        }
        var date = new Date(vTime * 1000);
        var Y = date.getFullYear(); //
        var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1); //
        var D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate(); //
        var h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours(); //
        var m = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes(); //
        var s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds(); //
        var strDate = Y + "/" + M + "/" + D + " " + h + ":" + m + ":" + s;
        return strDate;
      },
      /**
       * 添加按钮事件
       */
      addDivShow: function() {
        this.setData({
          addShow: true,
          inputFocus: true
        });
      },
      //输入内容绑定至数据
      bindAddText: function(e) {
        this.setData({
          addText: e.detail.value
        })
      },
      //确定新增按钮事件
      addTodo: function() {
        var content = this.data.addText;
        if (content.trim() == "") {
          wx.showToast({
            title: '添加的内容信息不能为空!',
            icon: 'none',
            duration: 2000
          })
          return;
        }
        var dtInfo = this.data.todoList;
        var objAdd = {
          id: dtInfo.length + 1,
          content: content,
          addTime: this.getStrDate(Date.parse(new Date()) / 1000),
          state: 2,
          txtStyle: ''
        }
        dtInfo.unshift(objAdd);
        var count = this.data.totalCount + 1;
        this.setData({
          todoList: dtInfo,
          totalCount: count,
          addShow: false,
          inputFocus: false,
          addText: ''
        });
        this.setBindDtInfo(this.data.todoTabId)
      },
      //取消按钮事件
      cancelTodo: function() {
        this.setData({
          addShow: false,
          inputFocus: false,
          addText: ''
        });
      },
      //设置绑定数据集合
      setBindDtInfo: function(vTabId) {
        var dtInfo = [];
        if (vTabId == "tab1") {
          dtInfo = this.data.todoList;
        } else if (vTabId == "tab2") {
          for (var i = 0; i < this.data.todoList.length; i++) {
            if (this.data.todoList[i].state == 1) {
              dtInfo.push(this.data.todoList[i]);
            }
          }
        } else {
          for (var i = 0; i < this.data.todoList.length; i++) {
            if (this.data.todoList[i].state == 2) {
              dtInfo.push(this.data.todoList[i]);
            }
          }
        }
        this.setData({
          todoDtBind: dtInfo,
          todoTabId: vTabId
        });
      },
      /**
       * 类型选中事件(全部,已完成,未完成)
       */
      onChangeSelect: function(e) {
        var dtInfo = this.data.todoList;
        dtInfo.forEach(function(item) {
          item.txtStyle = "";
        })
        var self = this;
        var id = e.currentTarget.dataset.id;
        this.setBindDtInfo(id);
      },
      // 滑动开始
      touchStart: function(e) {
        var dtInfo = this.data.todoDtBind;
        dtInfo.forEach(function(item) {
          item.txtStyle = "";
        })
        if (e.touches.length == 1) {
          this.setData({
            //设置触摸起始点水平方向位置
            startX: e.touches[0].clientX,
            todoDtBind: dtInfo
          });
        }
      },
      //滑动
      touchMove: function(e) {
        if (e.touches.length == 1) {
          //移动时水平方向位置
          var moveX = e.touches[0].clientX;
          var dValueX = this.data.startX - moveX; //差值:手指点击开始的X坐标位置减去移动的水平位置坐标
          var operBtnWidth = this.data.delBtnWidth;
          var state = e.currentTarget.dataset.state;
          if (state == 2) {
            operBtnWidth = this.data.delBtnWidth + this.data.finishBtnWidth;
          }
          var txtStyle = "";
          //没有移动或者向右滑动不进行处理
          if (dValueX == 0 || dValueX < 0) {
            txtStyle = "left:0px";
          } else {
            txtStyle = "left:-" + dValueX + "px";
          }
          if (dValueX >= operBtnWidth) {
            //文本移动的最大距离
            txtStyle = "left:-" + operBtnWidth + "px";
          }
          var index = e.currentTarget.dataset.index;
          var dtInfo = this.data.todoDtBind;
          dtInfo[index].txtStyle = txtStyle;
          this.setData({
            todoDtBind: dtInfo
          })
        }
      },
      //滑动结束
      touchEnd: function(e) {
        if (e.changedTouches.length == 1) {
          var endX = e.changedTouches[0].clientX;
          var dValueX = this.data.startX - endX;
          var operBtnWidth = this.data.delBtnWidth;
          var state = e.currentTarget.dataset.state;
          if (state == 2) {
            operBtnWidth = this.data.delBtnWidth + this.data.finishBtnWidth;
          }
          var txtStyle = ""
          if (dValueX > operBtnWidth / 2) {
            txtStyle = "left:-" + operBtnWidth + "px";
          } else {
            txtStyle = "left:0px"
          }
          var index = e.currentTarget.dataset.index;
          var dtInfo = this.data.todoDtBind;
          dtInfo[index].txtStyle = txtStyle;
          this.setData({
            todoDtBind: dtInfo
          })
        }
      },
      //标记完成
      finishItem: function(e) {
        var index = e.currentTarget.dataset.index;
        var dtInfo = this.data.todoDtBind;
        dtInfo[index].state = 1;
        dtInfo[index].txtStyle = "left:0px";
        this.setData({
          todoDtBind: dtInfo
        })
        this.setBindDtInfo(this.data.todoTabId);
        wx.showToast({
          title: '已完成成功',
          icon: 'success',
          duration: 2000
        })
      },
      //删除按钮事件
      delItem: function(e) {
        var index = e.currentTarget.dataset.index;
        var dtInfo = this.data.todoDtBind;
        var dtInfoList = this.data.todoList;
        var removeIndex = -1;
        for (var i = 0; i < dtInfoList.length; i++) {
          if (dtInfoList[i].id == dtInfo[index].id) {
            removeIndex = i;
          }
        }
        dtInfoList.splice(removeIndex, 1);
        var count = this.data.totalCount - 1;
        this.setData({
          todoList: dtInfoList,
          totalCount: count
        })
        this.setBindDtInfo(this.data.todoTabId);
        wx.showToast({
          title: '删除成功',
          icon: 'success',
          duration: 2000
        })
      },
      onLoad: function() {
    
        if (app.globalData.userInfo) {
          this.setData({
            userInfo: app.globalData.userInfo,
            hasUserInfo: true
          })
        } else if (this.data.canIUse) {
          // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
          // 所以此处加入 callback 以防止这种情况
          app.userInfoReadyCallback = res => {
            this.setData({
              userInfo: res.userInfo,
              hasUserInfo: true
            })
          }
        } else {
          // 在没有 open-type=getUserInfo 版本的兼容处理
          wx.getUserInfo({
            success: res => {
              app.globalData.userInfo = res.userInfo
              this.setData({
                userInfo: res.userInfo,
                hasUserInfo: true
              })
            }
          })
        }
      },
      getUserInfo: function(e) {
        console.log(e)
        app.globalData.userInfo = e.detail.userInfo
        this.setData({
          userInfo: e.detail.userInfo,
          hasUserInfo: true
        })
      }
    })

    2.2.2 小程序脚本语言(subString.wxs)

    var sub =function(val) {
      if (val == undefined || val.length == 0) {
        return;
      }
      if (val.length > 10) {
        return val.substring(0, 10) + "..."
      } else {
        return val;
      }
    }
    
    module.exports={
      sub:sub
    }

    2.3 样式设计(index.wxml)

    /**index.wxss**/
    
    .userinfo {
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      position: relative;
    }
    
    .userinfo-avatar {
      width: 128rpx;
      height: 128rpx;
      margin: 20rpx;
      border-radius: 50%;
    }
    
    .userinfo-nickname {
      color: #aaa;
    }
    
    .addDiv {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      background-color: #fff;
      z-index: 999;
    }
    
    .addDivContent {
      padding: 10px;
    }
    
    .addDivInput {
      border: solid 1px gainsboro;
      border-radius: 6px;
      height: 60px;
      margin-bottom: 10px;
    }
    
    .addDivButtonMargin {
      margin-right: 20px;
    }
    
    .hide {
      display: none;
    }
    
    .listDivTop {
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      padding-top: 10px;
      padding-bottom: 10px;
      width: 96%;
      border-bottom: 1px solid gainsboro;
    }
    
    .listDivType {
      display: flex;
      flex-direction: row;
      justify-content: space-around;
      width: 60%;
      color: #999;
    }
    
    .listDivTypeSelected {
      color: green;
      font-weight: 600;
    }
    
    .listDivContent {
      width: 100%;
      color: #666;
      margin: 0 auto;
      padding: 40rpx 0;
      position: absolute;
      top: 150px;
    }
    
    .items {
      width: 100%;
    }
    
    .listDivRow {
      width: 98%;
      display: flex;
      flex-direction: row;
      justify-content: space-between;
    }
    
    .listDivItem {
      position: relative;
      height: 80rpx;
      line-height: 80rpx;
      overflow: hidden;
    }
    
    .inner {
      position: absolute;
      top: 0;
    }
    
    .inner.txt {
      width: 100%;
      z-index: 5;
      transition: left 0.2s ease-in-out;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      background-color: lightcyan;
    }
    
    .itemTime {
      font-size: 12px;
    }
    
    .inner.del {
      width: 60px;
      text-align: center;
      z-index: 4;
      right: 0;
      background-color: red;
    }
    
    .inner.finish {
      width: 80px;
      text-align: center;
      z-index: 4;
      right: 60px;
      background-color: green;
    }

      

      

  • 相关阅读:
    Using AlloyTouch to control three.js 3D model
    AlloyTouch与three.js 3D模型交互
    移动Web触摸与运动解决方案AlloyTouch开源啦
    transformjs玩转星球
    swing with transformjs
    和transformjs一起摇摆
    getting started with transformjs
    移动Web利器transformjs入门
    腾讯AlloyTeam移动Web裁剪组件AlloyCrop正式开源
    Why AlloyFinger is so much smaller than hammerjs?
  • 原文地址:https://www.cnblogs.com/ajuan/p/10283266.html
Copyright © 2011-2022 走看看