每個.vue 文件就是一個 組件,組件和組件相互組合,就成了一個應用,這就涉及到的組件和組件之間的通訊,最經常使用的就是父子之間的通訊。在vue 中, 在一個組件中經過 import 引入另外一個組件,這個組件就是父組件,被引入的組件就是子組件。html
【一】父組件→子組件vue
(1)父組件傳遞數據vuex
在vue-cli 項目中,src 文件夾下有一個App.vue 文件,它的script標籤中vue-cli
import HelloDemo from './components/HelloDemo'
那麼 App.vue 就是父組件,components 文件夾下的HelloDemo.vue 就是子組件。父組件經過props 向子組件傳遞數據,子組件經過自定義事件向父組件傳遞數據。數組
父組件向子組件傳值, 它主要是經過元素的屬性進行的. 在App.vue 的template中,有一個 dom
<hello-demo></hello-demo>
這就是咱們引入的子組件. 給其添加屬性如函數
<hello-demo :mes-father="mesFather"></hello-demo>
父組件數據mesFather爲ui
return { 'mesFather':'message from father,我是來自父組件的數據' }
父組件將數據傳遞進去,子組件須要接收才能使用. 怎樣接收呢?this
(2)子組件接收數據spa
在HelloDemo.vue 中, export default 後面的對象中,添加一個字段props, 它是一個數組, 專門用來接收父組件傳遞過來的數據. props: ["mesFather"], 這裏定義了mesFather 字符串, 和父組件中定義的元素的屬性一一對應。
export default{ props:['mesFather'] }
可是咱們在父組件,就是在 <hello-demo> 元素中定義的屬性是mes-father, 沒有一一對應啊? 這主要是由於,在html 元素中大小寫是不敏感的。
若是咱們寫
<hello-demo :mesFather="mesFather"></hello-demo>
裏面的mesFather 就會轉化成mesfather, 至關於咱們向子組件傳遞了一個mesfather數據, 若是在js 文件中,咱們定義 props: ["mesFather"],咱們是接受不到數據的,由於js 是區分大小寫的, 因此只能寫成props: ["mesfather"]。
可是在js 文件中,像這種兩個單詞拼成的數據,咱們習慣用駝峯命名法,因此vue 作了一個轉化,若是在組件中屬性是 - 表示,它 自動會轉化成駝峯式。 傳進來的數據是mes-father, 轉化成mesFather, 咱們在js 裏面寫mesFather, 一一對應,子組件能夠接受到組件。 props 屬性是和data, methods 屬性並列的,屬同一級別。 props 屬性裏面定義的變量,在 子組件中的template 中能夠直接使用。
App.vue 的template 更改以下:
①<hello-demo :mes-father="mesFather"></hello-demo> ②import HelloDemo from './components/HelloDemo' export default{ name: 'App',
data(){
return {
'mesFather':'message from father,我是來自父組件的數據'
}
},
③components: {HelloDemo}
}
HelloDemo.vue組件:
<template> <div> <h1>Hello頁面</h1> ①<p>{{mesFather}}</p> </div> </template> <script> export default{ ②props:['mesFather'] } </script>
這時,在頁面中看到 ‘message from father,我是來自父組件的數據’ 字樣,父元素向子元素傳遞數據成功。
【二】子組件→父組件
子組件向父組件傳遞數據,須要用到自定義事件。 例如,咱們在HelloDemo.vue ,寫入一個input, 接收用戶輸入,咱們想把用戶輸入的數據傳給父組件。這時,input 須要先綁定一個keypress 事件,獲取用戶的輸入,同時還要發射自定義事件,如valueUp, 父組件只要監聽這個自定義事件,就能夠知道子組件要向他傳遞數據了。子組件在發射自定義事件時,還能夠攜帶參數,父組件在監聽該事件時,還能夠接受參數,參數就是要傳遞的數據。
在 HelloDemo.vue的template中,添加一個input輸入框,給它一個v-model 獲取用戶的輸入,再添加keypress的事件,用於發射事件和傳輸數據。script 中添加data,定義變量來獲取用戶的輸入,添加methods 來處理keypress事件的處理函數enter, 整個HelloDemo.vue 文件以下
(1)子組件發射事件和傳輸數據
<template> <div style="margin: 10px;border: 1px solid red;padding: 10px;background: rgba(0,0,0,0.3)"> <h1>Hello頁面</h1> <p>{{message}}</p> <p>{{mesFather}}</p> 子組件輸入框:<input type="text" placeholder="請輸入..." v-model="inputValue" v-on:keypress.enter="enterFn"/> 輸入元素僞:{{inputValue}} </div> </template> <script> export default{ props:['mesFather'], data(){ return { message:'我是Hello本頁面展現信息', inputValue:''// 添加inputValue,用戶輸入綁定到inputValue變量,從而獲取用戶輸入 } }, methods:{ enterFn(val){ this.$emit('valueUp',this.inputValue); //子組件發射自定義事件valueUp, 並攜帶要傳遞給父組件的值 //若是要傳遞給父組件不少值,這些值要做爲參數依次列出 如 this.$emit('valueUp', this.inputValue, this.mesFather); } } } </script>
結果:
(2)父組件監聽發射事件和展現接收數據
在App.vue 中, template中hello-demo組件綁定一個自定義事件,@valueUp =「receive」, 用於監聽子組件發射的事件,再寫一個 p 元素,用於展現子組件傳遞過來的數據,<p>子組件傳遞過來的數據 {{ childMes }}</p>
相應地,在scrpit中,data 中,定義一個變量childMes, 並在 methods 中,定義一個事件處理函數reciever。整個App.vue修改以下:
<!--添加自定義事件valueUp-->
<hello-demo :mes-father="mesFather" v-on:valueUp="recieve"></hello-demo> <!-- p元素,用於展現子組件傳遞過來的數據 -->
<p>子組件傳遞過來的數據 {{childMes}}</p> import HelloDemo from './components/HelloDemo' export default{ name: 'App', data(){ return { 'mesFather':'message from father,我是來自父組件的數據', childMes:'' } }, components: {HelloDemo}, methods:{ recieve(mes){ // recieve 事件須要設置參數,這些參數就是子組件傳遞過來的數據,所以,參數的個數,也要和子元素傳遞過來的一致。 this.childMes = mes; } } }
這時在input中輸入內容,而後按enter鍵,就以看到子組件傳遞過來的數據,子組件向父組件傳遞數據成功。
結果:
(3)分析:
①子組件input發射事件
<input type="text" placeholder="請輸入..." v-model="inputValue" v-on:keypress.enter="enterFn"/>
當在input輸入框中輸入數據,並按enter鍵時,它會觸發keypress.enter事件,從而調用事件處理函數enterFn
在enterFn 中, 咱們發射了一個事件valueUp, 並攜帶了一個參數
methods:{ enterFn(val){ this.$emit('valueUp',this.inputValue); //子組件發射自定義事件valueUp, 並攜帶要傳遞給父組件的值 //若是要傳遞給父組件不少值,這些值要做爲參數依次列出 如 this.$emit('valueUp', this.inputValue, this.mesFather); } }
②父組件監聽事件、接收展現數據
<hello-demo :mes-father="mesFather" v-on:valueUp="recieve"></hello-demo>
因爲在父組件中, 咱們綁定valueUp 事件,因此父組件在時刻監聽valueUp 事件, 當子組件發射value 事件時,父組件馬上捕獲到,並當即調用它的回調函數receive, 在receive 中,咱們獲取到子組件傳遞過來的數據,並賦值了父組件data 中的變量childMes, 因爲data 數據發生變化,從而觸發dom更新,頁面中就顯示子組件傳遞過來的內容。
<!-- p元素,用於展現子組件傳遞過來的數據 --> <p>子組件傳遞過來的數據 {{childMes}}</p> data(){ return { childMes:'' } }
(4)props驗證
在子組件中, props 最好的寫法是props 驗證,咱們在子組件HelloDemo.vue中寫 props:['mesFather'], 只是表達出,它接受一個參數mesFather, 若是寫成props 驗證,不只能表達出它須要什麼參數,還能表達參數類型,而且若有錯誤,vue 會作出警告。如今把props 改爲props 驗證的寫法, HelloDemo.vue 中的js中的props修改以下:
props:{ 'mesFather':{ type: String, default: 'from father來自父級的數據', required:true } }
若是是組件與組件之間的通訊很是複雜,不光是父子組件,還有兄弟組件,那就須要用到狀態管理vuex,稍後講解。
.