Vue傳參一籮筐
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。