详情请点阅读全文
一、组件各部分说明及互相引用 1 2 3 4 5 6 1. 一个vue组件由三个部分组成 Template 只能存在一个根元素 2. Script 3. Style scoped:样式只在当前组件内生效
1.1 组件的基本引用代码示例 重点:第1步,app.vue;第2步,father.vue
0、src/main.js 1 2 3 4 5 6 7 8 9 10 11 12 13 import Vue from 'vue' import App from './App' Vue.config.productionTip = false new Vue({ el: '#app' , components: { App }, template: '<App/>' })
第1步,src/APP.vue引入子组件示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <template> <div id="app" > <img src="./assets/logo.png" > <Father /> <!-- 【2 】第2 步,调用子组件 --> </div> </ template><script> import Father from './components/father' export default { name: 'App' , components: { Father }, data () { return { msg: 'hello' , } }, } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </ style>
第2步,src/components/father.vue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <template> <div> <!-- 第一层只能有一个根标签 --> 父组件 <Child /> <!-- 【2 】第2 步,调用子组件 --> </div> </ template><script> import Child from './child' export default { name:'Father' , components:{ Child, }, data(){ return {msg :'father' } }, } </script> <style scoped> / * [4 ]知识点4 ,此处写的样式只对当前father.vue组件生效 */ </ style>
第3步,src/components/child.vue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <template> <div> 子组件 </div> </ template><script> export default { name:'child' , data(){ return { tit :'child' } } } </script> <style scoped> </ style>
效果: 父组件 子组件
二、父–>子组件通信(交互)props—-父传子 1.通过设置子组件的Props(道具)接收父组件的传值代码示例 father.vue 1、父组件设置一个属性:(如name=xxx)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <template> <div> <h1>主题:父组件向子组件传值</h1> <Child title='父组件的数据' / > <!-- 【1 】第1 步,建一个属性title=xx,写入xx数据 --> </div> </ template><script> import Child from './child' export default { name:'Father' , components:{ Child, }, data(){ return {msg :'father' } }, } </script> <style scoped> </ style>
child.vue 2、子组件通过设置props接收父组件传过来的内容:props:[ ‘name’ ]或 props:{name:{type:String,default:’’}} 3、显示父组件传的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <template> <div> <!-- 【3 】显示父组件传过来的值 --> <h2>子组件:{{title}}</h2> </ div></template> <script> export default{ name:'child', data(){ return{} }, props:["title"] #【2】通过props接收父组件传的数据 } </ script><style scoped> </style>
效果:箭头部分即父组件title=xxx,传过来的值
2.向子组件传data里的动态数据 father.vue 1、在data(){title:’title content’} 2、把<child title=xxx />
中的xx换成data里的title
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <template> <div> <h1>主题:父组件向子组件传data里的动态值</h1> <Child v-bind:title="msg" / > <!-- 【1 】第1 步,title=xx,的内容写成data里的属性名 --> </div> </ template><script> import Child from './child' export default { name:'Father' , components:{ Child, }, data(){ return { msg:"父组件data内的动态的数据" , } }, } </script> <style scoped> </ style>
child.vue 3、child里不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <template> <div> <!-- 【2 】显示父组件传过来的值 --> <h2>子组件:{{title}}</h2> </ div></template> <script> export default{ name:'child', data(){ return{tit:'child'} }, props:["title"]/ /[1]接收父组件的属性名(在father.vue里的<child title=xx / > ) } </script> <style scoped> </ style>
3.改变data里的msg,将自动传给子组件示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <template> <div> <h1>主题:父组件向子组件传data里的动态值</h1> <Child v-bind:title="msg" / > <!-- 【1 】第1 步,title=xx,的内容写成data里的属性名 --> <button v-on:click="change_msg" >改变一下</button> </ div></template> <script> import Child from './ child' export default{ name:' Father', components:{ Child, }, data(){ return { msg:"父组件data内的动态的数据",//【1】数据里写一个属性:值; } }, methods:{ change_msg(event){//按键的处理函数 this.msg=' 改变一下msg消息' } } } </script> <style scoped> </style>
效果:
4.子组件通过props,父组件的v-model,随时获取表单数据示例 father.vue 【1】第1步,再定义一个数据,初始数据随便设置 【2】第2步,再v-bind绑定第2个属性msg(此可随便设置,子组件的props对应即可)为data里的msg2 【3】第3步,在表单里绑定data里的msg2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <template> <div> <h1>主题:父组件通过v-model实时向子组件传data里的值</h1> <input v-model="msg2" / > <!-- 【3 】第3 步,在表单里绑定data里的msg2 --> <Child v-bind:title="msg" v-bind:msg='msg2' /> <!-- 【2 】第2 步,再v-bind绑定第2 个属性msg(此可随便设置,子组件的props对应即可)为data里的msg2 --> <button v-on:click="change_msg" >改变一下</button> </ div></template> <script> import Child from './ child' export default{ name:' Father', components:{ Child, }, data(){ return { msg:"父组件data内的动态的数据",//数据里写一个属性:值; msg2:' 父向子组件传递的第2 个数据'//【1】第1步,再定义一个数据,初始数据随便设置 } }, methods:{ change_msg(event){ this.msg=' 改变一下msg消息' } } } </script> <style scoped> </style>
child.vue 【1】接收父组件的属性1、2的名字title,msg(在father.vue里的<child title= msg= /> 【2】显示父组件传过来的属性1,属性2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <template> <div> <!-- 【2 】显示父组件传过来的属性1 ,属性2 --> <h2>子组件:{{title}}--{{msg}}</h2> </ div></template> <script> export default{ name:'child', data(){ return{ tit:'child'} }, props:["title","msg"]/ /[1]接收父组件的属性1、2的名子(在father.vue里的<child title=xx msg=xxx / > ) } </script> <style scoped> </ style>
效果:输入框值变动,子组件随时跟着变动
5.通过子组件的props限制父组件传过来的数据类型 father.vue 【1】再定义一个数据 【2】第2步,对子组件,再加个v-bind绑定第2个属性age(此可随便设置,子组件的props对应即可)为data里的num
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <template> <div> <h1>主题:父组件通过v-model实时向子组件传data里的值</h1> <input v-model="msg2" / > <Child v-bind:title="msg" v-bind:msg='msg2' :age='num' /> <!-- 【2 】第2 步,再v-bind绑定第2 个属性age(此可随便设置,子组件的props对应即可)为data里的num --> <button v-on:click="change_msg" >改变一下</button> </ div></template> <script> import Child from './ child' export default{ name:' Father', components:{ Child, }, data(){ return { msg:"父组件data内的动态的数据",//数据里写一个属性:值; msg2:' 父向子组件传递的第2 个数据', num:' hello'//【1】再定义一个数据 } }, methods:{ change_msg(event){ this.msg=' 改变一下msg消息' } } } </script> <style scoped> </style>
child.vue 【1】把props改成字典写法,逐个对其属性的数据类型进行限定,把age的数据类型限定为数字 【2】显示父组件传过来的属性3:age
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <template> <div> <!-- 【2 】显示父组件传过来的属性1 ,属性2 ,属性3 :age --> <h2>子组件:{{title}}--{{msg}}----{{age*2 }}</h2> </ div></template> <script> export default{ name:'child', data(){ return{tit:'child'} }, props:{/ /【1】把props改成字典写法,逐个对其属性的数据类型进行限定 title:String, msg:String, age:Number / /此处把age的数据类型限定为数字 }/ /["title","msg","age"]/ /[1]接收父组件的属性1、2的名子(在father.vue里的<child title=xx msg=xxx / > ) } </script> <style scoped> </ style>
效果:
因为fahter.vue里的data的num数据类型为’hello’是字符串类型
又child.vue里的props限定了num必须为数字
所以控制台会报错:Invalid prop: type check failed for prop “age”. Expected Number with value NaN, got String with value “hello”.
只有父组件里的数据为数字(如Num=10),此处才能正确运行显示:20(num2=10 2)5.2 子组件用props把父组件传过来的数据[限定为多种数据类型]、[设置为必需选项] 【1】设置为支持多种数据类型 title:[String,Number],父组件传的title值可以为字符串,或数字 【2】设置为是否必须选项,如果父组件没有传msg=xx这个属性,就报错1 2 3 4 msg:{ type:String , required:true }
原码:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <template> <div> <!-- 显示父组件传过来的属性1 ,属性2 ,属性3 :age --> <h2>子组件:{{title}}--{{msg}}----{{age*2 }}</h2> </ div></template> <script> export default{ name:'child', data(){ return {tit:'child'} }, props:{ title:[String,Number],/ /【1】设置为支持多种数据类型 msg:{/ /【2】设置为是否必须选项 type:String, required:true }, age:Number, } } </ script><style scoped> </style>
效果:父组件没传msg,警告信息5.3在子组件props设置默认值(如果父不传,则使用默认值) child.vue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <template> <div> <!-- 【2 】显示父组件传过来的属性1 ,属性2 ,属性3 :age --> <h2>子组件:{{title}}--{{msg}}----{{age*2 }}</h2> </ div></template> <script> export default{ name:'child', data(){ return {tit:'child'} }, props:{ title:[String,Number], msg:{ type:String, required:true }, age:{/ /【1】设置默认值 type:Number, default:5 } } } </ script><style scoped> </style>
结果:父组件没传num,子组件用默认值5计算出来的值5*2=106.父组件data数据为字典时,向子组件props传值 father.vue 【1】第1步,设置一个字典的数据 【2】第2步,再v-bind绑定ojbData为data里的fatherObj1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <template> <div> <h1>主题:父组件通过v-model实时向子组件传data里的【对象类型数据】值</h1> <input v-model="msg2" / > <Child v-bind:title="msg" :msg="msg2" :objData="fatherObj" /> <!-- 【2 】第2 步,再v-bind绑定ojbData为data里的fatherObj --> <button v-on:click="change_msg" >改变一下</button> </ div></template> <script> import Child from './ child' export default{ name:' Father', components:{ Child, }, data(){ return { msg:"父组件data内的动态的数据", msg2:' 父向子组件传递的第2 个数据', num:10, fatherObj:{//【1】第1步,设置一个字典的数据 name:' flying', age:22 } } }, methods:{ change_msg(event){ this.msg=' 改变一下msg消息' } } } </script> <style scoped> </style>
child.vue 【1】父组件传值是字典时,props的特殊写法
【1.1】此处数据类型必须设置为Object
【1.2】这里返回值”未知”、0等可随意,目的是如果父组件没有传对应的值,就用此默认的值
【2】显示父组件传过来的字典类型数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <template> <div> <h2>子组件:{{title}}--{{msg}}----{{age*2 }}</h2> <!-- 【2】显示父组件传过来的字典类型数据 --> <h3>子组件:父组件传的对象{{objData}}---名字是:{{objData.name}}</ h3> </div> </ template><script> export default { name:'child' , data(){ return {tit :'child' } }, props:{ title:[String ,Number ], msg:{ type:String , required:true }, age:{ type:Number , default :5 }, objData:{ type:Object , default :function ( ) { return { name:"未知" , age:0 , } } } } } </script> <style scoped> </ style>
效果: 子组件:父组件传的对象{ “name”: “flying”, “age”: 22 }—名字是:flying
三、子 -> 父组件通信——子传父 3.1简单的子—>父通信 第1步:child.vue 【0】此处通过点击鼠标触发的函数向父组件发消息 【1】重点:传数据给父组件:this.$emit(键名,键值); 键名随便,父组件接收时要对应;键值此处用data里数据:this.msg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <template> <div> <!-- 【0 】此处通过点击鼠标触发的函数向父组件发消息 --> <button v-on:click="sendMsg" >点此向父组件发消息</button> </ div></template> <script> export default{ name:'child', data(){ return{ msg:'子组件发的消息' } }, methods:{ sendMsg(event){ / *【1 】重点:固定写法:this .$emit(键名,键值); 键名随便。键值此处用data里数据:this .msg 父组件<child @sendmsg='处理函数' />接收时@sendmsg处要对应;(把sendmsg当成一个自定义事件) */ this.$emit("sendmsg",this.msg) } } } </ script><style> </style>
第2步,parent.vue 【1】用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到之后触发一个函数getMsg,用它来测试子组件发来的消息 [2]定义一个空数据用来接收子组件传来的消息 【3】把接收到的数据传给data里的msg 【4】展示子组件传过来的消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <template> <div> 父组件 <Child v-on:sendmsg='getMsg' /><!-- 【1 】把sendmsg当自定义事件,所以要用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到之后触发一个函数getMsg,用它来测试子组件发来的消息 --> {{msg}}<!-- 【4 】展示子组件传过来的消息 --> </div> </ template><script> import Child from './child' ; export default { name:'parent' , data(){ return { msg:'' } }, components:{ Child, }, methods:{ getMsg(data){ console .log(data); this .msg=data; } } } </script> <style> </ style>
效果:点击按钮之后,子组件即会发一个消息过来,父组件即接收,展示。
3.2父–>子–>父:父子组件的交互通信 parent.vue 【2.1】绑定data里的num(输入变<==>data.num变) 【2.2】把data的数据转换为Number类型,(this.num - 0,即是把此数据转为数字类型) 【2.3】向子组件传送的数据变为computed的toNum()函数处理后的值,即转为数字再传送给子组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <template> <div> 父组件 <!-- 【1 】用监听事件命令v-on(简写@sendmsg(此名随便写)),监听到自定义事件sedmsg发生之后触发一个函数getMsg,用它来接收子组件发来的消息; v-bind为向子组件发送的数据; --> <Child v-on:sendmsg='getMsg' v-bind:num='toNum' /> <!-- 【2.3 】向子组件传送的数据变为computed的toNum()函数处理后的值,即转为数字再传送给子组件 --> <input type="text" v-model="num" /> <!-- 【2.1 】绑定data里的num(输入变<==>data.num变) --> {{msg}}<!-- 【5 】展示子组件传过来的消息 --> </div> </ template><script> import Child from './child' ; export default { name:'parent' , data(){ return { msg:'' , num:5 , } }, components:{ Child, }, computed:{ toNum(){ return this .num - 0 ; } }, methods:{ getMsg(data){ console .log(data); this .msg=data; } } } </script> <style> </ style>
child.vue [2.1]接收父组件传来的数据num( ) 【2.2】触发发送函数,向父组件发送数据 【2.3】调用computed里的addNum对收到父组件的数据处理处理后,再发给父组件 【2.4】把props里收到的num进行处理的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 <template> <div> <!-- 【0 】此处通过点击鼠标触发的函数,sendMsg通过其向父组件发消息 --> <button v-on:click="sendMsg" >点此向父组件发消息</button> 【2.2】触发 </ div></template> <script> export default{ name:'child', data(){ return{ msg:'子组件发的消息' } }, props:{/ /接收父组件数据道具 num:{/ /[2.1]接收父组件传来的数据num(<child v-bind:num='toNum'/ >) type:Number , default :8 } }, computed:{ addNum(){ return this .num*10 ; } }, methods:{ sendMsg(event){ this .$emit("sendmsg" ,this .addNum) } }, } </script> <style> </ style>
效果:在输入框输入数字,子组件接收,处理后,发回父组件显示