效果顯示
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