效果实现流程:
- 首先创建一个vue项目,Todo-list总共分三步来写,
- 头部我们使用input框来实现输入的数据,使用键盘事件点击添加到数据中,使用v-model实现响应式数据,
- 第二步来进行筛选,是完成还是未完成
- 我们添加的数据在这里拿到进行渲染,然后我们用css3的属性实现删除的显示和隐藏
?代码实现思路:
vuex代码实现思路:
我们在vuex中创建一个空对象,在定义一个初始值和初始状态,当我们的全部,然后在用map循环通过id来判断他的状态,是true还是false,实现单选和全选
代码实现:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state:{
listData:[],
status:'all',
totalselect:false
},
mutations: {
SET_LIST_DATA(state,data){
state.listData.push(data)
state.totalselect=false
localStorage.setItem('listData',JSON.stringify(state.listData))
localStorage.setItem('totalselect',JSON.stringify(state.totalselect))
},
GET_LIST(state,data){
const {listData,totalselect}=data
state.listData=listData
state.totalselect=totalselect
},
SET_SELECT(state,id){
state.listData.map(item=>{
if(item.id==id){
item.select=!item.select
}
})
const num=state.listData.filter(item=>item.select).length
if(num==state.listData.length){
state.totalselect=true
}else{
state.totalselect=false
}
localStorage.setItem('listData',JSON.stringify(state.listData))
localStorage.setItem('totalselect',JSON.stringify(state.totalselect))
},
SET_TOTAL_SELECT(state){
state.totalselect=!state.totalselect
if(state.totalselect==true){
state.listData.map(item=>{
item.select=true
})
}else{
state.listData.map(item=>{
item.select=false
})
}
localStorage.setItem('listData',JSON.stringify(state.listData))
localStorage.setItem('totalselect',JSON.stringify(state.totalselect))
},
DELETE(state,id){
const index=state.listData.findIndex(item=>item.id==id)
state.listData.splice(index,1)
localStorage.setItem('listData',JSON.stringify(state.listData))
},
SET_STATUS(state,status){
state.status=status
localStorage.setItem('status',JSON.stringify(state.status))
},
DELETE_FINISH(state){
state.listData=state.listData.filter(item=>!item.select)
localStorage.setItem('listData',JSON.stringify(state.listData))
}
},
actions: {
setListData({commit},data){
commit('SET_LIST_DATA',data)
},
getList({commit}){
const listData=JSON.parse(localStorage.getItem('listData'))||[]
const totalselect=JSON.parse(localStorage.getItem('totalselect'))||false
commit('GET_LIST',{
listData,
totalselect
})
},
setSelect({commit},id){
commit('SET_SELECT',id)
},
setTotalSelect({commit}){
commit('SET_TOTAL_SELECT')
},
Delete({commit},id){
commit('DELETE',id)
},
setStatus({commit},status){
commit('SET_STATUS',status)
}
},
modules: {
}
})
?效果页代码实现:
我们在效果页定义一个空数组,我们在input框使用v-model来是想双向绑定,在判断当我们触发键盘事件动态想当前页添加数据,然后在通过filter来筛选状态进行筛选
代码实现:
<template>
<div>
<h1>todolist</h1>
<div class="box">
<div class="header">
<div class="header-left" @click="totalSelect1">
<svg class="icon slt" :class="{'slt-act':totalselect}" aria-hidden="true">
<use xlink:href="#icon-down2"></use>
</svg>
</div>
<div class="header-right">
<input type="text" class="input" v-model="msg" placeholder="What need to be done?" @keyup.enter="add()">
</div>
</div>
<div>
<div class="list" v-for="item in show" :key="item.id">
<div class="selector" :class="{'back-act':item.select}" >
<input type="checkbox" @click="setSelect(item.id)">
</div>
<span :class="{'d':item.select}">{{item.title}}</span>
<span class="del" @click="Delete(item.id)"></span>
</div>
</div>
<div class="floot">
<span class="floot-left">{{listData.length}}item left</span>
<router-link to='/all' tag='span'>All</router-link>
<router-link to='/unfinish' tag='span'>active</router-link>
<router-link to='/finish' tag='span'>completed</router-link>
<span class="floot-right" @click="DELETE_FINISH">clear completed</span>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
import Btn from '@/components/btn-group'
import List from '@/components/list-group'
export default {
components:{
Btn,
List
},
data(){
return {
msg:''
}
},
methods:{
add(){
if(this.msg!=''&&this.msg.trim()!=''){
this.$store.dispatch('setListData',{
id:new Date().getTime(),
select:false,
title:this.msg
})
}else{
alert('内容不能为空')
}
this.msg=''
},
totalSelect1(){
this.$store.dispatch('setTotalSelect')
},
...mapMutations(['DELETE_FINISH'])
},
computed:{
...mapState(['listData','totalselect','status']),
show(){
switch(this.status){
case 'all':
return this.listData;
case 'unfinish':
return this.listData.filter(item=>!item.select)
default:
return this.listData.filter(item=>item.select)
}
}
},
created(){
this.$store.dispatch('getList')
},
watch:{
$route:{
handler(value){
if(value.params.id){
this.$store.dispatch('setStatus',value.params.id)
}
},
immediate:true
}
},
}
</script>
<style lang='scss' scoped>
.icon{
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
h1{
text-align: center;
}
.box{
width: 3.2rem;
border: 0.01rem solid red;
margin: 0 auto;
background: #fff;
}
.header{
width: 3.2rem;
height: .2rem;
position: relative;
border-bottom: .01rem solid black;
}
.header-left{
position: absolute;
top: 0;
left: .1rem;
z-index: 999;
.slt{
opacity: .1;
font-weight: 900;
z-index: 0;
}
.slt-act{
opacity: 1;
}
}
.header-right{
width: 100%;
height: .2rem;
position: absolute;
right: 0;
top: 0;
padding-left: 1rem;
}
.input{
width: 85%;
height: .2rem;
float: right;
font-size: .15rem;
border: 0;
outline: 0;
}
.list{
display: flex;
position: relative;
}
.d{
text-decoration: line-through;
}
.back-act{
background: red;
}
.selector {
width: .16rem;
height: .16rem;
border-radius: 50%;
border: .01rem solid #ccc;
input{
width: .16rem;
height: .16rem;
opacity: 0;
}
}
.del{
position: absolute;
top: 0;
right: .1rem;
display: none;
color: #cc9a9a;
}
.list .del:after{
content: 'x';
}
.list:hover .del{
display: block;
}
.floot{
display: flex;
justify-content: center;
font-size: .1rem;
position: relative;
}
.floot>span{
padding: 0 .05rem;
}
.floot-left{
position: absolute;
left: 0;
top: 0;
}
.floot-right{
position: absolute;
right: 0;
top: 0;
}
</style>
内容不太详细又不懂的地方请发私信给我我会一一解答
|