1、利用props实现父组件给子组件传递数据
在父组件中给子组件传递数据,然后再在子组件中用props接收,就可以实现父组件->子组件的数据传递
父组件:
<div>
<Student name='李四' sex='女' :age='18'/>
<!-- 这样可以提高代码的复用率,就算数据是不相同的,你可以动态的指定数据 -->
<Student name='张三' sex='男' :age='19'/>
</div>
</template>
<script>
//引入School组件
import Student from './components/Student.vue'
export default {
name:"App",
components:{
Student
},
}
</script>
子组件
<div class="school">
<h1>{{msg}}</h1>
<h2>{{Name}}</h2>
<h2>{{sex}}</h2>
<h2>{{myAge+1}}</h2>
<button @click='updataAge'>尝试修改收到的年龄</button>
</div>
</template>
<script>
export default {
name:"Student",
data() {
return {
msg:'欢迎!',
myAge:this.age
}
},
methods:{
updataAge(){
this.myAge++
}
},
// 在这里简单声明接收一下数据
props:['Name','age','sex']
// 在这里接收数据的同时限制了数据的类型
// props:{
// name:'String',
// age:'Number',
// sex:'String'
// }
//接收的同时对数据: 进行类型限制+默认值的指定+必要性的限制
// props:{
// name:{
// type:String,//name的类型
// required:true//name是必要的
// },
// age:{
// type:Number,
// default:99 //默认值
// },
// sex:{
// type:String,
// required:true
// }
// }
}
</script>
<style>
.school{
background-color: gray;
}
</style>
从上面可以看出,props有几种接受的形式,可以简单声明一下接收,也可以在接收数据的同时对类型进行限制,指定默认值,限制必要性
2、利用props实现子组件给父组件传递数据
在父组件中给子组件传递一个函数,函数的回调在父组件中;在子组件中定义一个事件,让他触发父组件中传递过来的函数,并且在触发的同时给函数传递数据,这样在父组件中就可以通过回调函数的到数据 父组件:
<div class="app">
<h1>{{msg}},学生姓名是:{{studentName}}</h1>
<!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
<School :getSchoolName='getSchoolName'/>
</div>
</template>
import School from './components/School.vue'
export default {
name:"App",
components:{
School
},
data(){
return{
msg:'你好啊!',
studentName:''
}
},
methods:{
getSchoolName(name){
console.log('App收到了学校名:',name)
//在这里通过回调可以的到学校名
}
},
子组件(School)组件:
<div class="school">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{adress}}</h2>
<button @click="sendSchoolName">把学校名给App</button>
</div>
</template>
<script>
export default {
name:"School",
props:['getSchoolName'],
data() {
return {
schoolName:'shangguigu ',
adress:'beijing'
}
},
methods:{
sendSchoolName(){
this.getSchoolName(this.schoolName)
}
}
}
</script>
<style>
.school{
background-color:skyblue;
padding: 5px;
margin-top: 30px;
}
</style>
3、通过绑定自定义事件来实现子组件给父组件传递数据
其实思路跟上面用props差不多,在父组件调用的子组件里绑定一个自定义事件,这个事件指向一个函数,函数的回调在父组件中。在子组件里定义一个事件,这个事件用来触发绑定在子组件上的自定义事件,并且在触发的同时传入数据,这样父组件中的回调就可以的到数据了。 父组件:
<div class="app">
<h1>{{msg}},学生姓名是:{{studentName}}</h1>
<!-- 通过绑定自定义事件实现(第一种:使用v-on或者@) -->
<Student v-on:hah='demo' @demo='m1'/>
<!-- 通过绑定自定义事件实现(第二种:使用ref实现) -->
<!-- <Student ref="student"/> -->
</div>
</template>
<script>
//引入School组件
import Student from './components/Student.vue'
import School from './components/School.vue'
export default {
name:"App",
components:{
Student,
School
},
data(){
return{
msg:'你好啊!',
studentName:''
}
},
methods:{
getSchoolName(name){
console.log('App收到了学校名:',name)
},
demo(name){
console.log('数据传输了',name)
this.studentName=name
},
},
// 这样写可以更加的灵活
//
// mounted(){
// setTimeout(()=>{
// this.$refs.student.$on('hah',this.demo)
// },3000)
// }
}
</script>
<style lang="css">
.app{
background-color: gray;
padding: 5px;
}
</style>
子组件(Student)组件:
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">把学生姓名给App</button>
<button @click="unbind">解绑hah事件</button>
</div>
</template>
<script>
export default {
name:"Student",
data() {
return {
name:'张三',
sex:'男'
}
},
methods:{
sendStudentName(){
// 触发Student组件实例身上的hah事件
this.$emit('hah',this.name)
},
unbind(){
this.$off('hah')//解绑一个自定义事间
}
}
}
</script>
<style>
.student{
background-color: orange;
padding: 5px;
}
</style>
上面自定义事件有两种写法,一种是在父组件中调用的子组件中直接用v-on或者@来定义自定义事件;第二种就是先用ref标记一下这个子组件,然后在后面通过on('自定义事件名,自定义事件的回调函数')来定义自定义事件。
4、利用全局事件总线实现组件间通信
需要创建一个事件总线,它的特点有以下几点
1、可以被所有的组件访问到:这一点可以通过将他定义在Vue原型来实现,(因为在Vue中内置了:
VueComponent.prototype.__proto__指向Vue.prototype,
这样vue的实例和vm实例都可以通过原型链来访问到Vue原型对象)
2、要有$on、$off、$emit等方法,这些Vm实例身上都有
为了实现从Student组件向School组件传递信息,可以通过¥on('xxx',callback)在School组件监听一个xxx事件,在Student组件里面通过¥emit('xxx',data)触发事件并传递参数,School组件中的回调callback接收参数。
main.js里面
el:'#app',
render:h=>h(app),
beforeCreate() {
Vue.prototype.$bus=this //安装全局事件总线
},
})
School组件:
<div class="school">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{adress}}</h2>
</div>
</template>
<script>
export default {
name:"School",
props:['getSchoolName'],
data() {
return {
schoolName:'shangguigu ',
adress:'beijing'
}
},
mounted(){
this.$bus.$on('hello',(name)=>{
console.log('success',name)
})
},
beforeDestroy(){
this.$bus.$off('hello')
}
}
</script>
<style>
.school{
background-color:skyblue;
padding: 5px;
margin-top: 30px;
}
</style>
Student组件:
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendToSchool">把数据传给school</button>
</div>
</template>
<script>
export default {
name:"Student",
data() {
return {
name:'张三',
sex:'男'
}
},
methods:{
sendToSchool(){
this.$bus.$emit('hello',this.name)
}
},
// mounted(){
// console.log('Student',this.x)
// }
}
</script>
<style>
.student{
background-color: orange;
padding: 5px;
}
</style>
5、消息订阅与发布
这是利用消息订阅发布的插件实现的,首先先导入一个插件 import pubsub from 'pubsub-js'
School组件:
<div class="school">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{adress}}</h2>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:"School",
props:['getSchoolName'],
data() {
return {
schoolName:'shangguigu ',
adress:'beijing'
}
},
mounted(){
pubsub.subscribe('hello',(msgName,data)=>{
this.pubId =console.log('有人发布了消息,hello的回调被执行了',msgName,data)
})
},
beforeDestroy(){
pubsub.unsubscribe(this.pubId)
}
}
</script>
<style>
.school{
background-color:skyblue;
padding: 5px;
margin-top: 30px;
}
</style>
在Student组件里面订阅消息(类似于订报纸,订的是hello这个报纸,后面的回调函数用来接收数据), 这里回调函数会犯一个值(标识符),将来用来unsubscribe(取消订阅)。
Student组件:
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendToSchool">把数据传给school</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name:"Student",
data() {
return {
name:'张三',
sex:'男'
}
},
methods:{
sendToSchool(){
pubsub.publish('hello',666)
}
},
}
</script>
<style>
.student{
background-color: orange;
padding: 5px;
}
</style>
在Student组件中用来发布消息,publish('消息名称',数据),消息名称对应于上面提到的‘报纸名称’,只用名称对应了(确定报纸是你订的才会接收)才会接收。