vue 组件通信方式

538 阅读1分钟

vue 中组件通信总共分为四种,父子组件通信,子父组件通信,兄弟组件通信

1. 父子通信

  • 父组件通过属性绑定方式,向自子组件传递数据
  • 子组件通过props 接受父组件传递的数据,props 有两种形式,一种形式是数组,另一种形式是对象,对象比数组的好处是,对象可以对当前传递的数据进行个性化配置

数组形式的 props

<!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>
</head>
<body>
    <div id="app">
        <child :msg="msg"></child>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('child', {
            template:  `
                <div>
                    <p>{{msg}}</p>    
                </div>
            `,
            props:['msg']
        })
        new Vue({
            el: '#app',
            data: {
                msg: '这是父组件传递的数据'
            }
        })
    </script>
</body>
</html>

对象形式的 props

<!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>
</head>
<body>
    <div id="app">
        <child :msg="msg"></child>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('child', {
            template:  `
                <div>
                    <p>{{msg}}</p>    
                </div>
            `,
            props: {
                msg: {
                    default: '这是子组件默认的数据', // 父组件不向子组件传递数据时,子组件默认的数据
                    type:String, // 用于控制父组件传递的数据类型
                    required: true // 用于控制父组件是否必须传递数据
                }
            }
        })
        new Vue({
            el: '#app',
            data: {
                msg: '这是父组件传递的数据'
            }
        })
    </script>
</body>
</html>

2. 子父通信

  • 子组件通过 $emit 触发自定义事件,并传递数据
  • 父组件通过监听自定义事件来判断子组件是否触发
<!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>
</head>
<body>
    <div id="app">
        <child @cp="handle($event)" :msg="msg"></child>  <!-- $event 是当前子组件传递的数据-->
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('child', {
            template:  `
                <div>
                    <p @click="child">{{msg}}</p>    
                </div>
            `,
            props: {
                msg: {
                    default: '这是子组件默认的数据', // 父组件不向子组件传递数据时,子组件默认的数据
                    type:String, // 用于控制父组件传递的数据类型
                    required: true // 用于控制父组件是否必须传递数据
                }
            },
            methods: {
                child() {
                    this.$emit('cp', '这是子组件传递的数据') // 触发父组件监听的自定义事件
                }
            }
        })
        new Vue({
            el: '#app',
            data: {
                msg: '这是父组件传递的数据'
            },
            methods: {
                handle(val) { // val 表示当前子组件传递的数据
                    console.log(val); 
                }
            }
        })
    </script>
</body>
</html>

3. 兄弟组件通信

  • 通过事件总线的方式去触发,事件总线就是一个 vue的实例对象,我们通过 on监听的事件,on监听的事件,emit 触发的事件都在这个 vue 的实例对象里面
<!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>
</head>
<body>
    <div id="app">
        <child1></child1>
        <child2></child2>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        // 获取当前事件中心
        var hub = new Vue()
        // 兄弟组件一
        Vue.component('child1', {
            template:`
                <div>
                    <p>这是兄弟组件一</p>    
                    <button @click="changeTwo">传递给兄弟组件二</button>
                </div>
            `,
            methods: {
                changeTwo() {
                    hub.$emit('change-two', '这是兄弟组件一传递的数据')
                }
            },
            mounted() {
                hub.$on('change-one', (val) => {
                    console.log(val);
                })
            }
        })
        // 兄弟组件二
        Vue.component('child2', {
            template:`
                <div>
                    <p>这是兄弟组件二</p>    
                    <button @click="changeOne">传递给兄弟组件一</button>
                </div>
            `,
            methods: {
                changeOne() {
                    hub.$emit('change-one', '这是兄弟组件二传递的数据')
                }
            },
            mounted() {
                hub.$on('change-two', (val) => {
                    console.log(val);
                })
            }
        })
        new Vue({
            el: '#app'
        })
    </script>
</body>
</html>

4.依赖注入

  • provide 与 inject的传值与 props 类似,前者可以给后代组件传值,而props是只能给子组件传值。
  • 使用 provide与inject 方法传值,如果值修改后面组件的值是不会跟着变得,也就是说值不会响应,(这种方式也是单向数据轻易不要修改)
  • 一般使用在组件封装当中
<!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>
</head>

<body>
    <div id="app">
        <father></father>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        Vue.component('father', {
            template: `
                <div>
                    <son></son>    
                </div>
            `
        })
        Vue.component('son', {
            template: `
                <div>
                    <p>这是son 组件</p>    
                    <p>{{foo}}</p>
                </div>
            `,
            inject: { // 接受隔代数据
                foo: { 
                    default: 'foo'
                }
            }
        })
        new Vue({
            el: '#app',
            provide: { // 对子代共享的数据
                foo: 'bar'
            }
        })
    </script>
</body>

</html>