应用笔记 · 2023年4月8日

Vue组件传值以及页面间传递数据的几种方法

VUE3 更新:

vue3.0取消了2.0部分api,所以路由跳转传值方式有所不同。

这里主要讲编程式导航,也就是router.push(location, onComplete?, onAbort?)

vue3.0新增API:useRouter和useRoute

一.路由跳转
1.首先在需要跳转的页面引入API—useRouter

2.在跳转页面定义router变量

3.用router.push跳转页面

4.如果有参数的话,在接收页面引入API–useRoute

5.在接收页面定义变量route,获取传过来的变量

二.页面传参的问题,此处有坑,特别注意

1.如果提供了 pathparams 会被忽略,但query 没有这种情况,此时需要提供路由的 name 或手写完整的带有参数的 path

2.上述规则同样适用于 router-link 组件的 to 属性

3.如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users/1 -> /users/2),你需要使用 beforeRouteUpdate 来响应这个变化 (比如抓取用户信息)

4.如果上述写法出现 prams 传参失效和报错问题,原因如下:

vue-router 在4.1.4版本有一个更新:删除了没有定义在path里的params。

mportant Note

Changes introduced by e8875705eb8b8a0756544174b85a1a3c2de55ff6.

If you were relying on passing params that were not defined as part of the path, eg: having a route defined as follows:

And pushing with an artificial param:

This change will break your app. This behavior has worked in some scenarios but has been advised against for years as it’s an anti-pattern in routing for many reasons, one of them being reloading the page lose the params. Fortunately, there are multiple alternatives to this anti-pattern:

  • Putting the data in a store like pinia: this is relevant if the data is used across multiple pages

  • Move the data to an actual param by defining it on the route’s path or pass it as query params: this is relevant if you have small pieces of data that can fit in the URL and should be preserved when reloading the page

  • Pass the data as state to save it to the History API state:

    Note state is subject to History state limitations.

  • Pass it as a new property to to.meta during navigation guards:

    This is known an transient state and since it’s in a navigation guard, it will be preserved when reloading the page. Check the documentation for more details.

Fixing #1497, required getting rid of unused params and therefore will broke this long standing anti-pattern usage

——————————————————————————————-

vue组件传值和页面间通信传参多种方式,在vue开发时大部分一个页面内父子间组件传参,第二页是跳路由页面间传参,下面解决几种情况不同传参数方法

一、通过路由带参数进行传值

①两个组件 A和B,A组件通过query把orderId传递给B组件(触发事件可以是点击事件、钩子函数等)

②在B组件中获取A组件传递过来的参数

 

二、通过设置 Session Storage缓存的形式进行传递

①两个组件A和B,在A组件中设置缓存orderData

 

此时 dataB 就是数据 orderData

朋友们可以百度下 Session Storage(程序退出销毁) 和 Local Storage(长期保存) 的区别。

三、父子组件之间的传值,用props

(一)父组件往子组件传值props

①定义父组件,父组件传递 number这个数值给子组件,如果传递的参数很多,推荐使用json数组{}的形式

image.png

②定义子组件,子组件通过 props方法获取父组件传递过来的值。props中可以定义能接收的数据类型,如果不符合会报错。

image.png

当然也可以简单一点,如果不考虑数据类型,直接 props:[“number”,”string”]就可以了,中括号包裹,多个值使用,分隔。

③假如接收的参数 是动态的,比如 input输入的内容 v-model的形式

注意:传递的参数名称 支持驼峰命名,下图 描述不正确(1.0是不支持的)

④父子组件传值,数据是异步请求,有可能数据渲染时报错

原因:异步请求时,数据还没有获取到但是此时已经渲染节点了

解决方案:可以在 父组件需要传递数据的节点加上  v-if = false,异步请求获取数据后,v-if = true

(二)、子组件往父组件传值,通过emit事件

四、不同组件之间传值,通过eventBus(小项目少页面用eventBus,大项目多页面使用 vuex)

①定义一个新的vue实例专门用于传递数据,并导出

image.png

②定义传递的方法名和传输内容,点击事件或钩子函数触发eventBus.emit事件

image.png

③接收传递过来的数据

注意:enentBus是一个另一个新的Vue实例,区分两个this所代表得vue实例

image.png

五、vuex进行传值

为什么使用vuex?

vuex主要是是做数据交互,父子组件传值可以很容易办到,但是兄弟组件间传值(兄弟组件下又有父子组件),或者大型spa单页面框架项目,页面多并且一层嵌套一层的传值,异常麻烦,用vuex来维护共有的状态或数据会显得得心应手。

需求:两个组件A和B,vuex维护的公共数据是 餐馆的名称 resturantName,默认餐馆名称是 飞歌餐馆,那么现在A和B页面显示的就是飞歌餐馆。如果A修改餐馆名称 为 A餐馆,则B页面显示的将会是 A餐馆,反之B修改同理。这就是vuex维护公共状态或数据的魅力,在一个地方修改了数据,在这个项目的其他页面都会变成这个数据。

image.png

①使用 vue-cli脚手架工具创建一个工程项目,工程目录,创建组件A和组件B路由如下:

image.png

路由如下:

app.vue

image.png

②开始使用vuex,新建一个 sotre文件夹,分开维护 actions mutations getters

image.png

②在store/index.js文件中新建vuex 的store实例

*as的意思是 导入这个文件里面的所有内容,就不用一个个实例来导入了。

③actions

④mutations

⑤getters

⑥在main.js中导入 store实例

④在组件A中,定义点击事件,点击 修改 餐馆的名称,并把餐馆的名称在事件中用参数进行传递。

…mapactions 和 …mapgetters都是vuex提供的语法糖,在底层已经封装好了,拿来就能用,简化了很多操作。

其中…mapActions([‘clickAFn’]) 相当于this.$store.dispatch(‘clickAFn’,{参数}),mapActions中只需要指定方法名即可,参数省略。

…mapGetters([‘resturantName’])相当于this.$store.getters.resturantName

B组件同理