黑马高大神 vue框架 第四天

本文详细介绍了如何使用Vue.js的事件总线(EventBus)进行非父子组件间的通信,并通过一个完整的TodoMVC案例,演示了如何创建、删除和切换任务状态,以及显示剩余任务数量。内容涵盖了事件触发、监听、组件传值等核心概念。
摘要由CSDN通过智能技术生成

day4

1.事件总线eventBus    兄弟组件的传值
事件总线  在一个实例上监听  在一个实例触发
打电话: 触发事件
接电话:接受事件
new Vue() vue实例
this.$emit --表示在当前的实例触发
this.$on--表示在当前实例上监听 

1.新建一个公共的实例

在src目录下新建 EVentBus目录 新建index.js
export default new Vue();//公共实例 谁都可以使用
2. A组件可以使用这个公共实例触发事件  
    B组件使用这个实例去监听事件

新建两个组件a,b
在app.vue导入这两个组件
import ChildA from './components/child-a.vue'
import ChildB from './components/child-b.vue'

在template里使用 
    <child-a></child-a>
    <child-b></child-b>
在componetns:{
    ChildA,
    ChildB,

在事件总线EventBus index.js文件写
import  Vue from 'vue'
export default new Vue()//导出一个公共的实例
 
在a组件写:
button @click='transValue' 给兄弟传值
导入事件总线js文件
import eventBus from '../EventBus/index.js'//如果目录下的文件是Index 可以省略index
data(){
    name:"aijing"
}
transValue(){
导入的事件总线文件  自定义事件名称  传a组件的数据
    eventBus.$emit('updateName',this.name) //使用事件触发总线
}

在b组件中
导入事件总线js文件
import eventBus from '../EventBus/index.js'//如果目录下的文件是Index 可以省略index

data(){
    return:{
    name:""
}
}
//这里要保证提前监听 保证监听你的内容
//实例创建之后执行
created(){
    eventBus.$on('updateName',(name)=>{
    this.name=name;//将a组件传递的自定义事件和数据传递给b定义的name
}
}


2. ToDoMvc
创建一个下面 todomvc
在黑马的react教程里面找样式 我懒得找

将头TodoHeader.vue 主体TodoMain.vue和脚TodoFooter.vue封装好代码
在app.vue里面导入三个组件

在app.vue定义list列表数组
list:[

id是任务的id值  name是任务名称  doone 是完成状态
        {id:1,name:'吃饭',done:true},
        {id:2,name:'吃饭',done:false},
        {id:3,name:'吃饭',done:false}
]
给主体<todo-main :list='list'>绑定传值
想要给谁传值  就在谁身上 通过v-bind绑定  :list='list'数组
在todoMain组件接受数据 props:['list']
在子组件TodoMain里面渲染数据
绑定样式  :class="{通过大括号绑定v-bind}"  true是做完 fasle是未做完 
li v-for='item in list' :key='item.id' :class="{completed:item.done}"


2.新增任务   
获取input的值  使用v-model
绑定子组件的回车事件 将name通过自定义事件传递给父组件的list数组中 成为待办任务  传递name完成之后 清空值
在父组件监听传递过来的参数 并且添加到list任务数组中


在头部组件  获取input的值  绑定name去除空格  回车输出方法
input v-model.trim='name' @keyup.enter='enterName'    触发事件

data(){
return{
    name:""  //待办任务名称
}
methods:{
    enterName(){
    触发事件  调用父组件的方法 这里的逻辑中断是为了要name有值 不然传一个空的就不好了
    this.name && this.$emit('addTodo',this.name)
}} 
在父组件 接受子组件的传参 和方法   
<todoHeader @addTodo='addTodo'></todoHeader>  监听事件
methods:{
addTodo(name){
    将name添加到list数组中  list数组的项都是要执行的任务
待办任务
this.list.push({name,done:false,id:~~(Math.random*100)});
}}
子组件的传参方法
enterName(){
    触发事件  调用父组件的方法 这里的逻辑中断是为了要name有值 不然传一个空的就不好了  
前面两个执行完毕 才执行清空this.name的任务名称
this.name && this.$emit('addTodo',this.name) &&(this.name=' ');
}} 

3.删除任务
找到到子组件的删除按钮  注册删除按钮的点击事件 并且传入一个要删除的id 任务项
触发自定义事件  传出要删除的任务项的id
父组件监听 并且过滤掉  就是实现删除功能

在TodoMain组件的有一个删除按钮  触发点击事件 并且 将这个任务项的id传递
button class='destroy' @click='delTodo(item.id)'

props:['list'] 这里的list列表是接收app.vue的list数组
在子组件里面删除父组件的任务
methods:{
    delTodo(id){
在父组件中删除list
id是判断id是否存在的简写  自定义事件在父组件中删除 定义一个自定义删除的方法名称  传递删除的id项

id && this.$emit('delTodo',id);//触发事件

}}

在app父组件
监听谁  在谁的身上接收
<todo-main :list='list' @delTodo='delTodo'></todo-main>
这里的id是接受子组件传递的id
delTodo(id){

这里的过滤就是 吧找到的任务项id过滤掉   返回一个删除掉点击事件的任务项的一个新数组

this.list=this.list.filter(item=>item.id!==id);//数据驱动视图
filter() 过滤方法 返回的是一个新数组
}

4.todomvc的切换状态  展示剩余任务条数
定义计算属性
将计算属性传递给todoFooter组件 接受 并且显示

剩余任务条数是判断list中done的ture和false变化   false是还剩多少条数据
在app中定义计算属性
computed:{
计算剩下没有完成任务的条数
    lastLength(){
返回  list数组过滤掉  item值是flase的  这里返回数字长度
return  this.list.filter((item)=>!item.done).length
}}

将剩余任务条数的计算属性 传递给子组件 并且显示
<todo-footer :lastLength='lastLength'></todo-footer>

再到todoFooter组件中接受传递过来的 剩余任务条数的计算属性值  返回一个长度
props:['lastLength']  {{lastLength}}

5.切换任务状态  all所有条数  active激活的 待办的 completed已经完成的
在app中定义三种状态
status:'all',//先定义初始的展示所有任务 
传值   将父组件定义的状态传递给子组件
<todo-footer :lastLength='lastLength' :status='status'></todo-footer>

子组件:接受传递过来的状态
props:['lastLength','status']
三个状态  点哪个就自定义事件传递哪一个值  prevent阻止默认事件 
a     @click.prevent='$emit("updateStatus",'all')' :class='{selected:status==="all"}'

a     @click.prevent='$emit("updateStatus",'active')' :class='{selected:status==="active"}'

a     @click.prevent='$emit("updateStatus",'completed')' :class='{selected:status==="completed "}'
这三个自定义事件 在app.vue中接收
<todo-footer @updateStatus='updateStatus' :lastLength='lastLength' :status='status'></todo-footer>
在app定义接收方法事件
updateStatus(status){
    this.status=status//将子组件点击的状态给父组件的状态  这里得到了点击的状态  在main组件中开始显示
}
computed:{
//    list-3条记录  all -3 active -2 completed 1 ->status
要展示的list
showList(){
    第一个 status  ===all  所有的 那就是当前的列表 因为的默认就是v-for遍历list所有数据
if(this.status==='all') return this.list
    第二个  激活情况下  过滤掉 list所有的项 不等于其值的取反  原本是ture  !false  如果原本是false  !ture
if(this.status==='active') 
return this.list.filter((item)=>!item.done);
    第三个 已完成  就是 值等于true的情况下 就代表它已经完成了  
if(this.status==='completed') 
return this.list.filter((item)=>item.done);

return [];//3个if没有一个else 所有要写一个三个都不执行的情况下  就返回一个空数组
}}
最后一步:将showList计算属性  给main主体来显示其list数据

因为原本是:list='list' 是显示所有的list数据  showList方法判断了三种情况   根据if返回的情况来确定传递的条数   再传递给子组件  并且子组件可以直接显示在页面上面
<todo-main :list='showList'


切换状态  筛选数据
1.用一个状态status管理状态   吧status传递给todofooter
在子组件点击可以  传递其all active completed 给父组件
父组件中定义计算属性  根据其传递过来的状态在main主体中根据状态来筛选数据
将筛选出来的数据 传递给子组件main来显示

day4总结 
1.一个vue组件 独立个体   数据独立  data返回一个新对象
scoped 为给所有的标签加一个唯一的hash值  样式只对当前的组件生效  有一个[]属性选择器唯一的


2.组件独立  组件的通讯:父传子 子传父 兄弟组件通过eventBus
3.父传子  确定父子关系 被引入的组件是子组件
父:
<template>
div
要给谁传  找到组件名  v-bind绑定样式
    Child :name='name'
/div
</template>
script
import Child from ''
export default{
name:"parent"
data(){
return{
        name:"aijing"
}
},
component:{
    Child
},
computed:{
    firstName(){
    return this.name.substr(0,3)
        }
    }
}
子:
<template>
div

        {{name}}

/div
</template>
script
export default{
name:"parent",
接受父组件传递的值 通过props接受
//props:['name']
props:{
    name:{
                type:String,//对name的要求  传递的类型是
                required:true, //必须传这个属性
                default:'aijing'//在没有传name属性时生效
        }
}
data(){
return{
    
}
}
}
要有父子关系  要有子组件的标签  给谁传就在是谁的标签上写属性 子组件接受属性 props
2.子组件  -父组件传值  三种用法
官方 自定义事件   
1.子组件触发事件
button @click='upadteName'
updateName(){
        触发自定义事件  参数
        this.$emit('updateName','aijing')
        因为是单向数据流   只读readOnly
}
在父组件接受子组件传递的数据
给子组件标签 定义 子组件传递过来的自定义事件  给自己组件定义一个方法来接收
Child :name='name' @updateName='updateName'

这个name是接受自定义事件的aijing参数
updateName(name){
    this.name=name
}
子传父 :子组件要触发事件   父组件通过传递的事件名和参数 来监听事件
$emit(‘事件名称’,参数)
v-on:自定义事件名称 ='方法'

3.非关系组件传值
eventBus 事件总线  将触发事件和监听事件都放在了一个实例上
新建事件总线的实例
import Vue from 'vue'
export default new Vue()//事件总线

触发事件:
import eventBus from ''
methods:{
传参
    eventBus.$emit('abc',123)
}
监听事件:越早越好 在组件实例化的时候就开始监听
export default{
    created(){
    eventBus.on('abc',(value)=>{
    //value就是123  接受参数
        }
    }
}


4.
todoMvc案例
components 注册组件
filters 过滤器
computed 计算属性
watch 侦听器 newValue oldValue
methods 方法
created 组件创建时触发

真正的应用都是综合的综合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fameless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值