Vuejs学习笔记(二)-9.父子组件交互案例
前置:父组件有data.num1,子组件通过props定义了cnum1来接收data.num1的值
需求:在子组件内定义个输入框,希望输入数据时能够改变父组件的data.num1的值。
思路:v-model双向绑定
1.通过v-model将子组件的输入框与props.cnum1双向绑定
代码如下:
1 <!-- 2 @author:invoker 3 @project:project_lianxi 4 @file: 13-父子组件交互南里.html 5 @contact:invoker2021@126.com 6 @descript: 7 @Date:2021/7/4 21:50 8 @version: html5 9 --> 10 11 <!DOCTYPE html> 12 <html lang="en"> 13 <head> 14 <meta charset="UTF-8"> 15 <title>13-父子组件交互案例</title> 16 </head> 17 <body> 18 <div id="app"> 19 <h2>父组件num1的值->data:{{num1}}</h2> 20 <p>-----------------------父子组件分隔符-----------------------------</p> 21 <h2>以下是父组件调用子组件</h2> 22 <cpn :cnum1="num1"></cpn> 23 </div> 24 <template id="cpn"> 25 <div> 26 <h2>子组件cnum1的值->props:{{cnum1}}</h2> 27 <label for="input1">子组件的输入框绑定的是cnum1:</label> 28 <input id="input1" type="text" v-model="cnum1"> 29 </div> 30 </template> 31 <script src="../js/vue.js"></script> 32 <script> 33 const cpn = { 34 template: '#cpn', 35 props: { 36 cnum1: Number 37 }43 } 44 45 const app = new Vue({ 46 el: '#app', 47 data: { 48 num1: 0 49 }, 50 components: { 51 cpn 52 } 53 }) 54 </script> 55 </body> 56 </html>
界面可以实现输入框与props.cnum1的双向绑定,但是页面报错,vue不希望子组件绑定props内的值,只希望父组件与子组件通信是使用props
2.这个时候子组件的input的v-model双向绑定就不能绑定props内的属性了,需要在子组件内部data函数中另外定义一个变量来存放数据。此处用cdnum1
代码如下:
1 <!-- 2 @author:invoker 3 @project:project_lianxi 4 @file: 13-父子组件交互南里.html 5 @contact:invoker2021@126.com 6 @descript: 7 @Date:2021/7/4 21:50 8 @version: html5 9 --> 10 11 <!DOCTYPE html> 12 <html lang="en"> 13 <head> 14 <meta charset="UTF-8"> 15 <title>13-父子组件交互案例</title> 16 </head> 17 <body> 18 <div id="app"> 19 <h2>父组件num1的值->data:{{num1}}</h2> 20 <p>-----------------------父子组件分隔符-----------------------------</p> 21 <h2>以下是父组件调用子组件</h2> 22 <cpn :cnum1="num1"></cpn> 23 </div> 24 <template id="cpn"> 25 <div> 26 <h2>子组件cnum1的值->props:{{cnum1}}</h2> 27 <!-- <label for="input1">子组件的输入框绑定的是cnum1:</label>--> 28 <!-- <input id="input1" type="text" v-model="cnum1">--> 29 <h2>子组件的cdnum1的值->data:{{cdnum1}}</h2> 30 <label for="input2">子组件的输入框绑定的是cdnum1:</label> 31 <input id="input2" type="text" v-model="cdnum1"> 32 33 </div> 34 </template> 35 <script src="../js/vue.js"></script> 36 <script> 37 const cpn = { 38 template: '#cpn', 39 props: { 40 cnum1: Number 41 }, 42 data() { 43 return { 44 cdnum1: this.cnum1 45 } 46 } 47 } 48 49 const app = new Vue({ 50 el: '#app', 51 data: { 52 num1: 0 53 }, 54 components: { 55 cpn 56 } 57 }) 58 </script> 59 </body> 60 </html>
子组件cpn定义data.cdnum1,然后在input内使用 v-model双向绑定cdnum1,这么做实现了input输入后直接改变cdnum1的需求。
问题又来了,如何变更父组件的num1呢?需要使用v-model的实现原理中@input,监听input事件,再通过Input事件的方法中使用自定义事件发射数据给父组件,父组件再使用自定义事件的方法来改变传过来的值。
代码如下:
1 <!-- 2 @author:invoker 3 @project:project_lianxi 4 @file: 13-父子组件交互南里.html 5 @contact:invoker2021@126.com 6 @descript: 7 @Date:2021/7/4 21:50 8 @version: html5 9 --> 10 11 <!DOCTYPE html> 12 <html lang="en"> 13 <head> 14 <meta charset="UTF-8"> 15 <title>13-父子组件交互案例</title> 16 </head> 17 <body> 18 <div id="app"> 19 <h2>父组件num1的值->data:{{num1}}</h2> 20 <p>-----------------------父子组件分隔符-----------------------------</p> 21 <h2>以下是父组件调用子组件</h2> 22 <cpn :cnum1="num1" @childcdnumchange="num1change"></cpn> 23 </div> 24 <template id="cpn"> 25 <div> 26 <h2>子组件cnum1的值->props:{{cnum1}}</h2> 27 <!-- <label for="input1">子组件的输入框绑定的是cnum1:</label>--> 28 <!-- <input id="input1" type="text" v-model="cnum1">--> 29 <h2>子组件的cdnum1的值->data:{{cdnum1}}</h2> 30 <!-- <label for="input2">子组件的输入框绑定的是cdnum1:</label>--> 31 <!-- <input id="input2" type="text" v-model="cdnum1">--> 32 <label for="input3">子组件的输入框绑定的是cdnum1:</label> 33 <input id="input3" type="text" :value="cdnum1" @input="emitCdnumToFather"> 34 35 </div> 36 </template> 37 <script src="../js/vue.js"></script> 38 <script> 39 const cpn = { 40 template: '#cpn', 41 props: { 42 cnum1: Number 43 }, 44 data() { 45 return { 46 cdnum1: this.cnum1 47 } 48 }, 49 methods:{ 50 emitCdnumToFather(event){ 51 this.cdnum1 = event.target.value 52 this.$emit('childcdnumchange',this.cdnum1) 53 } 54 } 55 } 56 57 const app = new Vue({ 58 el: '#app', 59 data: { 60 num1: 0 61 }, 62 components: { 63 cpn 64 }, 65 methods:{ 66 num1change(value){ 67 this.num1 = value 68 } 69 } 70 }) 71 </script> 72 </body> 73 </html>
代码解释:
1.input中不使用v-model,因为v-model只能双向绑定数据,暂时无法使用自定义事件。
2.input中使用 v-bind:value="cdnum1"来绑定cdnum1的数据。
3.input中使用 v-on:input来监听input事件。
4.监听到input事件则调用emitCdnumToFather方法,这个方法做了2件事件,第一,将实时输入事件的值传给cdnum1,实现了v-model的双向绑定。第二件事件,定义了自定义事件childcdnumchange,即子组件中的cdnum1发送改变,则将cdnum1的值作为事件参数传给父组件。
5.父组件在使用子组件时,创建监听该自定义事件 <cpn @childcdnumchange="num1change" :cnum1="num1"/>,并创建一个方法执行 num1change
6.在父组件的num1change中将传入的cdnum1的值value赋值给父组件的num1
结果如下:实现了子组件双向绑定,且改变子组件的值可以同时改变父组件的值。
第一步改变子组件input内的值cdnum1
第二步双向绑定改变父组件num1的值
第三步父组件通过props将父组件的值传给子组件的props
报错原因:因为子组件输入框输入的是string类型,需要传唤成Number类型。
因此,在父组件的num1change方法中需要使用类型转换
代码如下:
1 <!-- 2 @author:invoker 3 @project:project_lianxi 4 @file: 13-父子组件交互南里.html 5 @contact:invoker2021@126.com 6 @descript: 7 @Date:2021/7/4 21:50 8 @version: html5 9 --> 10 11 <!DOCTYPE html> 12 <html lang="en"> 13 <head> 14 <meta charset="UTF-8"> 15 <title>13-父子组件交互案例</title> 16 </head> 17 <body> 18 <div id="app"> 19 <h2>父组件num1的值->data:{{num1}}</h2> 20 <p>-----------------------父子组件分隔符-----------------------------</p> 21 <h2>以下是父组件调用子组件</h2> 22 <cpn :cnum1="num1" @childcdnumchange="num1change"></cpn> 23 </div> 24 <template id="cpn"> 25 <div> 26 <h2>子组件cnum1的值->props:{{cnum1}}</h2> 27 <!-- <label for="input1">子组件的输入框绑定的是cnum1:</label>--> 28 <!-- <input id="input1" type="text" v-model="cnum1">--> 29 <h2>子组件的cdnum1的值->data:{{cdnum1}}</h2> 30 <!-- <label for="input2">子组件的输入框绑定的是cdnum1:</label>--> 31 <!-- <input id="input2" type="text" v-model="cdnum1">--> 32 <label for="input3">子组件的输入框绑定的是cdnum1:</label> 33 <input id="input3" type="text" :value="cdnum1" @input="emitCdnumToFather"> 34 35 </div> 36 </template> 37 <script src="../js/vue.js"></script> 38 <script> 39 const cpn = { 40 template: '#cpn', 41 props: { 42 cnum1: Number 43 }, 44 data() { 45 return { 46 cdnum1: this.cnum1 47 } 48 }, 49 methods:{ 50 emitCdnumToFather(event){ 51 this.cdnum1 = event.target.value 52 this.$emit('childcdnumchange',this.cdnum1) 53 } 54 } 55 } 56 57 const app = new Vue({ 58 el: '#app', 59 data: { 60 num1: 0 61 }, 62 components: { 63 cpn 64 }, 65 methods:{ 66 num1change(value){ 67 this.num1 = parseInt(value) 68 } 69 } 70 }) 71 </script> 72 </body> 73 </html>
本文来自博客园,作者:kaer_invoker,转载请注明原文链接:https://www.cnblogs.com/invoker2021/p/14970451.html