16、父子组件通讯


1、组件数据关系

组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。如果在子组件中强行使用父组件的数据 ,就会报错,那么子组件如何才能获取父组件的数据呢?

2、组件之间的通讯

组件之间的通讯又叫做组件的传值,父子组件的通讯和非父子组件的通讯。
在这里插入图片描述
A与B、A与C :父子关系
B与D、C与E:父子关系
A与E、A与D:(祖孙)隔代关系
B与C:兄弟关系
D与E:堂兄弟关系(非直系亲属)
我们知道组件实例的作用域是孤立的,因此在子组件中是无法直接使用到父组件中的信息的。
举例:

 <div id="app">
        <my-son></my-son>
    </div>
    <template id="son">
        <div style="border:1px solid red">
           <h1>这是子组件,{{msg}}</h1>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        new Vue({
            el:"#app",
            data:{
                msg:"这是app中的msg"
            },
            components:{
                "mySon":{
                    template:"#son"
                }
            }
        })
    </script>

在这里插入图片描述
我们看到这里会报错,原因在于子组件的使用了父组件中的msg,因此会显示msg未定义。

3、父传子组件通讯

如何进行父子组件间的通信呢?Vue官方提到,①通过props向子组件传递数据,②通过事件向父组件发送消息。
在这里插入图片描述
在组件中,使用选项props来声明需要从父级接收到的数据。在父组件的子组件标签上绑定一个自定义属性,用于绑定要传递的值,在子组件中使用prop属性进行数据的接受,可以直接使用,绑定的属性名和prop定义的名字必须一致,否则无法接受数据。props中的数据,都是通过父组件传递给子组件的,props就是把父组件传递过来的属性,只有props定义,才能使用这个数据,props中的数据,只能读取,不能重新赋值。
props的值有两种方式:
方式一:字符串数组,数组中的字符串就是传递时的名称。
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。

举例:方式一:静态传值。

<div id="app">
          <!-- 静态使用子组件的属性 -->
          <my-son movies="唐人街探案3,你好,李焕英" des="电影"></my-son>
    </div>
    <template id="son">
        <div style="border: 1px solid red;"> 
            <h2>这是子组件</h2>
            <h3>类型:{{des}} 电影名称:{{movies}}</h3>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        let mySon = {
            template:"#son",
            //子组件定义props接收数据并使用
            //数组里存放的是自定义属性的名称
            props:['movies','des'] //数组写法
        }
        new Vue({ //父组件
            el:"#app",
            data:{
                msg:"这是app中的msg"
            },
            components:{ //注册的子组件
                mySon
            }
        })
    </script>

这里我们使用的是静态传值的方法,即在子组件中写上属性名为props中的属性,属性值则使我们静态传递的属性值。
举例:方式一:动态传值

<div id="app">
          <!-- 静态使用子组件的属性 -->
          <my-son movies="唐人街探案3,你好,李焕英" :des="msg"></my-son>
    </div>
    <template id="son">
        <div style="border: 1px solid red;"> 
            <h2>这是子组件</h2>
            <h3> 电影名称:{{movies}}</h3>
            <h4>{{des}}</h4>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        let mySon = {
            template:"#son",
            //子组件定义props接收数据并使用
            //数组里存放的是自定义属性的名称
            props:['movies','des'] //数组写法
        }
        new Vue({ //父组件
            el:"#app",
            data:{
                msg:"这是父组件中的msg"
            },
            components:{ //注册的子组件
                mySon
            }
        })
    </script>

其实动态传值的方式和静态传值的方式类似,我们可以看到这里是将父组件中的msg以属性值的方式传给子组件中的des。父组件在使用子组件的时候,可以将父组件的数据绑定到使用子组件的标签上,然后子组件再选项中添加一个props属性来接收数据。
举例:方式二:使用对象

<div id="app">
        <my-son :clist="list"></my-son>
        {{list}}
    </div>
    <template id="son">
        <div style="border: 1px solid red;"> 
            <h2>这是子组件</h2>
            <ul>
                <li>{{clist}}</li> 
            </ul>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        let mySon = {
            template:"#son",
            props:{//对象的写法
                clist:Array,//数组类型
            }
        }
        new Vue({ 
            el:"#app",
            data:{
                msg:"这是父组件中的msg",
                list:["苹果","香蕉","梨子","橘子"]
            },
            components:{ 
                mySon
            }
        })
    </script>

在这里插入图片描述
这里我们使用的clist:Array 的主要作用是限定clist的值的类型。
在上面的例子中,当我们将<my-son :clist="list"></my-son>中的clist的属性值修改为msg时,即:<my-son :clist="msg"></my-son>
在这里插入图片描述
我们可以看到这是会报错的,虽然也最终渲染出来了页面。
除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
那验证都支持那些类型呢?
String Number Boolean Array Object Date Function Symbol
在这里插入图片描述
我们也可以一个属性限制多个类型,如上面的例子中,我们可以将props修改成:

props:{//对象的写法
          clist:Array,//数组类型
          clist:String
       }

在这里插入图片描述
可以看到,这样修改后就不会再报错了。
推荐使用下面方法写props,注意不要使用引号。

 props:{//对象的写法
           clist:[String,Array]
        }

3.1、prop默认值设置

在prop中,我们可以使用默认值,以及一些必传值,例如:

<div id="app">
    <my-son :clist="msg"></my-son>
        {{list}}
    </div>
    <template id="son">
        <div style="border: 1px solid red;"> 
            <h2>这是子组件</h2>
            <ul>
                <li>{{clist}}</li> 
                <h3>{{cmsg}}</h3>
            </ul>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        let mySon = {
            template:"#son",
            props:{//对象的写法
                clist:[String,Array],
                cmsg:{
                    type:String,
                    default:"这是cmsg"
                }
            }
        }
        new Vue({ 
            el:"#app",
            data:{
                msg:"这是父组件中的msg",
                list:["苹果","香蕉","梨子","橘子"]
            },
            components:{ 
                mySon
            }
        })
    </script>

在这里插入图片描述
当我们将其修改为下面情况:<my-son :clist="list" :cmsg="msg"></my-son>
在这里插入图片描述
打印的是父组件中的msg,但是当我们父组件中没有传入msg的时候,它是会使用我们default中的值。
在这里插入图片描述

3.2、prop必传值设置

我们可以在prop中设置required来设置该数据是否为必传值,当required的属性值为true时,那么就为必传值,为false是就不是。
举例:prop中required的使用。

<div id="app">
        <my-son :mymsg="msg"></my-son>
    </div>
    <template id="son">
        <div style="border: 1px solid red;"> 
            <h2>这是子组件</h2>
            <h1>{{mymsg}}</h1>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        let mySon = {
            template:"#son",
            props:{//对象的写法
               mymsg:{
                   type:String,
               },
               eg:{
                   required:true,
               }
            }
        }
        new Vue({ 
            el:"#app",
            data:{
                msg:"我是父组件中的msg"
            },
            components:{ 
                mySon
            }
        })
    </script>

在这里插入图片描述
我们在上面例子中设置了eg的required的值为 true,但是在中,我们并没有使用到eg,因此会报错。

4、子传父组件通讯

子组件使用this.$emit()向父组件传值,首先必须在父组件中引用子组件,然后实现传值。
语法规则:

 $emit( eventName, […args] )

参数:
eventName:这是一个事件名,会绑定一个方法。当组件触发事件后,将调用这个方法。
…args:附加参数,会被抛出,由上述绑定的方法接收使用。

举例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div.son{
            width: 100px;
            height: 100px;
            background-color: red;
        }
    </style>
</head>
<body>
    <div id="app">
        <!-- 接收子组件通过$emit发射的事件 -->
        <h3>这里是子组件传过来的内容:{{des}}</h3>
        <son @biuapp="changes"></son>
    </div>
    <template id="son">
        <div>
            <div class="son"></div>
            <button @click=fn()>发射</button>
        </div>
    </template>
    <script src="./Vuejs/vue2-6-12.js"></script>
    <script>
        var son = {
            template:"#son",
            data(){
                return {
                    msg:'我是子组件中的msg',
                }
            },
            methods:{
                fn(){//把子组件的数据给父组件
                    //发送一个事件并携带参数
                    //$emit()第一个参数是事件名 第二个参数是携带的参数
                    this.$emit("biuapp",this.msg);
                    console.log("已经发射");
                }
            }
        }
        new Vue({
            el:"#app",
            data:{
                des:'',//定义一个空的des
            },
            components:{
                "son":son,
            },
            methods:{
                changes(value){
                    console.log(value);//我们这里的value接收的是$emit中的第二个参数
                    this.des = value;//将我们父组件中的des数据修改成$emit传递的数据,再在#app中调用我们的{{des}}
                }
            }
        })
    </script>
</body>
</html>

在这里插入图片描述
上面的例子中,我们使用了$emit()将我们子组件中的内容发送给我们的父组件,其中使用$emit()时我们是定义了一个事件名(biuapp),子组件传递的内容我们放在$emit()的第二个参数里,即this.msg,然后在父组件中,我们通过v-on来监听子组件事件(即使用@click=”biuapp”)。这样我们父组件就能接收到子组件传递过来的内容。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue 3.0 中,父子组件之间的通讯可以通过 props 和 emit 实现。 1. 父组件向子组件传递数据: 在父组件中使用子组件时,可以通过 props 将数据传递给子组件。具体实现如下: ```vue <template> <div> <child-component :message="parentMessage"></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue' export default { data() { return { parentMessage: 'Hello from parent' } }, components: { ChildComponent } } </script> ``` 在子组件中,可以通过 props 接收父组件传递过来的数据。具体实现如下: ```vue <template> <div> {{ message }} </div> </template> <script> export default { props: { message: String } } </script> ``` 2. 子组件向父组件传递数据: 在子组件中,可以使用 emit 触发一个自定义事件,并向父组件传递数据。具体实现如下: ```vue <template> <div> <button @click="sendMessage">Send Message</button> </div> </template> <script> export default { data() { return { message: 'Hello from child' } }, methods: { sendMessage() { this.$emit('message', this.message) } } } </script> ``` 在父组件中使用子组件时,可以通过 v-on 监听子组件触发的自定义事件,并在事件处理函数中获取子组件传递过来的数据。具体实现如下: ```vue <template> <div> <child-component @message="handleMessage"></child-component> <div>{{ receivedMessage }}</div> </div> </template> <script> import ChildComponent from './ChildComponent.vue' export default { data() { return { receivedMessage: '' } }, components: { ChildComponent }, methods: { handleMessage(message) { this.receivedMessage = message } } } </script> ``` 以上就是 Vue 3.0 中父子组件之间通讯的实现方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值