vue3+vant4+vuex4实现todolist备忘录案例
案例用的是vant-ui库,你可换成你自己用的ui库即可。
功能需求分析:
- 添加事项
- 删除事项
- 已完成删除
- 筛选:已完成、未完成
- 统计:剩余事项个数
安装vuex依赖包
npm install vuex --save
案例图片如下:
1 <van-cell-group> 2 <van-cell> 3 <van-row> 4 <van-col span="20"> 5 <van-field 6 :value="content" 7 @change="handleChange" 8 placeholder="请输入内容" 9 /> 10 </van-col> 11 <van-col span="4"> 12 <van-button type="primary" @click="onClickAdd" size="small" 13 >添加</van-button 14 > 15 </van-col> 16 </van-row> 17 </van-cell> 18 <van-cell v-for="(item, index) in listItem" :key="index"> 19 <van-row class="bg flex"> 20 <van-col span="2"> 21 <van-checkbox 22 v-model="item.checked" 23 shape="square" 24 @change="onChange(item, index, $event)" 25 > 26 </van-checkbox> 27 </van-col> 28 <van-col span="16"> 29 <div v-if="!item.checked" class="name">{{ item.name }}</div> 30 <van-field v-else v-model="item.name" placeholder="请输入内容" /> 31 </van-col> 32 <van-col span="4"> 33 <span @click="onClickDelete(item, index)" class="fontColor" 34 >删除</span 35 > 36 </van-col> 37 </van-row> 38 </van-cell> 39 <van-empty 40 v-if="listItem.length == 0" 41 image="https://fastly.jsdelivr.net/npm/@vant/assets/custom-empty-image.png" 42 image-size="40" 43 description="暂无数据" 44 /> 45 46 <div class="footer flex" v-if="items.length != 0"> 47 <span>剩余{{ notFinsh }}项</span> 48 <van-tabs 49 v-model:active="active" 50 @click-tab="onClickTab" 51 shrink 52 type="card" 53 size="small" 54 > 55 <van-tab title="全部"></van-tab> 56 <van-tab title="未完成"></van-tab> 57 <van-tab title="已完成"></van-tab> 58 </van-tabs> 59 <span type="primary" @click="onClickClear" class="fontColor" 60 >删除已完成</span 61 > 62 </div> 63 </van-cell-group>
js和css代码如下:
1 <script> 2 import { useStore, mapState, mapGetters } from 'vuex' 3 import { showToast } from 'vant' 4 import { showConfirmDialog } from 'vant' 5 import { ref, computed } from 'vue' 6 export default { 7 setup() { 8 const store = useStore() 9 const active = ref('1') 10 const content = computed(() => store.state.content) 11 const items = computed(() => store.state.items) 12 function onClickAdd() { 13 if (content.value == '') { 14 showToast('输入内容不能为空') 15 } else { 16 store.commit('addItem') 17 } 18 } 19 function handleChange(e) { 20 store.commit('setInputValue', e.target.value) 21 } 22 function onClickDelete(item, i) { 23 showConfirmDialog({ 24 title: '提示', 25 message: '您确定要' + item.name + '删除吗?', 26 }) 27 .then(() => { 28 store.commit('deleteItem', i) 29 }) 30 .catch(() => {}) 31 } 32 function onChange(item, index, e) { 33 item.checked != item.checked 34 } 35 function onClickClear() { 36 store.commit('clearItem') 37 } 38 function onClickTab(val) { 39 store.commit('changeItem', val.name) 40 } 41 return { 42 active, 43 onClickAdd, 44 onClickTab, 45 onClickClear, 46 onChange, 47 onClickDelete, 48 handleChange, 49 content, 50 items, 51 } 52 }, 53 computed: { 54 ...mapGetters(['notFinsh', 'listItem']), 55 }, 56 } 57 </script> 58 <style scoped> 59 .bg { 60 background: #fff; 61 width: 100%; 62 } 63 .fontColor { 64 color: #3071f1; 65 font-size: 12px; 66 } 67 .flex { 68 display: flex; 69 justify-content: space-between; 70 align-items: center; 71 } 72 .name { 73 text-align: left; 74 padding: 14px; 75 } 76 .bg >>> .van-field__control:focus { 77 outline: none; 78 border-color: #409eff; 79 } 80 .footer { 81 padding: 20px; 82 } 83 </style>
main.js引用vuex,并挂载到vue
import store from './store';
app.use(router).use(store);
sotore.js代码如下:
1 import { createStore } from 'vuex' 2 3 export default createStore({ 4 state:{ 5 content:'', 6 active:"", 7 items:[{ 8 "name": "1111", 9 "id": "1", 10 "checked": false 11 },{ 12 "name": "222", 13 "id": "2", 14 "checked": true 15 },{ 16 "name": "333", 17 "id": "3", 18 "checked": false 19 }], 20 id:0, 21 }, 22 mutations:{ 23 onChangeChecked(state,index,val){ 24 state.items[index].name = val 25 }, 26 todoUpdata(state,index,val){ 27 state.items[index].name = val 28 }, 29 setInputValue(state,val){ 30 state.content = val 31 }, 32 addItem(state){ 33 var obj = { 34 "name": state.content, 35 "id": state.id, 36 "checked": false 37 } 38 console.log("obj",obj) 39 state.items.unshift(obj) 40 state.id ++ 41 state.content = "" 42 }, 43 deleteItem(state,i){ 44 state.items.splice(i,1) 45 }, 46 clearItem(state){ 47 state.items = state.items.filter(x=>x.checked===false) 48 }, 49 changeItem(state,val){ 50 state.active = val 51 } 52 }, 53 actions:{ 54 55 }, 56 getters:{ 57 notFinsh(state){ 58 return state.items.filter(x=>x.checked===false).length 59 }, 60 listItem(state){ 61 //0全部 1未完成 2已完成 62 if(state.active==0){ 63 return state.items 64 } 65 if(state.active==1){ 66 return state.items.filter(x=>!x.checked) 67 } 68 if(state.active==2){ 69 return state.items.filter(x=>x.checked) 70 } 71 return state.items 72 } 73 } 74 })
QQ群:659182980 微信群 :扫一扫即可添加入群
欢迎扫码加群,一起讨论,共同学习成长!