效果显示
todo-list.gif几个技能点
- 点击view切换可编辑状态的input,回车后,要回到文本模式
- 将bindtap改为catchtap,阻止与checkbox冲突
- 注意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
网友评论