Vue頁面、元件之間傳參方式繁多,此處羅列出常用的幾種方式,歡迎審閱補充。
一丶路由傳參
這裡的路由傳參以程式設計式router.push(...)
為例,宣告式<router-link :to="...">
與之類似。此處模擬情景為從componentsA.vue
頁面跳轉到componentsB.vue
頁面傳參。首先,路由配置資訊如下:
router.js
import Vue from 'vue'
import Router from 'vue-router'
import componentsA from './components/componentsA' //在components下建立componentsA.vue
import componentsB from './components/componentsB' //在components下建立componentsB.vue
Vue.use(Router)
export default new Router({
routes:[
{
path:'/componentsA',
name:'componentsA',
component:componentsA
},
{
path:'/componentsB',
name:'componentsB',
component:componentsB
}
]
})複製程式碼
1.1 路由配置傳參
首先確定自己要傳的引數名,將路由配置修改一下,傳name,age,sex三個引數:
{
path:'/componentsB/:name/:age/:sex',
name:'componentsB',
component:componentsB
}複製程式碼
在componentsA.vue
頁面通過this.$router.push
配置與之對應的引數:
componentsA.vue
<template>
<div>
<div>我是元件A</div>
<button @click='routerToB1'>方式一跳轉到元件B</button>
</div>
</template>
<script>
export default{
data(){
return{
person:{name:'Gene',age:'18',sex:'male'}
}
},
methods: {
routerToB1() {
this.$router.push({
path:`componentsB/${this.person.name}/${this.person.age}/${this.person.sex}`
})
}
},
}
</script>
<style>
</style>複製程式碼
然後在componentsB.vue
頁面用this.$route.params
接收引數:
componentsB.vue
<template>
<div>
<div>我是元件B</div>
</div>
</template>
<script>
export default{
created(){
this.getRouterData()
},
methods: {
getRouterData(){
const param = this.$route.params
console.log(param)//{name:'Gene',age:'18',sex:'male'}
}
},
}
</script>
<style>
</style>複製程式碼
點選按鈕"方式一跳轉到元件B",componentsB頁面列印出{name:'Gene',age:'18',sex:'male'}
,成功獲取到A頁面傳過來的引數,並且位址列顯示為localhost:8889/#/componentsB/Gene/18/male
(埠號根據自己設定的來),表明這種傳參方式url會攜帶引數。
1.2 params傳參
首先將剛才路由配置修改部分還原,在componentsA.vue
頁面新增按鈕"方式二跳轉到元件B":
componentsA.vue
<template>
<div>
<div>我是元件A</div>
<button @click='routerToB1'>方式一跳轉到元件B</button>
<button @click='routerToB2'>方式二跳轉到元件B</button>
</div>
</template>複製程式碼
在methods
中新增方法routerToB2
,使用路由屬性name
來確定匹配的路由,使用屬性params
來傳遞引數:
componentsA.vue
routerToB2(){
this.$router.push({
name:'componentsB',
params:{
exa:'我是傳到元件B的引數'
}
})
},複製程式碼
componentsB.vue
保持不變,params傳參方式獲取引數也是通過this.$route.params
,點選A頁面新新增的按鈕"方式二跳轉到元件B",在B頁面列印出{exa: "我是傳到元件B的引數"}
,傳參成功,位址列為localhost:8889/#/componentsB
,表明這種方式url不會攜帶引數。
1.3 query傳參
這種方式和params傳參方式類似,在componentsA.vue
頁面繼續新增按鈕"方式三跳轉到元件B":
componentsA.vue
<template>
<div>
<div>我是元件A</div>
<button @click='routerToB1'>方式一跳轉到元件B</button>
<button @click='routerToB2'>方式二跳轉到元件B</button>
<button @click='routerToB3'>方式三跳轉到元件B</button>
</div>
</template>複製程式碼
在methods
中新增方法routerToB3
,使用路由屬性name
或者path
來確定匹配的路由,使用屬性query
來傳參:
componentsA.vue
routerToB3(){
this.$router.push({
name:'componentsB',// path:'/componentsB'
query:{
que:'我是通過query傳到元件B的引數'
}
})
}複製程式碼
在componentsB.vue
頁面通過this.$route.query
來獲取引數:
componentsB.vue
getRouterData(){
const query = this.$route.query
console.log(query)//{que: "我是通過query傳到元件B的引數"}
}複製程式碼
檢視位址列為localhost:8889/#/componentsB?que=我是通過query傳到元件B的引數
,顯然這種方式url會攜帶引數。
1.4 小結
- 路由配置傳參注意書寫格式
/:id
,獲取引數都是通過$route
而不是$router
params
傳參和query
傳參區別類似於post
和get
方法。params
傳參位址列不會顯示引數,而query
傳參會將引數顯示在位址列中params
傳參重新整理頁面引數會丟失,另外兩種不會params
傳參對應的路由屬性是name
,而query
傳參對應的路由屬性既可以是name
,也可以是path
二丶使用快取
快取方式即通過sessionStorage
、localStorage
、Cookie
方式傳參,這種方式和是不是用Vue無關,因此,不談。
三丶父子元件之間傳值
在components目錄下建立父元件parent.vue
和子元件children.vue
,在父元件中引入子元件。為了演示方便,在路由配置中加入/parent
路徑。
3.1 父元件向子元件傳值 props
在parent.vue
的子元件標籤上註冊message1,在children.vue
中通過props
接收message1,如果傳遞的值為變數,則使用v-bind:
或直接用:
,參考如下:
parent.vue
<template>
<div>
<div>我是父元件</div>
<children message1='我是直接引數' v-bind:message2='msg' :message3='obj'></children>
</div>
</template>
<script>
import Children from './children'
export default{
components:{
Children
},
data(){
return{
msg:'我是父元件的引數'
}
},
created(){
this.obj = {a:'1',b:'2',c:'3'}
}
}
</script>
<style>
</style>
複製程式碼
children.vue
<template>
<div>
<div>我是子元件</div>
<div>{{message1}}</div>
<div>{{message2}}</div>
<div>{{message3}}</div>
</div>
</template>
<script>
export default{
props:['message1','message2','message3'],
created(){
console.log(this.message3)
}
}
</script>
<style>
</style>複製程式碼
在瀏覽器中開啟:
3.2 子元件向父元件傳值 $emit
子元件通過vm.$emit( event, […args] ),觸發當前例項上的事件。附加引數都會傳給監聽器回撥。父元件在子元件標籤上監聽事件獲得引數。
children.vue
<template>
<div style="margin-top: 100px;">
<div>我是子元件</div>
<div>{{message1}}</div>
<div>{{message2}}</div>
<div>{{message3}}</div>
<button @click='ChildToParent'>點我傳愛</button>
</div>
</template>
<script>
export default{
props:['message1','message2','message3'],
data(){
return{
loud:'I love xx'
}
},
methods:{
ChildToParent(){
this.$emit('emitToParent',this.loud)
}
},
created(){
console.log(this.message3)
}
}
</script>
<style>
</style>
複製程式碼
parent.vue
<template>
<div>
<div>我是父元件</div>
<div>大聲告訴我你愛誰:{{loveWho}}</div>
<children @emitToParent='parentSayLove' message1='我是直接引數' v-bind:message2='msg' :message3='obj'></children>
</div>
</template>
<script>
import Children from './children'
export default{
components:{
Children
},
data(){
return{
msg:'我是父元件的引數',
loveWho:''
}
},
methods:{
parentSayLove(data){
this.loveWho = data
}
},
created(){
this.obj = {a:'1',b:'2',c:'3'}
}
}
</script>
<style>
</style>複製程式碼
點選按鈕瀏覽器顯示:
3.3 小結
props
可以是字串陣列,也可以是物件(可以型別驗證、設定預設值等) ;- 使用
.native
修飾監聽事件,開發中使用了element-ui
的框架標籤時候,使用事件繫結無效。這時候需要使用.native
修飾v-on:event
,可以在框架標籤或元件的根元素 上監聽一個原生事件,例如<my-component v-on:click.native="doTheThing"></my-component>
。
四丶非父子(兄弟)元件之間傳值
非父子元件之間傳值,需要定義公共例項檔案bus.js
,作為中間倉庫來傳值,不然路由元件之間達不到傳值的效果。在components目錄下新建first.vue
和second.vue
以及公共檔案bus.js
。
bus.js
import Vue from 'vue'
export default new Vue()複製程式碼
在first.vue
和second.vue
中分別引入bus.js。
import Bus from '../bus.js'複製程式碼
模擬情景:first.vue
向second.vue
傳值。在first.vue
通過在事件中新增Bus.$emit( event, […args] )
進行傳值,在second.vue
中通過Bus.$on(event,callBack)
進行監聽。
first.vue
<template>
<div>
<div>我是first.vue</div>
<button @click="firstToSecond">點選傳值給second.vue</button>
</div>
</template>
<script>
import Bus from '../bus.js'
export default{
data(){
return{
msg:'我是first.vue傳到second.vue的引數'
}
},
methods:{
firstToSecond(){
Bus.$emit('emitToSecond',this.msg)
}
}
}
</script>
<style>
</style>複製程式碼
second.vue
<template>
<div>
<div>我是second.vue</div>
{{info}}
</div>
</template>
<script>
import Bus from '../bus.js'
export default{
data(){
return{
info:''
}
},
mounted(){
const that = this;
Bus.$on('emitToSecond',function(data){
that.info = data
})
}
}
</script>
<style>
</style>複製程式碼
點選按鈕,瀏覽器中顯示:
小結
兄弟元件之間與父子元件之間的資料互動,兩者相比較,兄弟元件之間的通訊其實和子元件向父元件傳值有些類似,他們的通訊原理都是相同的,例如子向父傳值也是$emit
和$on
的形式,只是沒有Bus
,但若我們仔細想想,此時父元件其實就充當了Bus
這個事件匯流排的角色。
五丶使用Vuex
何為Vuex,看一下官網的解釋:
Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式。它採用集中式儲存管理應用的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
什麼情況下使用Vuex?
Vuex 可以幫助我們管理共享狀態,並附帶了更多的概念和框架。這需要對短期和長期效益進行權衡。
如果您不打算開發大型單頁應用,使用 Vuex 可能是繁瑣冗餘的。確實是如此——如果您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 store 模式 就足夠您所需了。但是,如果您需要構建一箇中大型單頁應用,您很可能會考慮如何更好地在元件外部管理狀態,Vuex 將會成為自然而然的選擇。
在components目錄下新建vuexA.vue
和vuexB.vue
,模擬場景:vuexA.vue
向vuexB.vue
傳值。
首先我們安裝vuex,npm install vuex --save
,在src目錄下建立vuex目錄,然後在vuex目錄下新建index.js
、state.js
、getters.js
、actions.js
、mutations.js
:
vuex/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state.js'
import mutations from './mutations.js'
import getters from './getters.js'
import actions from './actions.js'
Vue.use(Vuex)
export default new Vuex.Store({
state,
getters,
mutations,
actions
})複製程式碼
在main.js中引入vuex/index.js並注入到Vue中:
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './vuex'
Vue.config.productionTip = false
new Vue({
store,
router,
render: h => h(App),
}).$mount('#app')
複製程式碼
state.js
export default{
city:'nanjing'
}複製程式碼
vuexA.vue
<template>
<div>
<div>我是vuexA中city引數:{{city}}</div>
<input type="text" :value="city" @change="change">
</div>
</template>
<script>
export default{
methods:{
change(e){
this.$store.dispatch('setCityName',e.target.value)
}
},
computed:{
city(){
return this.$store.getters.getCity
}
}
}
</script>
<style>
</style>複製程式碼
vuexB.vue
<template>
<div>
<div>我是vuexB中的city引數:{{city}}</div>
</div>
</template>
<script>
export default{
data(){
return{
}
},
computed:{
city(){
return this.$store.state.city
}
}
}
</script>
<style>
</style>
複製程式碼
actions.js
export default{
setCityName({commit,state},name){
commit('setCity',name)
}
}複製程式碼
mutations.js
export default{
setCity(state,name){
state.city = name//設定新的值
}
}複製程式碼
getter.js
export default{
getCity(state){
return state.city//返回目前城市名稱
}
}複製程式碼
在瀏覽器中開啟:
修改input中的值:
顯而易見,當vuexA頁面中input值改變時,可同時改變vuexB頁面中的值,即將city引數從vuexA頁面傳到了vuexB頁面,從而實現用vuex在元件中傳值。
vuex更多詳細功能請參考Vuex中文官方文件。
全部例項程式碼已上傳至我的GitHub,歡迎訪問Fork。