Vue元件化常用方法之元件傳值與通訊
相關知識點
- 父元件傳值到子元件
- 子元件傳值到父元件
- 兄弟元件之間傳值
- 祖代和後代之間傳值
- 任意兩個元件之間傳值
父元件傳值到子元件
父元件傳值到子元件基本方法有三個,分別為:
- 屬性 props
- 引用 $refs
- 子元素 $children
日常開發中,我們用到 props 和 $refs 頻率比較多,$children 相對較少些(我就沒怎麼使用過~)。
屬性 props
在父元件中新增屬性,在子元件中接收使用,例如:
父元件:
<HelloWorld msg="Welcome to Your vue.js App" />
子元件:
<h1>{{ msg }}</h1> props: { msg: String }
引用 $refs
在父元件中可以使用 this.$refs.xxx 獲取子元件中定義的資料或者方法,並使用。
父元件:
<HelloWorld ref="hw" /> mounted() { this.$refs.hw.foo = "bar"; }
子元件:
http://www.cppcns.com<p>{{ foo }}</p> data() { return { foo: "foo" }; }
注意事項:
this.$refs.xxx 不能在 created 生命週期中使用,因為真實的 DOM 還沒有掛載完畢,如果非要想,可以使用 vm.$nextTick 來訪問 DOM。或者也可以這樣理解,父元件先於子元件建立,在父元件的 created 生命週期中子元件還沒有建立,所以獲取不到子元件。
在 Vue 中元件生命週期呼叫順序如下:
組建的呼叫順序都是 先父後子,渲染完成的順序是 先子後父
元件的銷燬操作是 先父後子,銷燬完成的順序是 先子後父
載入渲染過程
- 父 beforeCreate
- 父 created
- 父 beforeMount http://www.cppcns.com
- 子 beforeCreate
- 子 created
- 子 beforeMount
- 子 mounted
- 父 mounted
子元件更新過程
- 父 beforeUpdate
- 子 beforeUpdate
- 子 updated
- 父 updated
父元件更新過程
- 父 beforeUpdate
- 父 updated
銷燬過程
- 父 beforeDestroy
- 子 beforeDestroy
- 子 destroyed
- 父 destroyed
created() { console.log("第一個執行"); console.log(this.$refs.hw); // undefined this.$nextTick(() => { console.log("第三個執行"); console.log(this.$refs.hw); // 此時可以獲取到 }); } mounted() { console.log("第二個執行"); this.$refs.hw.foo = "bar"; }
子元素 $children
父元件:
this.$children[0]oKvMJgVf.xx = "xxx";
注意事項:
$children 獲取當前例項的直接子元件。如果父元件中存在多個子元件,需要注意 $children 並不保證順序,也不是響應式的。
子元件傳值到父元件
子元件傳值到父元件使用的方法是自定義事件。在子元件中派發,在父元件中監聽。
注意事項: 事件的派發者是誰,事件的監聽者就是誰,只不過宣告的時候宣告在父元件中了。
分為三種情況:不傳遞引數、傳遞一個引數、傳遞多個引數。
不傳遞引數
子元件:
this.$emit('childFoo');
父元件:
<HelloWorld2 @childFoo="onChildFoo"></HelloWorld2> methods: { onChildFoo() { console.log("====== onChildFoo ========"); } }
傳遞一個引數
在父元件中使用 $event 接收引數。
子元件:
this.$emit('childFooSingle','foo');
父元件:
<HelloWorld2 @childFooSingle="onChildFooSingle($event)"></HelloWorld2> methods: { onChildFooSingle(e) { console.log(e); // foo } }
傳遞多個引數
在父元件中使用 arguments 接收引數,會以陣列的形式傳遞。
子元件:
this.$emit('childFooMultiple','foo','bar','dong');
父元件:
<HelloWorld2 @childFooSingle="onChildFooMultiple(arguments)"></HelloWorld2> methods: { onChildFooMultiple(msg) { console.log(msg[0]); // foo console.log(msg[1]); // bar console.log(msg[2]); // dong } }
兄弟元件之間傳值
兄弟元件之間傳值可以通過共同的父輩元件搭橋進行傳遞,例如:$parent、$root。
兄弟元件1:
this.$parent.$on('foo',handle);
兄弟元件2:
this.$parent.$emit('foo');
祖代和後代之間傳值
由於元件巢狀層數過多,使用 props 進行傳遞不切實際,vue 提供了 provide/inject API 完成該任務。
provide/inject 能夠實現祖先給後代傳值。
祖代:
provide() { return {foo: 'foo'} }
後代:
inject: ['foo']
注意:provide 和 inject 主要為高階元件/元件庫提供用例,並不推薦直接用於應用程式程式碼中,我們更多會在開源元件庫中見到。但是,反過來想要後代給祖代傳值,這種方案就不行了!!!
官方提示:provide 和 inject 繫結並不是響應式的。這是刻意為之的。然而,如果你傳入了一個可監聽的物件,那麼其物件的 property 還是可響應式的。
祖代:
provide() { return { dong: this.home }; },data() { return { home: ["App home"] }; }
後代:
inject: ["dong"] this.dong = ["App data"]; // 會報錯,Avoid mutating an injected value directly since the changes will be overwritten whenever the provided component re-renders this.dong.push("App data"); // 可以修改成功
任意程式設計客棧兩個元件之間傳值
任意兩個元件之間傳值有兩種方案:事件匯流排、Vuex。
事件匯流排
建立一個 Bus 類負責事件派發、監聽和回撥管理。
首先建立一個 bus.js,並在 main.js 中引入,然後在元件中使用:
第一步:新建 plugins/bus.jswww.cppcns.com
class Bus{ constructor(){ this.callbacks = {} } $on(name,fn){ this.callbacks[name] = this.callbacks[name] || [] this.callbacks[name].push(fn) } $emit(name,args){ if(this.callbacks[name]){ this.callbacks[name].forEach(cb => cb(args)) } } } export default Bus;
第二步:main.js 中引入
import Bus from "./plugins/bus"; Vue.prototype.$bus = new Bus()
第三步:在元件中使用
元件1:
this.$bus.$on('foo',handle)
元件2:
this.$bus.$emit('foo')
Vuex
建立唯一的全域性資料管理者 store,通過它管理資料並通知元件狀態變更。可以自行先了解一下官方文件Vuex,具體詳細使用後續會寫一個專題~
總結
到此這篇關於Vue元件化常用方法之元件傳值與通訊的文章就介紹到這了,更多相關Vue元件傳值與通訊內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!