Vue父子組件通信的三兩事(prop、emit)

組件是Vue核心功能之一,合理的組件化,可以減少我們代碼的冗餘,提高項目的可維護性。下面,我將由淺入深的講Vue的組件
在講之前,首先我們先了解一下組件的命名。
HTML是對特徵名不敏感的語言,他會將所有的字符全部轉換成小寫。我們命名了一個組件的名稱爲 nameTest ,然後再其他組件裏面引用 <nameTest> </nameTest> ,那麼我們將找不到這個組件,因爲這個組件一已經將名字轉換爲nametest

props : 父組件子組件 傳參

基本使用

Parent.vue

<template>
<div>
    parent:下面是我的子組件
    <childSon :userName='name'></childSon>
</div>
</template>
<script>
import childSon from './Childs'
export default {
    name:'Parent',
    components:{
        childSon
    },
    data(){
        return{ 
            name:'啊哈'
        }
    }
}
</script>

Childs.vue

<template>
<div>
    child:這是父組件給我傳的數據——{{userName}}
</div>
</template>
<script>
export default {
    name:'Childs',
    props:['userName'],
    data(){
        return{

        }
    }
}
</script>

props1

我們在 Parent.vue 組件裏面引用子組件 Childs.vue 然後傳入 userName 參數給子組件,Childs 在props裏面接收父組件傳傳來的數據。

上面的例子我們傳入的是一個字符串,其實,props可以傳入StringNumberObjectBoolenArray等數據類型。那麼我們在接受參數的時候就會有一個問題,我們怎麼知道接收的應該是字符串'12'還是數字12呢?
所以 Vue有一個 Prop驗證 的功能。

Prop 驗證

子組件在接受數據的時候,可以指定接收具體類型的數據、是否不能爲空,是否有默認值等。

Parent.vue

<template>
<div>
    parent:下面是我的子組件
    <childSon :name='name' :firstName='firstName' :age='18' ></childSon>
</div>
</template>
<script>
import childSon from './Childs'
export default {
    name:'Parent',
    components:{
        childSon
    },
    data(){
        return{ 
            name:'大衛',
            firstName:'大華'
        }
    }
}
</script>

Child.vue

<template>
<div>
     child:這是父組件給我傳的數據——name:{{name}}——firstName:{{firstName}}——lastName:{{lastName}}——age:{{age}}
</template>
<script>
export default {
    name:'Childs',
    props:{
        name: String,
        firstName: {
            type: String,//規定值的類型
            required: true //必須傳值,否則報錯
        },
        lastName: {
            type: String,
            default: 'lastNameDefault' //如果不傳值,則爲default的值
        },
        age: {
            type: [String,Number], //類型可以是多種
            validator: function(value) { //自定義驗證

                let num = parseInt(value)
                if (num > 0 && num <100) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    },
    data(){
        return{

        }
    }
}
</script>

運行結果如下圖:
prop驗證

如果我們將條件改變的時候,name 傳入一個數組,firstName 不傳值,age 傳入一個不能轉換爲數字的值。

 <childSon :name=[11]  age='ss' ></childSon>

運行結果如下圖:
驗證1
驗證2
驗證3
驗證4
根據我們的驗證規則,name 必須爲一個String 類型,所以控制檯報錯:希望得到一個String,得到了一個數組;firstName 爲一個必填的值,但是我們沒有傳值,所以報錯;age要爲一個可以轉換成數字的值,但是我們穿了"ss",會經過我們自定義的驗證,然後拋錯。

Prop傳入對象

如果我們要將一個 對象 的所有屬性全部傳給子組件,我們不需要將屬性一個個的作爲Prop傳遞,只需要將整個對象傳遞過去就可以。

Parent.vue

template>
<div>
    parent:下面是我的子組件
    <childSon v-bind='obj' ></childSon>
</div>
</template>
<script>
import childSon from './Childs'
export default {
    name:'Parent',
    components:{
        childSon
    },
    data(){
        return{ 
            obj: {
                name: 'lily',
                age: '16'
            }
        }
    }
}
</script>

Childs.vue

<template>
<div>
    child:這是父組件給我傳的數據——name:{{name}}——age:{{age}}
</div>
</template>
<script>
export default {    
    name:'Childs',
    props:{
        name: String,
        age: {
            type: [String,Number], //類型可以是多種
            validator: function(value) { //自定義驗證

                let num = parseInt(value)
                if (num > 0 && num <100) {
                    return true;
                } else {
                    return false;
                }
            }
        }
    }
}
</script>

運行結果如下圖:
object
我們傳入一個 obj 對象,然後在子組件裏面可以拿到對象的所有屬性。

Prop的單向數據傳遞

直接作爲一個本地變量

Parent.vue

<template>
<div>
    parent:<input type='text' v-model="content">下面是我的子組件 
    <childSon :content='content' ></childSon>
</div>
</template>
<script>
import childSon from './Childs'
export default {
    name:'Parent',
    components:{
        childSon
    },
   data() {
    return {
      content:'er'
    };
  },
}
</script>

Childs.vue

<template>
<div>
    child:這是父組件給我傳的數據——{{con}}
</div>
</template>
<script>
export default {    
    name:'Childs',
    props:['content'],
    data(){
        return{
           con:this.content
        }
    }
}
</script>

運行結果如下圖:
prop

emit :子組件父組件 傳遞數據

基本使用

子組件父組件傳遞數據,不能像上面一樣實時的傳遞數據,必須通過 事件 觸發。我們通過 $emit 方法來向父子間傳遞數據,第一個參數爲事件的 名稱 ,第二個爲傳遞的 數據 ,是一個可選的參數。父組件必須監聽同樣的事件名稱才能監聽到我們的這個事件,事件拋出的值必須通過 $event或者通過一個方法來訪問。

**Parent.vue

<template>
<div>
    parent:這是我的子組件傳給我的值:{{num}}
    <childSon :content='content' @getNum='getMsg'></childSon>
</div>
</template>
<script>
import childSon from './Childs'
export default {
    name:'Parent',
    components:{
        childSon
    },
   data() {
    return {
      content:'er',
      num:''
    }
  },
  methods:  {
      getMsg(num){
          this.num = num;
      }
  }
}
</script

Childs.vue

<template>
<div>
    child:這是父組件給我傳的數據——{{content}} <br />
    <button @click="sendMsgtoParent">點擊我可以向父子間傳遞參數哦</button>
</div>
</template>
<script>
export default {    
    name:'Childs',
    props:['content'],
    data(){
        return{
            num: 0
        }
    },
    methods: {
        sendMsgtoParent(){
            this.$emit('getNum',this.num ++ );
        }
    }
}
</script>

運行結果如下圖:
emit基礎用法
子組件定義了一個num變量,然後點擊按鈕觸發method,通過 $emit向父組件發送事件的名稱(getNum)和一個參數(this.num),然後 父組件 監聽事件getNum,然後將傳遞值賦值給父組件的一個屬性上,這樣就可以是實現子組件點擊一次按鈕,就向父組件發送一次數據。更多實例可以參考官網

組件間的數據雙向綁定

我們知道我們可以使用v-model來實現數據的雙向綁定。但是如果這個數據是跨組件的話,我們要怎樣實現綁定嗎?

首先我們先要明白v-model的原理。v-model其實是分爲兩個方面,一方面數據層的改變引起視圖層的變化,我們可以使用v-bind來實現,另一方面視圖層的變化引起數據層的變化我們可以監聽事件來實現。所以我們想要雙向綁定一個數據,只需要這兩步操作。具體實現參考官網

彈框嵌套表格組件化使用

(待續...)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章