二、Vue組件(component):組件的相互引用、通過props實現父子組件互傳值


一、組件各部分說明及互相引用

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*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:{//【1】父組件傳值是字典時,props的特殊寫法
        type:Object, //【1.1】此處數據類型必須設置為Object
        default:function(){
          return{//【1.2】這里返回值"未知"、0等可隨意,目的是如果父組件沒有傳對應的值,就用此默認的值
            name:"未知",
            age:0,
          }
        }
      }
    }
  }
</script>

<style scoped>
</style>

效果:
子組件:父組件傳的對象{ "name": "flying", "age": 22 }---名字是:flying

三、子 -> 父組件通信——子傳父

3.1簡單的子--->父通信

第1步:child.vue

【0】此處通過點擊鼠標觸發的函數向父組件發消息
【1】重點:傳數據給父組件:this.$emit(鍵名,鍵值); 鍵名隨便,父組件接收時要對應;鍵值此處用data里數據:this.msg

<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】展示子組件傳過來的消息

<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:'' //[2]定義一個空數據用來接收子組件傳來的消息
      }
    },
    components:{
      Child,
    },
    methods:{
      getMsg(data){//此處data可隨便寫,下面和其對應即可
        console.log(data); //測試【3】把子組件傳的數據輸出到控制台
        this.msg=data;//【3】把接收到的數據傳給data里的msg
      }
    }
  }
</script>

<style>
</style>

效果:點擊按鈕之后,子組件即會發一個消息過來,父組件即接收,展示。
在這里插入圖片描述

3.2父-->子-->父:父子組件的交互通信

parent.vue

【2.1】綁定data里的num(輸入變<==>data.num變)
【2.2】把data的數據轉換為Number類型,(this.num - 0,即是把此數據轉為數字類型)
【2.3】向子組件傳送的數據變為computed的toNum()函數處理后的值,即轉為數字再傳送給子組件

<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:'', //[3]定義一個空數據用來接收子組件傳來的消息
        num:5,
      }
    },
    components:{
      Child,
    },
    computed:{
      toNum(){//【2.2】把data的數據轉換為Number類型,(this.num -0,即是把此數據轉為數字類型)
        return this.num - 0;
      }
    },
    methods:{//【2】用函數來接收子組件消息輸出到控制台進行測試
      getMsg(data){
        console.log(data);
        this.msg=data;//【4】把接收到的數據傳給data里的msg
      }
    }
  }
</script>

<style>
</style>

child.vue

[2.1]接收父組件傳來的數據num(
【2.2】觸發發送函數,向父組件發送數據
【2.3】調用computed里的addNum對收到父組件的數據處理處理后,再發給父組件
【2.4】把props里收到的num進行處理的函數

<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(){//【2.4】把props里收到的num進行處理的函數
        return this.num*10;
      }
    },
    methods:{
      sendMsg(event){
        //【1】重點:固定寫法:this.$emit(鍵名,鍵值); 鍵名隨便,父組件接收時要對應;鍵值此處用data里數據:this.msg
        this.$emit("sendmsg",this.addNum) //【2.3】調用computed里的addNum對收到父組件的數據處理處理后,再發給父組件
      }
    },

  }
</script>

<style>
</style>

效果:在輸入框輸入數字,子組件接收,處理后,發回父組件顯示
在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM