上一篇内容我们了解了vue组件中关于prop选项的内容,props选项实现了父组件向子组件的数据传递,这篇我们将了解一下子组件与父组件进行通信。

$emit()方法

子组件使用 $emit()方法触发父组件事件。在父组件中通过v-on指令监听子组件的自定义事件,然后自定义事件执行 $emit()方法触发父组件事件,这样就可以实现子组件和父组件之间的通信

<div id="app">
        <post-item :value="arr" @greet="fatherClick"></post-item>
    </div>
    <script>
        Vue.component('PostItem', {
            props: [
                'value'
            ],
            methods: {
                click() {
                    this.$emit('greet', '这是通过$emit方法触发')
                }
            },
            template: '<h3> <button type="button" v-on:click="click">点击一下</button></br> {{ value }}</h3>'
        })
        let vm = new Vue({
            el: "#app",
            data: {
                arr: ""
            },
            methods: {
                fatherClick(value) {
                    this.arr = value;
                }
            }
        })
    </script>

通过$emit方法的第一个参数是事件名,第二个参数是参数
在上述案例中,在我们先监听子组件的单击事件,当触发单击事件后执行子组件的click方法,然后click方法触发父组件中的fatherClick方法,并将参数传递过去。

vue2 中监听行页面resize_javascript


vue2 中监听行页面resize_javascript_02

.sync修饰符

在vue中,一个组件通过prop属性传递数据是单向的,父组件可以将数据传递到子组件。但是在特殊情况下,需要对一个组件的prop进行双向绑定,vue提供了一个update:myPropName模式触发事件来实现双向绑定。看下列案例:

<div id="app">
        <span>计数器的值:{{ counter }}</span>
        <parent :val="counter" v-on:update:count="counter = $event"></parent>
    </div>
<script>
        Vue.component('parent', {
            props: {
                count: {
                    type: Number,
                    define: 0
                }
            },
            template: `
            <div>
                <span>计数:{{ count }}</span>    
                <button @click="Click">添加计数</button> 
            </div>
            `,
            methods: {
                Click() {
                    this.$emit('update:count', ++this.count);
                }
            },
        })
        let vm = new Vue({
            el: "#app",
            data: {
                counter: 0
            }
        })
    </script>

在这个组件中有一个名为 count的prop,点击按钮的单击事件,调动 $emi(()方法触发 update:val事件, 并将加 1 之后的计数值作为事件的附加参数。

在父组件中,使用 v-on指令监听 update:val事件,这样就可以接收子组件传递过来的数据,然后使用 v-bind 指令绑定子组件中名为 count 的 prop,就可以实现给子组件传递父组件的数据,这样就实现了数据的双向绑定。

其中$event是自定义的事件的附加参数,而update:val事件是一个自定义事件,所以其参数就是加 1 之后的计数值。

vue2 中监听行页面resize_Vue_03

在上面我们实现的数据双向绑定比较复杂,vue 提供了.sync修饰符简化了数据的双向绑定,如下所示修改:

<parent :count.sync="counter"></parent>

需要注意的是,在这种简化方式,一定要确保 prop 中的参数和 需要出发的事件同名,且事件名必须是update:开头,如下所示:

<parent :count.sync="counter"></parent>
this.$emit('update:count', ++this.count);
 props: {
                count: {
                    type: Number,
                    define: 0
                }
            },

//如果进行修改,则同时改变
<parent :ss.sync="counter"></parent>
 this.$emit('update:ss', ++this.ss);
  props: {
                ss: {
                    type: Number,
                    define: 0
                }
            },

.native修饰符

.native修饰符主要是将原生事件绑定到组件。

<div id="app">
      <div :style="'font-size:'+fontsize+'em'">
         <parent v-for="book of books" :book="book" @click.native="fangda"></parent>
      </div>
</div>
Vue.component('parent', {
    props: ['book'],
    template: `
    <div>
        <p>{{ book.title }}</p>    
        <button>放大字体</button>
        <p>{{ book.content }}</p>    
    </div>
     `,
})
let vm = new Vue({
            el: "#app",
            data: {
                fontsize: 1,
                books: [{
                    title: "朝花夕拾",
                    content: "鲁迅的文章",
                    id: 1
                }, {
                    title: "时间简史",
                    content: "反正我不喜欢看,但是她很出名",
                    id: 2
                }]
            },
            methods: {
                fangda() {
                    this.fontsize++;
                }
            }
        })

vue2 中监听行页面resize_vue.js_04

在上述案例中,我们将点击事件通过.native修饰符添加到了组件根元素上,导致点击任何文字都会将字体放大。

但我们需要的效果是点击按钮放大文字,所以我们需要通过$listeners属性将组件所有的事件监听器全部转发到特定的子元素

Vue.component('parent', {
    props: ['book'],
    template: `
    <div>
        <p>{{ book.title }}</p>    
        <button v-on="$listeners">放大字体</button>
        <p>{{ book.content }}</p>    
    </div>
     `,
})

上述案例就是当单击按钮之后才能修改文本大小。需要注意的是$listeners属性虽然会将所有的事件监听转发到特定的子元素,但是不包括通过.native修饰的事件