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。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。