一.组件传值问题分为三大类
1.父子传值,主要用于传递参数
2.子父传值,主要用于触发子组件的点击事件,对父组件的元素产生更改现象
3.非父子组件传值(没有上下级关系),主要用于没有关系的两个组件之间的传值
二.父子传值
原理: 在父组件中使用子组件时,通过自定义属性来进行传值,在子组件中通过props属性来接收父组件传递的数据。(子用父的参数)
(1)首先在父组件中与components同级,创建参数data,注意data是一个函数,而不是一个对象了,因为每个组件都是独立的,互不影响的,所以需要data函数return出来一个新的对象供每个组件使用,返回来讲,就是需要return出来一个新的对象所以data才会是一个函数
(2)其次在父组件中的template的子组件件上绑定一个属性,该属性的属性名为自定义,属性值为data传递的参数名
(3)(父组件)代码:
<template>
<div>
<h1>中国新闻</h1>
<!-- 第三步:使用子组件,并且传递数据 -->
<my-news :newarr="news"></my-news>
<p>时间:{{stime|formatTime}}</p>
</div>
</template>
<script>
<!-- 第一步:引入子组件 -->
import myNews from './news'
export default {
<!-- 第二步:注册子组件 -->
components:{
myNews
},
data(){
return{
news:[...]
}
}
</script>
(4)在子组件的script中,接收父组件传递的数据
props:["在父组件中自定义的属性名"]
(5)注意:这就意味着子组件已经有了参数,参数的名字是”在父组件中自定义的属性名”,这个参数是父组件传递过来的
(6)代码(子组件)
<template>
<div>
<!-- 第二步:遍历父组件传递过来的数据 -->
<div class="item" v-for="(item,index) of newarr" :key="index">
<p >新闻标题:{{item.title}}</p>
<p>时间:{{item.time|formatTime}}</p>
</div>
</div>
</template>
<script>
export default {
// 第一步:接收父组件传递的数据
props:['newarr']
</script>
(7)拿到参数后就可以进行子组件的逻辑了
三.子父传值
(1)原理:自定义事件+$emit
在父组件中使用子组件时,通过自定义事件来传递函数,在子组件中通过$emit('父组件的自定义事件名',传递的参数)来进行触发
(2)首先在子组件中肯定会有个点击按钮(因为子父传值就是触发子组件中的事件操作父组件),在点击按钮上添加点击事件+传参(传参是为了判断点击的是哪个按钮,因为一般多个按钮都是循环遍历出来的)
(3)其次在子组件与props同级处,创建methods,点击事件在methods里面编写逻辑,注意:在methods里面的点击事件函数需要传递形参(该形参是在点击按钮时传递过来的实参 ) (4)在点击事件函数的里面,通过$emit来触发父组件的自定义事件
this.$emit('自定义事件名',参数);
(5)代码:(子组件)
<template>
<div>
<div class="item" v-for="(item,index) of newarr" :key="index">
<p >新闻标题:{{item.title}}</p>
<p>时间:{{item.time|formatTime}}</p>
<!-- 第一步:执行子组件的点击事件 -->
<button @click="newsDel(index)">删除</button>
</div>
</div>
</template>
<script>
export default {
// 接收父组件传递的数据
props:['newarr'],
methods:{
newsDel(i){
//第二步,通过$emit 触发父组件的自定义事件
this.$emit('delByNews',i);
}
}
}
(6)在父组件中template使用的子组件的标签上,@子定义的自定义事件名=“自定义一个在父组件中事件的名字”
(7)在父组件中的methods中写事件函数,注意;函数需要接收参数,该参数是子组件传递过来,就可以利用该参数来进行逻辑
(8)代码(父组件)
<template>
<div>
<h1>中国新闻</h1>
<!-- 第三步:使用子组件,并且传递数据和自定义事件 -->
<my-news :newarr="news" @delByNews="del"></my-news>
<p>时间:{{stime|formatTime}}</p>
</div>
</template>
<script>
<!-- 第一步:引入子组件 -->
import myNews from './news'
export default {
<!-- 第二步:注册子组件 -->
components:{
myNews
},
data(){
return{
news:[...]
}
},
methods:{
del(e){
this.news.splice(e,1)
}
}
</script>
四.非父子组件
1.原理:在main.js里定义一个容器,用来传递数据,在需要发送数据的组件中,通过这个容器来进行数据的发送,在需要接受的组件中,通过这个容器来监听和接收数据。
2.在src目录下的main.js中,设置容器,注意:必须在vue的实例前
Vue.prototype.“自定义一个容器名”= new Vue()
new Vue({
...
})
3.需要发送数据的组件
(1)点击事件按钮
(2)在methods中的点击函数将数据发送给接收端
this.”容器名”.$emit('自定义一个名字(该名字是发送端和接收端联系的关键,发送端和接收端这个名字需要一致才能关联上,好比同一个频道)',传递的数据)
(3)代码(需要发送数据的组件)
<template>
<div>
<p>第一个组件的数据:{{msg}}</p>
<button @click="send">发送数据</button>
</div>
</template>
<script>
export default {
data(){
return{
msg:'异性不存在,唯有代码是真爱'
}
},
methods:{
send(){
this.ev.$emit('child1Val',this.msg)
}
}
}
</script>
4.需要接收数据的组件, 在生命周期函数的mouted中通过$on监听数据
(1)在与data同级的位置上,创建生命周期函数的mouted,监听
this.”容器名”.$on('频道名',(形参(该形参的实参是发送端传递过来的数据))=>{ 代码逻辑 });
<template>
<div>
<h1>这是第二个组件</h1>
<p>{{str}}</p>
</div>
</template>
<script>
export default {
data(){
return{
str:''
}
},
mounted(){
this.ev.$on('child1Val',(e)=>{
this.str = e
});
}
}
</script>