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 组件创建时触发
真正的应用都是综合的综合