组件实例之间的作用域是独立的,意味了不应该在子组件的模板内直接引用父组件的数据,但是父子组件之间需要通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。

这里写图片描述

prop 是父组件用来传递数据的一个自定义属性。子组件需要显式地用 props 选项声明 “prop”:

Vue.component('child', {

      // 声明 props

      props: ['message'],

      // 就像 data 一样,prop 可以用在模板内

      // 同样也可以在 vm 实例中像 “this.message” 这样使用

      template: '<span>{{ message }}</span>'

  })

一个实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多层组件通信</title>
</head>
<body>
    <div id="app">
        <my-parent :imgtitle='title' :imgsrc='img'></my-parent>
    </div>

    <template id="my_img">
        <img :src="imgsrc" width="200">
    </template>

    <template id="my_title">
        <h2>{{title}}</h2>
    </template>

    <template id="my_parent">
        <div>
            <child1 :imgsrc="imgsrc"></child1>
            <child2 :title="imgtitle"></child2>
        </div>
    </template>

        <script src="js/vue.min.js"></script>
        <script>
            //1.子组件的实例
            let Child1 = Vue.extend({
                template:'#my_img',
                props:['imgsrc']
            });
            let Child2 = Vue.extend({
                template:'#my_title',
                props:['title']
            });
            //注册父组件
            Vue.component('my-parent',{
                props:['imgtitle','imgsrc'],
                components:{
                    'child1':Child1,
                    'child2':Child2
                },
                template:'#my_parent'
            });
            new Vue({
                el:'#app',
                data:{
                    title:'我很帅',
                    img:'img/01.jpg'
                }
            });
        </script>
</body>
</html>

可以看到数据从父组件通过props传递给子组件,但是注意通过这种方法prop默认是单向绑定, 当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态。

然后就是子组件传递数据给父组件,通过自定义事件。

每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件

  • 使用 $emit(eventName) 触发事件

父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

一个实例,一旦子组件的total()事件发生,通过emit触发父组件的方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue的自定义事件</title>
</head>
<body>
<div id="app">
    <my-btn @total="allcounter()"></my-btn>
    <my-btn @total="allcounter()"></my-btn>
    <my-btn @total="allcounter()"></my-btn>
    <my-btn @total="allcounter()"></my-btn>
    <my-btn @total="allcounter()"></my-btn>
    <my-btn @total="allcounter()"></my-btn>
    <p>所有按钮一共点击了{{totalCounter}}</p>
</div>

<template id='my_btn'>
    <button @click="total()">点击了{{counter}}</button>
</template>

<script src="js/vue.min.js"></script>
<script>
    Vue.component('my-btn',{
        template:'#my_btn',
        data(){
            return{
                counter:0
            }
        },
        methods:{
            total(){
                this.counter += 1;

                //子组件通知外界,我调用了这个方法
                this.$emit('total');
            }
        }
    });

    new Vue({
        el: '#app',
        data: {
            totalCounter:0
        },
        methods:{
            allcounter(){
                this.totalCounter += 1;
            }
        }
    });
</script>
</body>
</html>

运行结果就是子组件之间的点击互不影响,父组件总点击数增加。

Logo

前往低代码交流专区

更多推荐