整体效果
父子组件传值
父组件
子组件
父子传值-子组件.png
父子传值--子组件.png
mutations 处理操作
Home.vue 接收来自 store 中的数据
代码展示
状态管理index.js
import { createStore } from 'vuex'
export default createStore({
state: {
list:[
{
title:'吃饭',
complete:false
},
{
title:'睡觉',
complete:true
},
{
title:'敲代码',
complete:false
},
]
},
mutations: {
addTodo(state, payload){
state.list.push(payload)
},
delTodo(state,payload){
state.list.splice(payload,1) // 删除任务 splice(下标,个数)
},
clear(state,payload){
state.list = payload
}
},
actions: {
},
modules: {
}
})
组件App.vue
该组件作为入口组件
<template>
<div>
<router-view/>
</div>
</template>
<style lang="scss" scoped>
*{
margin: 0;
padding: 0;
}
div{
width: 800px;
margin: 50px auto;
}
</style>
组件Home.vue
<template>
<div>
<nav-header @add="add"></nav-header>
<nav-main :list="list" @del="del"></nav-main>
<nav-footer :list="list" @clear="clear"></nav-footer>
</div>
</template>
<script>
import NavHeader from '@/components/navHeader/NavHeader';
import NavMain from '@/components/navMain/NavMain';
import NavFooter from '@/components/navFooter/NavFooter';
import { computed, ref } from 'vue';
import { useStore } from 'vuex';
export default {
components:{
NavHeader,
NavMain,
NavFooter
},
setup() {
let store = useStore()
let list = computed(()=>{
return store.state.list
})
let value = ref('')
let add = (val) =>{
value.value = val
let flag = true
list.value.map(item=>{
if(item.title == value.value){
flag =false
alert('任务已存在')
}
})
if(flag){
store.commit('addTodo',{ // 调用mutations
title:value.value,
complete:false
})
}
}
let del = (val) => {
store.commit('delTodo',val)
}
let clear = (val) => {
store.commit('clear',val)
}
return {
add,
value,
list,
del,
clear
}
}
}
</script>
组件NavHeader.vue
<template>
<div>
<input type="text"
placeholder="请输入任务名称" @keydown.enter = "enter" v-model="value">
</div>
</template>
<script>
import { defineComponent,ref } from 'vue'
export default defineComponent({
setup(props, ctx) {
let value = ref('')
let enter = () => {
ctx.emit('add',value.value)
console.log(value.value);
value.value = ''
}
return{
value,
enter
}
}
});
</script>
<style lang="scss" scoped>
input{
margin-bottom: 10px;
}
</style>
组件NavMain.vue
<template>
<div>
<div v-if="list.length>0">
<div v-for="(item,index) in list" :key="index">
<div class="item">
<input type="checkbox" name="" id="" v-model="item.complete">
{{item.title}}
<button class="del" @click="del(item, index)">删除</button>
</div>
</div>
</div>
<div v-else>
暂无任务
</div>
</div>
</template>
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
props:{
list:{
type:Array,
required:true
}
},
emits:['del'], // 放分发事件的属性名字 没有这句浏览器控制台有报错
setup(props,ctx){
let del = (item,index)=>{
ctx.emit('del',index)
}
return{
del
}
}
})
</script>
<style lang="scss">
.item{
height: 35px;
line-height: 35px;
position: relative;
width: 160px;
cursor: pointer;
button{
position: absolute;
right: 20px;
top: 6px;
display: none;
z-index: 99;
}
&:hover{
background-color: #ddd;
button{
display: block;
}
}
}
</style>
组件NavFooter.vue
<template>
<div class="container">
<div>
已完成{{isComplete}} / 全部{{list.length}}
</div>
<div v-if="isComplete > 0" class="btn">
<button @click="clear">清除已完成</button>
</div>
</div>
</template>
<script>
import { defineComponent, ref, computed } from 'vue'
export default defineComponent({
props:{
list:{
type:Array,
required:true
}
},
setup(props,ctx){
let isComplete = computed(()=>{
let arr = props.list.filter(item => {
return item.complete // 过滤已完成
})
return arr.length
})
let clear = () =>{
let arr = props.list.filter(item => {
return item.complete === false // 过滤未完成的
})
ctx.emit('clear',arr)
}
return {
isComplete,
clear
}
}
})
</script>
<style lang="scss" scoped>
.container{
display: flex;
align-items: center;
.btn{
margin-left: 10px;
}
}
</style>
网友评论