美文网首页
微信小程序todo list

微信小程序todo list

作者: 黄秀杰 | 来源:发表于2020-01-16 20:24 被阅读0次

    效果显示

    todo-list.gif

    几个技能点

    1. 点击view切换可编辑状态的input,回车后,要回到文本模式
    2. 将bindtap改为catchtap,阻止与checkbox冲突
    3. 注意sort()函数的坑,是按字符ascii排序,而非数值大小,所以要传递sort()排序回调方法

    代码

    代码里有详情的注释,完整代码托管在git,https://gitee.com/laeser/demo-weapp
    )

    JS文件

    Page({
      data: {
        todos: [
          {
            title: '明天9点打电话给老张'
          },
          {
            title: '打电话给老王'
          },
          {
            title: '打电话'
          }
        ]
      },
      onLoad() {
        // 调用模拟数据代码,需要时打开下面的注释
        // this.mock()
      },
      // 模拟长列表数据源
      mock() {
        // 生成12行数据,看底部删除按钮是否正常
        const todos = []
        for (let index = 0; index < 12; index++) {
          todos.push({
            title: index
          })
        }
        // 保存数据源
        this.setData({
          todos: todos
        })
      },
      add(e) {
        // 获取文本框里的内容
        const title = e.detail.value
        // 如果文本为空,给出toast提示
        if (!title) {
          wx.showToast({
            title: '请输入内容'
          })
          return
        }
        // 获取原来数据源
        let todos = this.data.todos
        // 构建todo对象
        let todo = {
          title: title
        }
        // 向数组最后添加一个元素
        todos.push(todo)
        // 保存数据源
        this.setData({
          todos: todos,
          title: ''
        })
      },
      editing(e) {
        // 获取当时点击的是第n个元素
        const index = e.currentTarget.dataset.index
        // 设定currentIndex值,让当前的文本框高亮
        this.setData({
          currentIndex: index
        })
      },
      edit(e) {
        // 获取input组件上的取值
        const title = e.detail.value
        // 设定currentIndex值,改变它的聚会
        const index = e.currentTarget.dataset.index
        // 获取原来数据源
        let todos = this.data.todos
        // 修改当前元素的title值
        todos[index].title = title
        // 保存数据源
        this.setData({
          todos: todos,
          currentIndex: -1
        })
      },
      // 勾选事件
      checkboxChange(e) {
        // 取出当前复选框的值
        const values = e.detail.value
        // 保存数据源
        this.setData({
          checkIndices: values
        })
      },
      // 批量删除
      deleteAll() {
        const checkIndices = this.data.checkIndices
        // 判断是不是数组,并且元素个数大于1
        if (Array.isArray(checkIndices) && checkIndices.length > 0) {
          // 删除确认
          wx.showModal({
            title: '确定删除吗?',
            success: ({ confirm }) => {
              if (confirm) {
                // 从后往前遍历,不会造成index错乱
                let todos = this.data.todos
                for (let i = checkIndices.length - 1; i >= 0; i--) {}
                // 注意sort原生是按string的ascii排序,会造成1,11,2这样一系列数据排序不合预期
                checkIndices
                  .sort((a, b) => {
                    return a - b
                  })
                  .reverse()
                // 逆序后就可以逐一删除元素
                checkIndices.forEach(item => {
                  todos.splice(item, 1)
                })
                // 保存数据源,同时checkIndices将它复位
                this.setData({
                  todos: todos,
                  checkIndices: []
                })
                // 给出提示框
                wx.showToast({
                  title: '删除成功'
                })
              }
            }
          })
        } else {
          wx.showToast({
            title: '请先勾选'
          })
        }
      },
      // 失去焦点事件
      bindblur(e) {
        // 列表中的文本框失去焦点时,currentIndex复位,让它们全部回到未高亮的状态
        this.setData({
          currentIndex: -1
        })
      }
    })
    
    

    wxml文件

    <!-- 操作区域主体内容 -->
    <view class="main">
      <input type="text" name="title" value="{{title}}" class="add" placeholder="请输入记录内容" confirm-type="done" placeholder-class="input-placeholder" auto-focus bindconfirm="add" />
      <!-- 使用checkbox-group作为容器,方便勾选 -->
      <checkbox-group bindchange="checkboxChange">
        <!-- 遍历数据源 -->
        <label wx:for="{{todos}}" class="list" wx:key="">
          <!-- 复选按钮,取值就是index值,回传checkbox改变事件回调 -->
          <checkbox value="{{index}}" checked="{{item.checked}}" />
          <!-- 文本框,由于currentIndex的存在而具有高亮状态 -->
          <input name="editor" catchtap="editing" data-index="{{index}}" value="{{item.title}}" disabled="{{currentIndex !== index}}" focus="{{currentIndex === index}}" class="input-common {{currentIndex !== index ? 'input-disabled' : 'input-enabled'}}" bindconfirm="edit" bindblur="bindblur" />
        </label>
      </checkbox-group>
    </view>
    <!-- 删除按钮容器 -->
    <view class="delete-container">
      <button type="warn" class="delete-all" bindtap="deleteAll">删除</button>
    </view>
    

    wxss文件

    /* 主体区域的样式,设定内外边距 */
    .main {
      padding: 0 10px;
      margin-top: 10px;
      margin-bottom: 60px;
    }
    
    /* 文本框通用样式 */
    input {
      color: #666;
      border: 1px solid #999;
      border-radius: 4px;
      padding: 6px;
    }
    
    /* 文本框placeholder占位字符的样式 */
    input.input-placeholder {
      color: #999;
    }
    
    /* 页首添加用文本框背景色 */
    .add {
      background-color: white;
    }
    
    /* 文本内容的flex布局 */
    .list {
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      align-items: center;
      margin: 5px 0;
    }
    
    /* 不论高亮与否都需要具备的样式 */
    .input-common {
      color: #000;
      flex: 1;
    }
    
    /* 非高亮时的样式 */
    .input-disabled {
      border: 1px solid #F8F8F8
    }
    
    /* 高亮时的样式 */
     .input-enabled {
      background: white;
    }
    
    view.delete-container {
      z-index: 99;
      position: fixed;
      bottom: 0;
      left: 0;
      right: 0px;
      width: 100%;
      text-align: center;
      background-color: #F8F8F8;
    }
    
    button.delete-all {
      margin: 10px;
    }
    

    关注我

    欢迎关注订阅号【黄秀杰】

    mp

    相关文章

      网友评论

          本文标题:微信小程序todo list

          本文链接:https://www.haomeiwen.com/subject/sxojyctx.html