查看原文
其他

用大头儿子和小头爸爸举例,就讲明白 vue 中父子组件的传值? | 原力计划

程序人生 2020-12-18

The following article is from 程序猿编程 Author 扬帆向海

作者 | 扬帆向海
责编 | 王晓曼
出品 | CSDN 博客
女朋友:“扬帆,你给我上一次讲了 vue 中的组件,我现在自己学习父子组件的传值,可是官方文档看不懂啊!你能不能通过父子组件传值的知识实现大头儿子和小头爸爸互相通信呢?”
我:“可以呀!我先分别给你讲父组件向子组件传值和子组件向父组件传值,最后在给你写个案例,实现父子组件的相互通信。”
点击【说话】按钮,大头儿子给小头爸爸传递消息。
小头爸爸收到消息,点击【回复】按钮,给大头儿子发送消息。

父组件向子组件传值

1. 传值步骤
① 子组件在props中创建一个属性,用以接收父组件传过来的数据;
② 父组件中注册子组件。通过属性绑定(v-bind:)的形式,把需要传递给子组件的数据传递到子组件的内部,供子组件使用;
③ 在子组件标签中添加子组件props中创建的属性;
④ 把需要传给子组件的值赋给该属性。
2. 代码示例
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>父组件向子组件传值</title>
    <script src="js/vue.js"></script>
</head>

<body>
    <div id="app">
        <!-- 父组件中注册子组件 -->
        <!-- 在子组件标签中添加子组件props中创建的属性, 把需要传给子组件的值赋给该属性 -->
        <mycom :parent-msg='pmsg' :content='hello'></mycom>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                pmsg: '父组件中的内容',
                hello: '我是父组件传过来的'
            },
            components: {
                mycom: {
                    data: function () {
                        return {
                            msg: '我是子组件本身的数据'
                        }
                    },
                    // 子组件在props中创建一个属性,用以接收父组件传过来的值
                    props: ['parentMsg', 'content'],
                    template: '<h3>{{msg + "---" + parentMsg + "----" + content}}</h3>'
                }
            }
        });
    </script>
</body>

</html>
【效果如下】
3. 注意事项
① prop 是子组件用来接受父组件传递过来的数据的一个自定义属性;
②父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 “prop”;
③prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来;
④ props中的数据都是只读的,无法进行重新赋值。
 
子组件向父组件传值

1. 传值步骤
① 子组件需要以某种方式例如点击事件的方法来触发一个自定义事件;
② 将需要传递的值作为$emit的第二个参数,该值将作为实参传递给响应自定义事件的方法;
③ 在父组件中注册子组件,在子组件标签上监听该自定义事件,并添加一个响应该事件的处理方法。
2. 代码示例
点击子组件中的按钮,给父组件发送子组件的信息:
<body>
    <div id="app">
        <h3>父组件</h3>
        <child @receive="handleEvent"></child>
    </div>
    <script>
        Vue.component('child', {
            template: `
                <div>
                    <h3>子组件</h3>
                    <button @click="sendMessage()">发送</button>
                </div>
            `,
            data() {
                return {
                }
            },
            methods: {
                sendMessage() { // 按钮的点击事件
                    this.$emit("receive","父组件您好,我是子组件!") // 调用父组件传递过来的方法,并且把数据传递出去
                }
            }
        })
        var vm = new Vue({
            el: '#app',
            methods: {
                // 定义在子组件中通过 this.$emit() 调用的方法
                handleEvent(val) {
                    console.log("父组件收到的消息是:",val)
                }
            }
        })
    </script>
</body>
【效果如下】
3. 注意事项
① 父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
② 我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
使用 $on(eventName) 监听事件;
使用 $emit(eventName) 触发事件。
③ 父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
 
大头儿子小头爸爸案例
 
这个案例实现了文章开头:大头儿子和小头爸爸之间的通信。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>父子组件通信</title>
    <script src="js/vue.js"></script>
    <style>
        .father,
        .son {
            width: 150px;
            height: 100px;
        }

        .info {
            color: #446ee4;
            font-size: 20px;
            font-size: bold;
        }

        .desc {
            font-size: 18px;
        }

        .btn {
            width: 100px;
            float: left;
            height: 40px;
            font-size: 18px;
            color: #fff;
            font-weight: bold;
            background: #446ee4;
            margin-top: 15px;
        }

        .parent,
        .child {
            display: inline-block;
            width: 550px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="parent">
            <img class="father" src="images/father.jpg">
            <div class="info">我是小头爸爸</div>
            <div v-if="msg !== ''" class="desc">小头爸爸接收到的消息:【{{msg}}】</div>
            <div v-if="replyMsg !== ''" class="desc">小头爸爸回复说:【{{replyMsg}}】</div>
            <button class="btn" @click="reply()">回复</button></button>
        </div>
        <div class="child">
            <child :reply-msg="replyMsg" @listen="listenHandle($event)"></child>
        </div>
    </div>
    <script>
        Vue.component('child', {
            props: {
                replyMsg: {
                    type: String,
                    default: ''
                }
            },
            template: `
                <div>
                    <img class="son" src="images/son.jpg">
                    <div class="info">我是大头儿子</div>
                    <div v-if="msg !== ''" class="desc">大头儿子说:【{{msg}}】</div>
                    <div v-if="replyMsg !== ''" class="desc">大头儿子接收到的消息:【{{replyMsg}}】</div>
                    <button class="btn" @click="say()">说话</button>
                </div>
            `,
            data() {
                return {
                    msg: ''
                }
            },
            methods: {
                say() {
                    this.msg = '小头爸爸好!'
                    this.$emit("listen", this.msg)
                }
            }
        })
        var vm = new Vue({
            el: '#app',
            data() {
                return {
                    msg: '',
                    replyMsg: ''
                }
            },
            methods: {
                listenHandle(val) {
                    this.msg = val
                },
                reply() {
                    this.replyMsg = '小头儿子好,消息已收到'
                }
            },

        })
    </script>
</body>

</html>
【效果如下】

总结

在组件传值过程中,无论是父传子、还是子传父,它们都有一个共同点就是有一个中间介质。父传子的介质是props中的属性,子传父的介质是自定义事件。
父子组件的关系可以总结为prop向下传递,事件向上传递。父组件通过prop给子组件下发数据,子组件通过事件给父组件发送信息。
父组件通过 v-bind:绑定参数传给子组件,子组件通过props接受这个参数。
在组件的最底层开始写事件,由最底层组件逐步向上$emit事件流,并携带相应参数,最后在父组件内完成总的数据处理。
版权声明:本文为CSDN博主「扬帆向海」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43570367/article/details/105854306

更多精彩推荐

中国最优秀的程序员都有哪些?王兴、张小龙、张一鸣是哪类?| 蒋涛说

前字节跳动程序员 28 岁提前退休引热议,网友:我也想!

听说你还没收到端午福利?程序人生来宠你!

秋名山老司机从上车到翻车的悲痛经历,带你深刻了解什么是 Spark on Hive!| 原力计划

MATLAB 被禁点燃导火索,国产软件路在何方?

破碎的互联网下,加密技术正在恢复数据主权!

你点的每个“在看”,我都认真当成了喜欢

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存