欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

二、Vue 组件(component):组件之间相互参照,通过道具实现父子组件之间的数值传递

最编程 2024-07-03 22:53:01
...

一、组件各部分说明及互相引用

1.一个vue组件由三个部分组成
	Template
只能存在一个根元素
	2.Script
	3.Style
scoped:样式只在当前组件内生效

1.1 组件的基本引用代码示例

重点:第1步,app.vue;第2步,father.vue

0、src/main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'//【重点1】引入vue.js
import App from './App'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({//【重点】创建vue组件实例
  el: '#app', //[1]:在index.html里id为#app标签里写入组件内容
  components: { App },//[2]:写入的组件
  template: '<App/>' //[3]:写入的模板名(也可看成一个完整组件)
})

第1步,src/APP.vue引入子组件示例

<template>
  <div id="app">
     <img src="./assets/logo.png">
    <Father /> <!--2】第2步,调用子组件 -->
  </div>
</template>

<script>
import Father from './components/father' //【1】第1步,引入子组件

export default {
  name: 'App',
  components: {
    Father //【3】第3步,把组件写到此处,目的是把它暴露出去
  },

  data () {//【data必须是一个函数】此为标准es6写法,也可写成data:function(),这样才能对每个实例可以维护一份被返回对象的独立的拷贝
    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

<template>
  <div> <!-- 第一层只能有一个根标签 -->
    父组件
    <Child /> <!--2】第2步,调用子组件 -->
  </div>
</template>

<script>
 import Child from './child' //【1】第1步,引入子组件

  export default{//需要暴露出去的内容都要写在此处,这样才能被其它组件使用用
    name:'Father',//当前组件名
    components:{//【3】第3步,把组件写到此处,目的是把它暴露出去(其对应import xxx)中的xxx
      Child,
    },
    data(){//data必须是一个函数】此为标准es6写法,也可写成data:function(),这样每个实例可以维护一份被返回对象的独立的拷贝
      return{msg:'father'} //此处一定要记得return
    },

  }
</script>

<style scoped> /* [4]知识点4,此处写的样式只对当前father.vue组件生效 */
</style>

第3步,src/components/child.vue

<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)

<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、显示父组件传的内容:{{name}}

<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

<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内的动态的数据",//【1】数据里写一个属性:值;
        }
    },

  }
</script>

<style scoped>
</style>

child.vue

3、child里不变

<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,将自动传给子组件示例

<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

<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

<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

<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

<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=102)在这里插入图片描述

5.2 子组件用props把父组件传过来的数据[限定为多种数据类型]、[设置为必需选项]

【1】设置为支持多种数据类型 title:[String,Number],父组件传的title值可以为字符串,或数字
【2】设置为是否必须选项,如果父组件没有传msg=xx这个属性,就报错

msg:{//【2】设置为是否必须选项
        type:String,
        required:true
      }

原码:

<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
<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=10
在这里插入图片描述

6.父组件data数据为字典时,向子组件props传值

father.vue

【1】第1步,设置一个字典的数据
【2】第2步,再v-bind绑定ojbData为data里的fatherObj

<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】显示父组件传过来的字典类型数据

<template>
  <div>

    <h2>子组件:{{title}}--{{msg}}----{{age
																				
															

推荐阅读