vue3的路由
- 使用的方法和vue2相差不大
- 路由的跳转,使用的是router-link 实际上是一个a标签 ,to属性改变路径
- 跳转方式
- to=“/path”
- :to=“{name:’ name ’ }”
- :to=“{path:’ /path ’ }”
路由的嵌套
-
在vue3中,当要个路由嵌套时,在父路由的配置下 直接的写children会报错,原因应该是 定义的routes是有一定的泛型的,不允许直接的添加,需要在创建路由的时候导入 RouterRecordRaw 的方法,在给routes添加在相应的类型限制
-
const route:Array<RouterRecordRaw> = []
-
路由的传参
1.query的两种方法
-
第一种 query 使用比较复杂
- 参数在路径的后面添加,写在? 后面, 有多个的参数要使用 & 分割
- 同时 to要变成动态组件 添加: 参数的值需要使用模板字符串来存放变量key=${value }
- 获取参数的话 要导入hooks 的useRoute方法 在route.query.key 读取出值
-
第二种query
- 还是把to添加:变成动态的 传递一个query对象{path:’ ',query:{key:value}}
- 读取值还是和第一种一样
<!-- 第一种--> <li v-for="item in list" :key="item.id"> <router-link :to="`/home/childid=${item.id}&title=${item.title}&detail=${item.detail}`">{{item.title } </router-link></li> <!-- 第二种params --> <li> <router-link :to="{ path: '/home/child', query: { id: item.id, title: item.title, detail: item.detail } }">{{ item.title }}</router-link></li>
<!--参数的获取--> <div> <p>编号:{{ route.query.id }}</p> <p>标题:{{ route.query.title }}</p> <p>内容:{{ route.query.detail }}</p> </div> <div> <p>编号:{{ query.id }}</p> <p>标题:{{ query.title }}</p> <p>内容:{{ query.detail }}</p> </div> <script lang="ts" setup> import { useRoute } from 'vue-router'; import { toRefs } from 'vue'; let route = useRoute() // 再次的解构route 使得html中语句变的简单 let { query } = toRefs(route) </script>
2.param传参
- params的第一种写法
- 在配置路由时先要使用 /:id/:title? 的类似参数 先在 路由的路径里面占位,后加?表示可传可不传
- 跳转时 也要使用模板字符串 /path/${} 的方法来写
- 获取参数 首先引用 useRoute的方法 再获取参数 const {router} = useRoute()
- params的第二种写法
- 在to中传递params的对象,参数的写法和query类似
- 但是不能使用path了 只能使用路由中配置的name才行
<!-- <router-link :to="`/home/child/${item.id}/${item.title}/${item.detail}`">{{ item.title }}</router-link> -->
<router-link :to="{
name: 'detail',
params: {
id: item.id,
title: item.title,
detail: item.detail
}
}
">{{ item.title }}</router-link>
<!--路由的配置
{
path: "child/:id/:title/:detail",
component: ChildParams,
name: "detail",
}, -->
3.路由的props配置
-
当我们使用的是params时 配置路由时可以添加一个属性 props:true,类似与把组件接收了父组件传过来的参数,这样的话 在获取参数的时候,就可以直接的使用变量 id,title,detail
-
切记展示的页面需要引入 方法 defineProps([])接收一下变量
-
props:true 的作用是将路由接收到的params的参数作为props传递给路由组件
params: { id: item.id, title: item.title, detail: item.detail, props:true } <div> <p>编号:{{ id }}</p> <p>标题:{{ title }}</p> <p>内容:{{ detail }}</p> </div>
-
当我们想要一个query的传参时,还能使用props接收的话,我们就要写一个函数在路由中 props(route){ return route.query }
4.路由的replace模式
- 在router-link 添加replace时这样浏览器就不能放回上一次的页面 默认时history模式 可以返回的
编程式跳转
就是使用函数的跳转,不是使用router-link
-
使用的是useRouter方法 ,需要导入
-
在使用的时可以使用push(),跳转到指定的路径,并且to中可以写的params和query参数 都可以写在push中
const getDetail = function (item: any) { router.push({ name: 'detail', params: { id: item.id, title: item.title, detail: item.detail }, }) }
-
在这里需要传递的参数item可能会有type的报错,需要限制一下类型
路由的重定向
就是redirect,打开页面默认的页面
path:‘ ’
redriect: ‘/path’
集中式的状态管理
一般是共享的数据需要放在里面
- 搭建pinia环境 npm i pinia
- 在main.ts 中 引入pinia import {createPinia} from ‘pinia’
- 创建pinia const pinia = createPinial()
- 安装pinia use(pinia)
1.数据的保存
- 把要保存的数据存放在store文件夹中,在文件夹中写文件把数据保存。一般要注意命名
- 先导入defineStore 方法 要传入参数和配置对象,
- 一般参数是文件名
- 配置对象有state()方法 还必须return出来
- 实例化出来export const useCountStore = defineStore(’ name ',{ state(){ return { } } })
- 导出实例化,在使用
2.读取store中的数据
- 在使用的页面,先导入保存了数据的文件方法 import {useCountStore} from ’ ’
- 需要把方法给暴露出来
- const useCount = useCountStore()
- 读取数据时 useCount.sum/useCount.$state.sum 就是保存在内部的数据
3.数据的修改
三种修改数据的方法
-
我们定义了 useCount 的实例,就可以直接的修改数据 useCount.sum = 1
-
使用$patch( { sum:2 }),和定义的一样修改成相同的格式,
-
使用actions函数
-
要使用这个的话,要先在定义store的时候就要定义actions函数,是放置用于响应式动作的方法
-
然后再actions定义一个方法,在这个方法里修改state中保存的数据
actions:{ increment(value){ this.sum += value } }
-
然后当我们调用这个方法时,就会发生数据的改变
useCount.incement(2)
-
-
actions 的用法是比较复杂的,但是我们可以添加更多的函数设置
4.storeToRefs 解构数据
- 展示数据太复杂了,可以对useCount进行解构,使用toRefs的话会全部成功为ref的数据
- storeToRefs只会对store的数据进行解构,不会对方法进行ref包裹
5.getters
- 当对数据不满意时,可以对数据进行修改,getters定义的方法是要 有return返回的 并且参数可以传入state直接读取数据
- 要使用getters内部的方法的话,可以在使用的组件中使用 storeToRefs解构 ,解构出来就可以使用了
6.监视数据发生的变化
每个store的方法实例化之后,就会有$subscribe( () => { } ) 函数,当检测的数据发生变化时,就是执行内部的函数,和监测函数watch有点类似,state 是当前存储的数据
useList.$subscribe((mutate, state) => {
console.log(state);
})
1.父子组件的通信props
1.父传子
- 父传子,和vue2的类似 在子组件是的标签上使用 动态的数据绑定
- 子组件在接收的时候 需要导入defineProps方法,并且内部只能是数组,子组件就可以接收到了
2.子传父
- 需要使用函数来传递,父组件接收这个函数
- 在子组件中,写好要传递的函数,再把函数写进 defineProps的数组中
- 父组件 需要在子组件的标签中,接收之后,在重新的赋值给一个函数
3.自定义事件(用来子传父)
- @name =function 这就创建好了一个自定义的事件,就是当我们执行了name是就会触发function,并且这个自定义的事件也是可以发送的
- 这个自定义事件是执行不了的,给子组件绑定上自定义事件,使用defineEmits() 方法和defineProps方法类似,处理一下name 并且 用一个emit接收 const emit = defineEmit([‘name’])
- 处理之后就可以使用了,只要调用 emit(‘name’) 就能调用函数了 并且还可以传递参数,这样调用时参数会传递给function的函数中
4.v-model
2.祖传孙$attrs
- 实现祖元素和孙元素之间的数据传递,想在祖组件中定义数据,通过动态绑定先把数据传递给子组件,可以在devtools的工具中可以看到,祖组件传递的数据 若子组件接受了 则会在 props中显示,没接收的数据会在attrs中显示
- 在子组件中 我们给孙子组件标签添加上 v-model=‘$attrs’ 就能把数组传递给 孙组件了
- 孙组件需要使用defineProps方法来接收 数据 在这里也可以使用自定义事件
3.$ r e f s 和 refs和 refs和 $parent
- $refs用于 父传子
- 给子组件添加refs属性,就可以在父组件中拿到子组件的实例,但是 内部的数据时获取不到的,需要在子组件中使用 defineExpose({ }),暴露出想要修改的数据
- 在父组件中使用$refs的话就会获取到所有的子组件的实例对象,获取到的是一个对象,
- $parent用于 子传父
- 在子组件的函数中可以使用 $parent 获取到父组件的实例,但是也需要父组件把 属性暴露出来
- 子组件可以在函数中修改
- 两个都写在在标签的函数中,传递的参数是 $ $refs $ $parent
4.provide 和 inject 祖孙直接通信
- 祖传孙 在祖组件导入 provide方法 provide(‘name’ , 属性) 第二个是要传递的数据 可以是多个要用对象表示,接收的时候也需要解构
- 在孙组件 导入inject方法 来接收数据 let x = inject( ‘name’ , default )
- 孙组件传递数据给祖组件的话 需要在 祖组件中定义一个函数 让后也要通过 provide发送出去,让后在孙组件中接收,孙组件再调用函数