首页 > 编程笔记
Vue子组件给父组件传值详解
组件的 prop 属性只能实现父组件向子组件传值,在实际的前端项目中,需要实现子组件将值传给父组件。Vue.js 提供了 3 种机制,实现子组件将值传给父组件。
$emit 方法的第 1 个参数是一个字符串,对应 v-on 指定的事件名称,父组件中使用 v-on 给 son-component 组件的 parent-method 事件绑定了定义在父组件中 parentMethod 函数,在 son-component 的 toTest 函数中,使用 this.$emit('parent-method') 方式触发 parent-method 事件,执行 parentMethod 方法,实现父组件中的 count 自增,代码如下:
在 son-component 子组件的 toTest 方法中,通过第 2 个参数给父组件中绑定的 parentMethod 方法传递 count 的递增幅度 step,代码如下:
父组件基于子组件的 funcData prop 属性,给子组件 son-component 传递 increment 函数对象,在子组件 son-component的toTest 方法中,调用传入的 increment 函数,并且传入参数 step 的值,代码如下:
input 元素中的 b-bind:value='name',将 name 数据属性的值绑定到 input 的 value 属性上,这样 input 输入框就可以实时显示 name 数据属性的值了。
input 元素中的 v-on:input="demoInputChange($event)" 将 demoInputChange 函数绑定到 input 元素的 input 事件上,并且传入了当前的事件对象,当 input 事件触发时自动执行 demoInputChange 函数,将 input 的 value 属性的值赋给 name 数据属性,从而实现了 input 元素中的 value 同 Vue.js 实例对象中的 name 数据属性的双向绑定,代码如下:
1、使用$emit方法调用父组件方法传值
在 Vue.js 的父组件中,可以通过 v-on 指令,给子组件的指定事件绑定一个函数,在子组件中,用 $emit 方法触发自己的事件,从而执行被绑定的函数。$emit 方法的第 1 个参数是一个字符串,对应 v-on 指定的事件名称,父组件中使用 v-on 给 son-component 组件的 parent-method 事件绑定了定义在父组件中 parentMethod 函数,在 son-component 的 toTest 函数中,使用 this.$emit('parent-method') 方式触发 parent-method 事件,执行 parentMethod 方法,实现父组件中的 count 自增,代码如下:
<div id="app"> <son-component v-on:parent-method="parentMethod"></son-component> <br /> <div>{{ count }}</div> </div> <template id="sonComponent"> <button v-on:click="toTest">单击子组件</button> </template> <script type="text/javascript"> const SonComponent = { template: '#sonComponent', methods: { toTest() { this.$emit('parent-method'); } } }; const vm = new Vue({ el: '#app', components: { SonComponent }, data: { count: 0 }, methods: { parentMethod() { this.count++; } } }); </script>$emit 方法必须有一个参数指定要触发的事件,同时支持更多的可选参数,通过这些参数,子组件可以将自己的数据传递给事件绑定的方法,而绑定的方法是定义在父组件中的,所以就可以间接地使用 $emit 方法,将子组件中的数据传递给父组件。
在 son-component 子组件的 toTest 方法中,通过第 2 个参数给父组件中绑定的 parentMethod 方法传递 count 的递增幅度 step,代码如下:
<div id="app"> <son-component v-on:parent-method="parentMethod"></son-component> <br /> <div>{{ count }}</div> </div> <template id="sonComponent"> <button v-on:click="toTest">单击子组件</button> </template> <script type="text/javascript"> const SonComponent = { template: '#sonComponent', methods: { toTest() { this.$emit('parent-method', 2); } } }; const vm = new Vue({ el: '#app', components: { SonComponent }, data: { count: 0 }, methods: { parentMethod(step) { this.count += step; } } }); </script>
2、调用父组件的方法传值
prop 属性的数据类型支持 Function,利用这个特点,开发人员可以在父组件中定义一个 Function 类型的 prop 属性,给子组件传递一个函数对象,在子组件中调用这个函数,通过函数的参数,可以将子组件中的数据传递给父组件。父组件基于子组件的 funcData prop 属性,给子组件 son-component 传递 increment 函数对象,在子组件 son-component的toTest 方法中,调用传入的 increment 函数,并且传入参数 step 的值,代码如下:
<div id="app"> <son-component v-bind:func-data="increment"></son-component> <br /> {{ count }} </div> <template id="sonComponentTemplate"> <button v-on:click="toTest">单击递增</button> </template> <script type="text/javascript"> const SonComponent = { template: '#sonComponentTemplate', props: { funcData: { type: Function } }, methods: { toTest() { this.funcData(2); } } }; const vm = new Vue({ el: '#app', components: { SonComponent }, data: { count: 0 }, methods: { increment(step) { this.count += step; } } }); </script>
3、使用v-model实现父子组件的数据同步
v-model 指令可以实现 input 输入框同组件数据属性双向同步,改变输入框的值,此值能自动被同步到 Vue.js 实例对象中。同样,改变 Vue.js 实例对象的数据属性,此数据属性也能自动被同步到 input 输入框,代码如下:<div id="app"> name: {{ name }}<br /> <input v-model="name" /><br /> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data: { name: '' } }); </script>实际上,v-model 是 v-bind:value 和 v-on:input 两个指令的组合:
- v-bind:value 指令将 Vue.js 实例对象的数据属性绑定到 input 元素的 value 属性;
- v-on:input 指令给 input 元素的 input 事件绑定一个函数,该函数将 input 输入框的 value 属性值赋给 Vue.js 实例对象的数据属性。
input 元素中的 b-bind:value='name',将 name 数据属性的值绑定到 input 的 value 属性上,这样 input 输入框就可以实时显示 name 数据属性的值了。
input 元素中的 v-on:input="demoInputChange($event)" 将 demoInputChange 函数绑定到 input 元素的 input 事件上,并且传入了当前的事件对象,当 input 事件触发时自动执行 demoInputChange 函数,将 input 的 value 属性的值赋给 name 数据属性,从而实现了 input 元素中的 value 同 Vue.js 实例对象中的 name 数据属性的双向绑定,代码如下:
<div id="app"> name: {{ name }}<br /> <input v-bind:value="name" v-on:input="demoInputChange($event)" /><br /> </div> <script type="text/javascript"> const vm = new Vue({ el: '#app', data: { name: '' }, methods: { demoInputChange(event) { this.name = event.target.value; } } }); </script>既然 v-bind 和 v-on 的组合可以实现 input 元素的 value 属性同 Vue.js 实例对象的数据属性的双向绑定,同样可以用在子组件上,实现子组件的 value 和数据属性的双向绑定,代码如下:
<div id="app"> <!-- 子组件使用v-bind和v-on:input的组合 --> age: {{ age }}<br /> <son-component v-bind:age="age" v-on:input="sonChange"></son-component> </div> <template id="sonComponentTemplate"> <input type="text" v-bind:value="age" v-on:input="toChange($event)" /> </template> <script type="text/javascript"> const SonComponent = { template: '#sonComponentTemplate', props: ['age'], methods: { toChange(event) { this.$emit('input', event.target.value); } } }; const vm = new Vue({ el: '#app', components: { SonComponent }, data: { age: 0 }, methods: { sonChange(age) { this.age = age; } } }); </script>使用 v-model 合并子组件的 v-bind 和 v-on 指令,代码如下:
<div id="app"> <!-- 子组件使用v-bind和v-on:input的组合 --> age: {{ age }}<br /> <son-component v-model="age"></son-component> </div> <template id="sonComponentTemplate"> <input type="text" v-bind:value="age" v-on:input="toChange($event)" /> </template> <script type="text/javascript"> const SonComponent = { template: '#sonComponentTemplate', props: ["age"], methods: { toChange(event) { this.$emit('input', event.target.value); } } }; const vm = new Vue({ el: '#app', components: { SonComponent }, data: { age: 0 } }); </script>