Vue 组件(二)子组件向父组件传递数据

子组件向父组件传递数据有一下两种方式:javascript

一、自定义事件java

子组件用”$emit()“来触发事件,父组件用”$on()“来监听子组件事件。父组件也能够直接在子组件的自定义标签上使用” v-on ” 来监听子组件触发的自定义事件。(由于” v-on “除了监听DOM事件外,还能够用于组件间的自定义事件。)web

示例代码:express

<div id="app"> <p>{{total}}</p> <my-component @increace="getTotal" @reduce="getTotal"></my-component> </div>
<script>    
        Vue.component('my-component',{
            template:`\
               <div>\
                  <button @click="increaceTotal">增长</button>\
                  <button @click="reduceTotal">减小</button>\
               </div>`,

            data: function(){
                return{
                    counter:0
                } 
            },
            methods:{
                increaceTotal:function(){
                    this.counter ++;
                    this.$emit('increace',this.counter);
                },
                reduceTotal:function(){
                    this.counter --;
                    //$emit()第一个参数是自定义事件名称,
                    //第二个参数是要传递的数据,能够不填或填写多个
                    this.$emit('reduce',this.counter);
                }

            }
        });     
        new Vue({
            el:'#app',
            data:{
                total:0
            },
            methods:{
                getTotal:function(total){
                    this.total = total;
                }
            }
        })      
</script>

上面例子中,子组件有两个按钮,实现加1和减1的效果,在改变组件的 data:”counter” 后,经过 $emit()再把它传递给父组件,父组件经过 v-on:increacev-on:reduce(示例中使用了语法糖)来监听。app

运行效果:
这里写图片描述svg

二、使用 v-model 指令
示例代码:this

<div id="app"> <p>总数:{{total}}</p> <my-component v-model="total"></my-component> </div>
<script>
    Vue.component('my-component',{
            template:`<button @click="handleClick">++1</button>`,
                data: function(){
                    return{
                        counter:0
                    }
                },
                methods:{
                    handleClick:function(){
                        this.counter++;
                          //组件$emit()事件名是特殊的input
                        this.$emit('input',this.counter);
                    }
                }
            });

            new Vue({
                el:'#app',
                data:{
                    total:0
                }               
            })
            /* 组件$emit()事件名是特殊的input, * 在使用组件的父级直接用了 v-model 绑定的一个数据 total. * 能够间接的用自定义事件来实现。 * */
</script>

这里写图片描述
上面的示例仍然是点击按钮加1的效果,不过此次组件$emit()事件名是特殊的input ,在使用组件的父级,并无在<my-component>上使用 v-on:increace = "handle" 这样的监听器,而是直接使用了 v-model 绑定的一个 total
这也能够称做一种语法糖,由于上例能够间接的用自定义事件来实现,以下:spa

<div id="app"> <p>总数:{{total}}</p> <my-component @input="handle"></my-component> </div>
<script> Vue.component('my-component',{ //.....省略组件代码 }); new Vue({ el:'#app', data:{ total:0 }, methods:{ handle:function(counter){ this.total = counter; } } }) </script>

运行结果和上例相同。双向绑定

v-model 建立自定义表单输入控件,进行数据双向绑定。code

示例以下:

<div id="app"> <p>总数:{{total}}</p> <my-component v-model="total"></my-component> <button @click="handleReduce">-1</button> </div>
<script>
    Vue.component('my-component',{
          props:['value'],
          template:`\
            <input :value="value" @input="updateValue"></input>`,
          methods:{
                    updateValue:function(event){
                        this.$emit('input',event.target.value);
                    }
                }
            });         
    new Vue({
            el:'#app',
            data:{
                total:0
                },
            methods:{
                    handleReduce:function(){
                        this.total--;
                    }
                }
            })          
            /* 实现这样一个具备双向绑定的v-model组件要知足下面两个要求 * 一、接收一个value属性 * 二、在有新的value时出发input事件 * */
</script>

运行结果:
这里写图片描述
这里写图片描述