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

1、自定义事件

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

示例代码:

<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(示例中使用了语法糖)来监听。

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

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

<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
这也可以称作一种语法糖,因为上例可以间接的用自定义事件来实现,如下:

<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 创建自定义表单输入控件,进行数据双向绑定。

示例如下:

<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组件要满足下面两个要求
             * 1、接收一个value属性
             * 2、在有新的value时出发input事件
             * */
</script>

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

Logo

前往低代码交流专区

更多推荐