父組件能夠將一條數據傳遞給子組件,這條數據能夠是動態的,父組件的數據更改的時候,子組件接收的也會變化。前端
子組件被動的接收父組件的數據,子組件不要再更改這條數據了。vue
組件實例的做用域是孤立的,父組件不能直接使用子組件的數據,子組件也不能直接使用父組件的數據。
父組件在調用子組件的時候給子組件傳遞數據:vuex
<template id="father"> <div class="father"> <p>我是父組件,這是個人fMsg:{{fMsg}}</p> <input type = "text" v-model = "fMsg"> <hr> <son msg = "你好"></son> </div> </template>
父組件給子組件傳遞數據的時候,子組件須要利用props的屬性來肯定本身的預期數據,若是兒子沒有經過props屬性接受傳遞過來的數據,則數據會以自定義屬性的方式,放在兒子最外層的根元素上面。api
子組件經過props來接受父組件傳遞過來的數據,而且經過{{msg}}使用數組
components:{ son:{ template:"<div>我是son子組件!這是父組件傳遞給個人msg:{{msg}}</div>", //接收父組件傳遞來的屬性 msg props:["msg"] } }
咱們能夠用 v-bind 來動態地將 prop 綁定到父組件的數據。每當父組件的數據變化時,該變化也會傳導給子組件。app
<template id="father"> <div class="father"> <p>我是父組件,這是個人fMsg:{{fMsg}}</p> <input type = "text" v-model = "fMsg"> <hr> <!-- <son msg = "你好"></son> --> <son :msg = "fMsg"></son> </div> </template>
若是若是父組件傳遞屬性給子組件的時候鍵名有'-'dom
<son :f-msg = "fMsg"></son>
子組件接收、使用的時候寫成小駝峯的模式函數
components:{ son:{ template:"<div>我是son子組件!這是父組件傳遞給個人msg:{{fMsg}}</div>", //接收父組件傳遞來的屬性 msg props:["fMsg"] } }
咱們能夠爲組件的 prop 指定驗證規則。若是傳入的數據不符合要求,Vue 會發出警告。這對於開發給他人使用的組件很是有用
驗證主要分爲:類型驗證、必傳驗證、默認值設置、自定義驗證工具
// 類型驗證 // num:Number //父組件傳遞過來的num必須是Number類型 // 添加多個類型 num: [Number,String],
規定傳遞過來的數值類型必須是number,不然系統會報錯ui
規定父組件必須給子組件傳遞該值
//必傳驗證 // num:{ // required: true // }
當父組件不給子組件傳遞該值的時候,給子組件設定一個默認值
// 默認值設置 // num:{ // default:100 // }
//自定義驗證 num:{ validator(val){ return val > 100 } }
規定傳遞過來的數值必需要大於100,不然系統會報錯
單向數據流
Prop 是單向綁定的:當父組件的屬性變化時,將傳遞給子組件,可是反過來不會。這是爲了防止子組件無心間修改了父組件的狀態,來避免應用的數據流變得難以理解。
<template id="father"> <div class="father"> <input type = "text" v-model = "message"> <hr> <son :message = "message"></son> </div> </template> <template id = "son"> <div> <p>這是子組件</p> <input type = "text" v-model = "message"></input> </div> </template>
另外,每次父組件更新時,子組件的全部 prop 都會更新爲最新值。這意味着你不該該在子組件內部改變 prop。若是你這麼作了,Vue 會在控制檯給出警告。
因此若是咱們想實現父子間的數據共享,依靠的就是應用類型的地址傳遞,應將message寫成對象的形式,傳遞的時候將對象傳遞給子組件,子組件引用的時候使用對象的value值。
<template id="father"> <div class="father"> <input type = "text" v-model = "message.value"> <hr> <!-- 傳遞的時候將對象傳遞給子組件 --> <son :message = "message"></son> </div> </template> <template id = "son"> <div> <p>這是子組件</p> <!-- 引用的時候使用對象的value值 --> <input type = "text" v-model = "message.value"></input> </div> </template>
這時候更改父組件的value值,子組件的數據同步更改,子組件修改value值的時候也同步修改了父組件的數據。這是由於不論是子組件仍是父組件,咱們操做的都是同一個對象,父組件直接把引用類型的地址傳遞給子組件,子組件沒有直接修改對象,只是更改了裏面的屬性值。
父組件若是將一個引用類型的動態數據傳遞給子組件的時候,數據會變成雙向控制的,子組件改數據的時候父組件也能接收到數據變化,由於子組件改的時候不是在改數據(地址),而是在改數據裏的內容,也就是說引用類型數據的地址始終沒有變化,不算改父組件數據。
注意:在 JavaScript 中對象和數組是引用類型,指向同一個內存空間,若是 prop 是一個對象或數組,在子組件內部改變它會影響父組件的狀態。 message:{val:""}
$父子間數據共享(雙向控制),基本不會使用,違背了單向數據流(父=》子)$
在組件間能夠用過ref造成ref鏈,組件還擁有一個關係鏈($parent),經過這兩種鏈;理論來講,任意的兩個組件均可以互相訪問,互相進行通訊。
$parent:父組件
$children:子組件
$root:根組件
當子組件在set方法中修改父組件傳遞過來的值時,系統會報錯,由於子組件不能修改父組件的數據。
Vue.component("bbb",{ template:"#bbb", props:["msg"], computed:{ /* ownMessage(){ return this.msg; } */ ownMessage:{ get(){ return this.msg; }, set(val){ this.msg = val //系統報錯:子組件不能更改父組件傳遞的數據 } } } })
因此這時候要使用$parent,讓父組件本身更改本身的數據
set(val){ // this.msg = val //系統報錯:子組件不能更改父組件傳遞的數據 // console.log(this) // 至關於父組件本身更改了msg數據 this.$parent.msg = val; }
父組件在調用子組件的時候使用ref作標記
<template id="aaa"> <div> <button @click = "get">點擊獲取bbb數據</button> <!-- 組件間不只能夠用過$root/$parent/$children來獲取對應關係的組件,父組件還能夠主動的經過ref爲子組件作標記 --> <bbb ref = "b"></bbb> </div> </template>
父組件的this屬性上有$refs標記,經過refs標記拿到子組件
// 經過ref標記更改子組件的數據 // this.$refs.b.message = "哈哈"
組件間不只能夠用過$parent/children/root來獲取對應關係的組件,父組件還能夠主動的經過ref爲子組件作標記 也能夠給dom作標記,也會造成ref鏈,也能夠交互.
<button ref="btn" @click="get">get</button> <bbb ref="b></bbb>
注意多個子組件標記的是同一個鍵名,獲取到的應該是一個數組
<bbb ref = "b" v-for = "(item,index) in 3" :key = "index"></bbb>
// 經過下標修改對應的數值 this.$refs.b[0].message = "哈哈"
運行效果:
父組件能夠將更改自身數據的方法傳遞給子組件,子組件調用這個方法的時候,就能夠給父組件傳遞數據,父組件被動的接收子組件的數據。
子組件聲明一條自身的msg
Vue.component("son",{ template:"#son", // 子組件接收父組件傳遞過來的方法 props:["change"], data(){ return{ msg:"我是子組件" } } })
父組件先聲明一條本身的數據
data(){ return{ // 父組件先聲明一條本身的數據 parentMsg:"" } }
再寫一個能夠更改自身數據的方法
methods:{ // 寫一個能夠更改自身數據的方法 change(msg){ this.parentMsg = msg } }
將寫好的change方法傳遞給子組件
<template id="father"> <div> <p>這是父組件</p> <p>子組件傳遞過來的值是:{{parentMsg}}</p> <hr> <!-- 調用子組件的時候,將更改自身數據的方法傳遞給子組件 --> <son :change = "change"></son> </div> </template>
子組件經過props接收父組件傳遞過來的change方法
props:["change"]
給p標籤添加點擊事件,點擊即觸發change方法,同時將自身的msg傳遞給父組件,至關於父組件的change方法被執行。
<template id="son"> <div> <p>子組件說:{{msg}}</p> <p @click = "change(msg)">點擊我觸發父親的change方法</p> </div> </template>
父組件能夠在頁面中渲染子組件傳遞過來的數據
<p>子組件傳遞過來的值是:{{parentMsg}}</p>
運行效果:
每個組件或者實例都會有自定義事件,和觸發事件的能力,父組件給子組件綁定一個自定義事件,這個事件的處理程序倒是父組件的一個方法,當子組件觸發這個事件的時候,至關於父組件的方法被執行。
父組件想獲取子組件的數據時,在調用子組件的時候給子組件綁定一個自定義事件change-event
<template id="father"> <div> <p>這是父組件</p> <p>子組件傳遞過來的值是:{{parentMsg}}</p> <hr> <!-- 給子組件綁定一個自定義事件 --> <son @change-event = "change"></son> </div> </template>
在子組件中定義一個點擊事件,點擊p標籤執行changeWord方法
<p @click = "changeWord">點擊我觸發父親的change方法</p>
在方法中編寫changeWord方法,經過this.$emit來觸發綁定在本身身上的自定義事件,第一個參數爲事件名稱change-event,第二個參數爲觸發這個函數的時候給他傳遞的數值:自身的msg。
methods:{ changeWord(){ //觸發自身綁定的change事件 this.$emit("change-event",this.msg)//第一個參數爲觸發事件的名字,第二個參數爲觸發這個函數的時候給他傳遞的數值 } }
一旦觸發綁定在自身上的自定義事件,至關於父組件的change方法被執行。
定義哥哥組件,給哥哥組件添加一個點擊事件,點擊觸發hitLittle方法
<template id = "big-brother"> <div> <p>我是哥哥</p> <button @click = "hitLittle">打弟弟</button> </div> </template>
定義弟弟組件,給弟弟組件添加一個p標籤,由crying數據控制其顯示與隱藏
<template id="little-brother"> <div> <p>我是弟弟</p> <p v-if = "crying">嗚嗚嗚</p> </div> </template>
在弟弟組件的data中聲明crying數據,默認爲false
Vue.component("little-brother",{ template:"#little-brother", data(){ return{ crying:false } } })
在哥哥組件的methods中定義hitLittle方法,經過viewmodel關係鏈更改弟弟組件中的crying方法
Vue.component("big-brother",{ template:"#big-brother", methods:{ hitLittle(){ //在兄弟組件之間的通訊,能夠採用關係鏈和ref鏈去使用,解決兄弟之間通訊問題。 this.$parent.$children[1].crying = true;//讓littel改變自身的crying狀態 } } })
運行效果:
在弟弟組件中添加ref標記
<little-brother ref = "little"></little-brother>
在哥哥組件的hitLittle方法中經過viewmodel和ref鏈配合使用更改弟弟組件中的crying數據
hitLittle(){ //在兄弟組件之間的通訊,能夠採用關係鏈和ref鏈去使用,解決兄弟之間通訊問題。 // this.$parent.$children[1].crying = true;//讓littel改變自身的crying狀態 //viewmodel鏈和ref鏈配合使用 this.$parent.$refs.little.crying = true; }
建立一個空的實例
var angle = new Vue();
弟弟組件本身定義一個更改自身狀態的方法
methods:{ cry(){ this.crying = true } }
在mounted生命週期函數中綁定一個自定義事件,第一個參數爲自定義事件名,第二個函數爲須要處理的函數
mounted(){ // 綁定一個自定義事件,第一個參數爲自定義事件名,第二個函數爲須要處理的函數 angle.$on("hit-little",this.cry) }
在哥哥組件中觸發自定義事件
hitLittle(){ //觸發little-brother組件的hit-little事件 angle.$emit("hit-little") }
vuex是vue提供的一個全局的狀態管理工具,主要處理項目中多組件間狀態共享。
Vuex是vue官方的一款狀態管理工具,什麼是狀態呢?咱們在前端開發中有一個概念:數據驅動,頁面中任意的顯示不一樣,都應該有一條數據來控制,而這條數據又叫作state,狀態。
在vue中。組件間進行數據傳遞、通訊很頻繁,而父子組件和非父子組件的通訊功能也比較完善,可是,惟一困難的就是多組件間的數據共享,這個問題由vuex來處理
(1)建立store
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
(2)設置state
state就是一個純對象,上面有一些狀態掛載
state: { num:0, name:"list" }
(3)在根實例裏配置store
這樣,咱們就能夠在任意的組件中經過this.$store來使用關於store的api
import store from './store/index' Vue.config.productionTip = false new Vue({ router, store, render: h => h(App) }).$mount('#app')
(4)在Home組件中使用state
computed:{ ...mapState({ num:state=>state.num }) },
(5)使用mutations更改state
mutations也是一個純對象,裏面包含不少更改state 的方法,這些方法的形參接收到state,在函數體裏更改,這時,組件用到的數據也會更改,實現響應式。
mutations: { changeNum(state){ state.num++ } }
(6)在組件中調用mutations方法,更改組件中的state。
//使用vuex提供的mapMutations幫助咱們在組件中調用mutations方法 ...mapMutations(["changeNum"]), //給按鈕添加點擊事件 <button @click = "changeNum">點擊更改num值</button>
運行效果: