vue学习笔记 十九、实例完整代码

  基础知识讲了不少,今天把之前所学的所有内容整合起来实现一个例子完善 vue学习笔记 九、父子组件实例-基本结构 中的功能,仔细看代码会有不小的收获。

一、 效果

 

 

父组件:Home 由三个子组件组成分别是:navHeader、navMain、navFooter

要完成的功能说明:

navHeader组件:输入新的任务,点击回车如果新的任务navMain中没有则添加到navMain中。

navMain组件:展示任务,点击“删除按钮”则删除当前任务,多选框可以多选任务。

navFooter组件:记录任务完成的数量(多选框选中为完成)、总数,以及点击“清除已完成”按钮删除navHeader中的已完成任务。

二、  项目结构截图

 

 

三、代码:

router--index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
 
//路由的配置属组
//paht:路由路劲 必须以/开头 必填
//component:对应的路由组件 必填
//name:路由的名字
const routes = [
  {
    path: '/',
    name: 'Home',
    //按需引入
    //如果没有访问/about 就不会加载这个组件 节约性能
    component: () => import( '../views/Home.vue')
  },
  {
    path: '/about',
    name: 'About',
    //按需引入
    //如果没有访问/about 就不会加载这个组件 节约性能
    component: () => import( '../views/About.vue')
  }
]
 
//创建路由对象
const router = createRouter({
    //createWebHashHistory hash模式路径前面会多一个#号
  history: createWebHistory(process.env.BASE_URL),
  routes
})
 
export default router

 

store--index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { createStore } from 'vuex'
 
export default createStore({
  //定义所需要的状态
  state: {
     list:[
         {
            title:'吃饭',
            complete:false
         },{
            title:'睡觉',
            complete:false
         },{
            title:'敲代码',
            complete:true
         },
     ]
  },
  //同步修改state 都是方法
  //第一个参数state,第二个参数是需要修改的值
  mutations: {
       //添加任务
       addTodo(state,payload){
           state.list.push(payload)
       },
       //删除任务 splice(下标,个数)
       delTodo(state,payload){
           state.list.splice(payload,1)
       },
       //清除已完成
       clear(state,payload){
           state.list = payload
       }
  },
  //异步提交mutations
  //第一个参数是store 第二个参数是修改的值
  actions: {
        
  },
  //模块化的
  modules: {
  }
})

 

Home.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<template>
    <div class="item">
        <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>
    //编写js内容
import NavHeader from '@/components/navHeader/NavHeader.vue'   
import NavMain   from '@/components/navMain/NavMain.vue'
import NavFooter from '@/components/navFooter/NavFooter.vue'
import {defineComponent,ref,computed} from 'vue'
import{useStore} from 'vuex'
  
 
 
export default defineComponent({
    name:'Home',
    components:{
        NavHeader,
        NavMain,
        NavFooter
    },
    setup(){
        let store = useStore()
        let list = computed(()=>{
            return store.state.list
        })
        let value = ref('')
        let add =(val)=>{
             value.value = val
             //设置flag 判断输入的信息是否已经存在
             let flag = true
             list.value.map(item =>{
                 if(item.title===value.value){
                     //有重复任务
                     flag = false;
                     alert('任务已经存在')
                 }
                  
             })
              
             if(flag){
             //调用mutation
                store.commit('addTodo',{
                    title:value.value,
                    complete:false
                })
             }
      
         }
         //删除任务
         let del =(val)=>{
            console.log(val)
            store.commit('delTodo',val)
         }
         let clear =(val)=>{
             store.commit('clear',val)
         }
         return {
             add,
             value,
             list,
             del,
             clear
         }
    }
  
          
})
     
     
</script>
 
<style scoped lang="scss">
    .item{
         text-align:left;
    }
</style>

 

NavHeader.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template>
     <div >
        <input
        placeholder="请输入任务名称"
        v-model="value"
        @keydown.enter="enter"
        />
     </div>
</template>
 
<script>
import {defineComponent,ref} from 'vue'
export default defineComponent({
    name:'navHeader',
    setup(props,ctx){
        let value=ref('')
        //按回车确认
        let enter = () => {
            ctx.emit('add',value.value)
            //console.log(value.value)
            //清空输入框
            value.value=''
        }
        return{
            value,
            enter
        }
    }
})
     
     
</script>
 
<style scoped lang="scss">
input{
    margin-bottom: 10px;
}
</style>

 

NavMain.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<template>
     <div v-for="(item,index) in list" :key ="index">
         <div class="item">
             <input type="checkbox" v-model="item.complete"/>
             {{item.title}}
             <button class="del" @click="del(item,index)">删除</button>
         </div>
     </div>
</template>
 
<script>
import {defineComponent,ref} from 'vue'
export default defineComponent({
    name:'navMain',
    props:{
        list:{
            type:Array,
            required:true
        }
    },
    //放分发事件的属性名字  没有这句浏览器控制台有报错 
    emits:['del'],
    setup(props,ctx){
        //删除任务
        let del =(item,index)=>{
            ctx.emit('del',index)
            console.log(item)
            console.log(index)
        }
         
        return{
            del
        }
         
    }
})
     
     
</script>
 
<style scoped lang="scss">
    .item{
        height: 35px;
        line-height: 35px;
        position: relative;
        width: 260px;
        cursor: pointer;
        button{
                position: absolute;
                right: 20px;
                top: 6px;
                display: none;
                z-index: 99;
        }
        &:hover{
            background: #ddd;
            button{
                display: block;
            }
        }
         
         
    }
     
</style>

 

NavFooter.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<template>
     <div  >
         <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({
    name:'navFooter',
    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)
            console.log('clear')
        }
         
        return{
            isComplete,
            clear
        }
    }
      
})
     
     
</script>
 
<style scoped lang="scss">
      
    .btn{
        margin-left: 10px;
    }
</style>

 

资源丰富的的网盘资源:网盘资源大全! 推荐一个适合零基础学习SQL的网站:不用安装数据库,在线轻松学习SQL!
posted @   万笑佛  阅读(482)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示