路由简单使用
安装
固定5个固定的步骤(不用死背,熟能生巧)
下载 VueRouter 模块到当前工程
yarn add vue-router@3.6.5在main.js中
import VueRouter from 'vue-router'//引入VueRouter
Vue.use(VueRouter)//安装注册
const router = new VueRouter()//创建路由对象
new Vue({
render: h => h(App),
router:router//将路由对象注入到new Vue实例中
}).$mount('#app')当我们配置完以上5步之后 就可以看到浏览器地址栏中的路由 变成了 /#/的形式。表示项目的路由已经被Vue-Router管理了

配置
创建好需要的组件 (views目录),配置路由规则
const router = new VueRouter({
// routes 路由规则们
// route 一条路由规则 { path: 路径, component: 组件 }
routes: [
{ path: '/find', component: Find },
{ path: '/my', component: My },
{ path: '/friend', component: Friend },
]
})
export default router每条路由规则是一个对象,包含:
path:URL 路径(如/find)component:路径匹配时渲染的组件(需提前导入组件如Find)
而export default router将配置好的路由实例导出,供 Vue 主文件(如 main.js)注入到根实例中
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
new Vue({
render: h => h(App),
router
}).$mount('#app')声明式导航
router-link标签
vue-router 提供了一个全局组件 router-link (取代 a 标签)
- 能跳转,配置 to 属性指定路径(必须) 。本质还是 a 标签 ,to 无需 #
- 能高亮,默认就会提供高亮类名,可以直接设置高亮样式
语法: <router-link to="path的值">发现音乐</router-link>
<div>
<div class="footer_wrap">
<router-link to="/find">发现音乐</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/friend">朋友</router-link>
</div>
<div class="top">
<!-- 路由出口 → 匹配的组件所展示的位置 -->
<router-view></router-view>
</div>
</div>router-link类名
使用router-link跳转后,我们发现。当前点击的链接默认加了两个class的值 router-link-exact-active和router-link-active

在 Vue Router 中,router-link-active 和 router-link-exact-active 是两个非常重要的 CSS 类名,它们由 Vue Router 自动添加到 <router-link> 组件上,用于指示当前导航链接的激活状态:
router-link-active
- 触发条件:当路由路径部分匹配时添加
- 匹配规则:只要当前路由的路径包含该
<router-link>的目标路径,就会添加 - 示例:
html <router-link to="/user">用户</router-link> - 当访问
/user→ 激活 - 当访问/user/profile→ 激活(因为包含/user) - 当访问
/product→ 不激活
router-link-exact-active
- 触发条件:当路由路径完全匹配时添加
- 匹配规则:只有当当前路由的路径完全等于该
<router-link>的目标路径时才会添加 - 示例:
html <router-link to="/user">用户</router-link> - 当访问
/user→ 激活 - 当访问/user/profile→ 不激活(路径不完全相等) - 当访问
/users→ 不激活(即使相似但不相等)
自定义类名
router-link的两个高亮类名太长了,我们可以在创建路由对象时,额外配置两个配置项
const router = new VueRouter({
linkActiveClass: 'active', // 配置模糊匹配的类名
linkExactActiveClass: 'exact-active' // 配置精确匹配的类名
})查询参数传参
- 通过 URL 的
?后拼接参数(如/user?id=123) - 参数可见,适合非敏感数据(如分页、筛选条件)
- 不需要提前在路由配置中定义参数名
传参
<!-- 方式1:字符串拼接 -->
<router-link to="/user?id=123&name=Alice"></router-link>
<!-- 方式2:对象形式(推荐) -->
<router-link :to="{
path: '/user',
query: { id: 123, name: 'Alice' }
}">
</router-link>接收
export default {
mounted() {
// 通过 $route.query 获取
console.log(this.$route.query.id) // 输出 123
console.log(this.$route.query.name) // 输出 'Alice'
}
}动态路由传参
这种方式需要配置路由,必须使用 : 定义参数名
const router = new VueRouter({
routes: [
...,
{
path: '/search/:words', //定义参数名
component: Search ,
name: xxx//定义别名,可选
}
]
})传参
<!-- 方式1:路径拼接 -->
<router-link to="/user/123">用户123</router-link>
<!-- 方式2:对象形式(推荐) -->
<router-link :to="{
name: 'user',
params: { id: 123 }
}">
</router-link>其中,第二种写法需路由配置 name 属性
接收参数
export default {
props: ['id'], // 需路由配置 props: true
mounted() {
// 方式1:通过 props(推荐)
console.log(this.id) // 输出 123
// 方式2:通过 $route.params
console.log(this.$route.params.id) // 输出 123
}
}两种传参方式对比
| 对比项 | 查询参数(Query) | 动态路由参数(Params) |
|---|---|---|
| URL 形式 | /path?key=value | /path/:id(如 /user/123) |
| 路由配置 | 无需特殊配置 | 需定义 :param 占位符 |
| 参数可见性 | 明文显示在 URL | 部分隐藏(仅路径中显示值) |
| 传参方式 | query: { key: value } | params: { key: value } |
| 组件获取方式 | this.$route.query | this.$route.params 或 props |
| 适用场景 | 筛选、分页等可选参数 | 必选参数(如用户ID、文章ID) |
用查询参数(Query)当:
- 参数是可选的(如
?page=1) - 需要保留参数在 URL 中可见(如分享链接)
- 参数是可选的(如
用动态路由(Params)当:
- 参数是必选的(如用户详情页
/user/123) - 需要更简洁的 URL(符合 RESTful 风格)
- 参数是必选的(如用户详情页
重定向
网页打开时, url 默认是 / 路径,未匹配到组件时,会出现空白
const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home'},
...
]
})404
404的路由,虽然配置在任何一个位置都可以,但一般配置在其他路由规则的后面
即前面不匹配就命中最后
const router = new VueRouter({
routes: [
...
{ path: '*', component: NotFound }
]
})编程式导航
跳转
编程式导航即用JS代码来进行跳转
//简单写法
this.$router.push('路由路径')
//完整写法
this.$router.push({
path: '路由路径'
})也可以通过name来进行跳转,配置name配置项
{ name: '路由名', path: '/path/xxx', component: XXX },this.$router.push({
name: '路由名'
})查询参数传参
传参
// 方式1:path + query
this.$router.push({
path: '/search',
query: { keyword: 'vue', page: 1 } // 参数对象
})
// 方式2:命名路由 + query
this.$router.push({
name: 'search',
query: { keyword: 'vue' }
})
// 方式3:URL 字符串(不推荐)
this.$router.push('/search?keyword=vue&page=1')接收
export default {
mounted() {
// 通过 $route.query 获取
console.log(this.$route.query.keyword) // 'vue'
console.log(this.$route.query.page) // '1'
}
}动态路由传参
传参
// 方式1:命名路由 + params
this.$router.push({
name: 'user', // 必须用 name!
params: { id: 123 } // 参数对象
})
// 方式2:路径字符串(不推荐,维护性差)
this.$router.push('/user/123')接收
export default {
props: ['id'], // 需路由配置 props: true
mounted() {
// 方式1:通过 props(推荐)
console.log(this.id)
// 方式2:通过 $route.params
console.log(this.$route.params.id)
}
}Vuex核心使用
安装
安装vuex与vue-router类似,vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装
npm i vuex@3新建 store/index.js 专门存放 vuex
为了维护项目目录的整洁,在src目录下新建一个store目录其下放置一个index.js文件。 (和 router/index.js 类似)

创建仓库 store/index.js
// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)
// 创建仓库 store
const store = new Vuex.Store()
// 导出仓库
export default store在 main.js 中导入挂载到 Vue 实例上
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')成功创建了一个 空仓库
State
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储。
打开项目中的store.js文件,在state对象中可以添加我们要共享的数据。
// 创建仓库 store
const store = new Vuex.Store({
state: {
count: 101
}
})state 状态, 即数据, 类似于vue组件中的data
state 中的数据整个vue项目的组件都能访问到
组件中可以使用 $store 获取到vuex中的store对象实例,可通过state属性属性获取count
<h1>state的数据 - {{ $store.state.count }}</h1>组件逻辑中使用,把state中数据,定义在组件内的计算属性中
<h1>state的数据 - {{ count }}</h1>
computed: {
count () {
return this.$store.state.count
}
}js文件中使用,需要先引入store
import store from "@/store"
console.log(store.state.count)Mutations
Mutations 的核心职责是直接修改 Vuex store 的状态(state)
mutations: {
addCount (state, count) {
state.count = count
}
}其中state 参数是必须的
在组件中发送请求更新state,需要使用$store.commit,其中传参可以是对象
this.$store.commit('addCount', 10)
this.$store.commit('addCount', {
count: 10
})若要传递多个数据,只能通过传对象的方式
actions
state是存放数据的,mutations是同步更新数据 (便于监测数据的变化, 更新视图等, 方便于调试工具查看变化),
actions则负责进行异步操作
定义actions
mutations: {
changeCount (state, newCount) {
state.count = newCount
}
}
actions: {
setAsyncCount (context, num) {
// 一秒后, 给一个数, 去修改 num
setTimeout(() => {
context.commit('changeCount', num)
}, 1000)
}
},组件中通过dispatch调用
setAsyncCount () {
this.$store.dispatch('setAsyncCount', 666)
}
getters
除了state之外,有时我们还需要从state中筛选出符合条件的一些数据,这些数据是依赖state的,此时会用到getters
例如,state中定义了list,为1-10的数组,
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}组件中,需要显示所有大于5的数据,正常的方式,是需要list在组件中进行再一步的处理,但是getters可以帮助我们实现它
getters: {
// getters函数的第一个参数是 state
// 必须要有返回值
filterList: state => state.list.filter(item => item > 5)
}调用语法也很简单
<div>{{ $store.getters.filterList }}</div>
Vuex辅助函数
mapState
mapState 是 Vuex(Vue.js 的状态管理库)中的一个辅助函数,用于将 Vuex store 中的 state 属性快速映射到组件的计算属性中。它可以简化组件中获取全局状态的代码,避免重复声明计算属性
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['count', 'message'])
}
}将 store.state.count 映射为 this.count
将 store.state.message 映射为 this.message
可直接{{count}}调用
mapMutations
mapMutations和mapState很像,它把位于mutations中的方法提取了出来,我们可以将它导入
import { mapMutations } from 'vuex'
methods: {
...mapMutations(['addCount'])
}此时,就可以直接通过this.addCount调用了
<button @click="addCount">值+1</button>mapActions
mapActions 是把位于 actions中的方法提取了出来,映射到组件methods中
import { mapActions } from 'vuex'
methods: {
...mapActions(['changeCountAction'])
}
直接通过 this.方法 就可以调用
<button @click="changeCountAction(200)">+异步</button>Vuex模块化
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
这句话的意思是,如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护
由此,又有了Vuex的模块化

准备 state
定义模块 user 和 setting
user中管理用户的信息状态 userInfo modules/user.js
const state = {}
export default {
state,
}在store/index.js文件中的modules配置项中,注册模块
import user from './modules/user'
import setting from './modules/setting'
const store = new Vuex.Store({
modules:{
user,
}
})使用模块中的数据, 可以直接通过模块名访问 $store.state.模块名.xxx => $store.state.setting.desc
也可以通过 mapState 映射
获取模块内的state数据
尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的 state 中,属性名就是模块名

访问方式有两种
- 直接通过模块名访问 $store.state.模块名.xxx
- 通过 mapState 映射:mapState('模块名', ['xxx']) - 要开启命名空间 namespaced:true
const state = {}
export default {
namespaced: true,
state,
}$store直接访问
$store.state.user.userInfo.namemapState辅助函数访问
...mapState('user', ['userInfo']),
...mapState('setting', ['theme', 'desc']),获取模块内的getters数据
使用模块中 getters 中的数据:
- 直接通过模块名访问
$store.getters['模块名/xxx '] - 通过 mapGetters 映射:
mapGetters('模块名', ['xxx'])- 需要开启命名空间
const getters = {
// 分模块后,state指代子模块的state
UpperCaseName (state) {
return state.userInfo.name.toUpperCase()
}
}直接访问
<div>{{ $store.getters['user/UpperCaseName'] }}</div>通过命名空间访问
computed:{
...mapGetters('user', ['UpperCaseName'])
}获取模块内的mutations方法
- 直接通过 store 调用 $store.commit('模块名/xxx ', 额外参数)
- 通过 mapMutations 映射 :mapMutations('模块名', ['xxx']) - 需要开启命名空间
const mutations = {
setUser (state, newUserInfo) {
state.userInfo = newUserInfo
}
}直接访问
methods: {
updateUser () {
$store.commit('模块名/mutation名', 额外传参)
},
}通过命名空间访问
methods:{
...mapMutations('setting', ['setTheme']),
}获取模块内的actions方法
- 直接通过 store 调用 $store.dispatch('模块名/xxx ', 额外参数)
- 通过 mapActions 映射:子模块的映射 mapActions('模块名', ['xxx']) - 需要开启命名空间
const actions = {
setUserSecond (context, newUserInfo) {
setTimeout(() => {
context.commit('setUser', newUserInfo)
}, 1000)
}
}直接通过store调用
methods:{
update () {
this.$store.dispatch('user/setUserSecond', {
name: 'xiaohong',
age: 28
})
},
}mapActions映射
methods:{
...mapActions('user', ['setUserSecond'])
}
1 条评论
新车首发,新的一年,只带想赚米的人