声明式导航VS编程式导航
声明式导航VS编程式导航
前言
最近在学习Vue-Router的时候,对于声明式导航和编程式导航中的查询参数和动态路由的语法有些不清晰,发现有很多相似的地方,但是直觉告诉我没有这么简单,所以我仔细的学习了一下,发现竟然真的一样!
不同的只是使用位置有些差异,所以苯人在这篇博客中分享一下自己的思考😀
📌 核心结论先行
声明式导航(<router-link>
)和编程式导航($router.push()
)在传参的语法格式上保持高度一致,都支持相同的对象结构。主要区别在于使用位置(模板 vs 代码),而参数接收方式完全统一。只有在声明式导航的字符串写法传递动态参数时稍有不同。
简单说:除了写的地方不一样,其他几乎都一样!
🎯 通用的传参语法(两种导航方式都适用)
1. 查询参数传参
对象写法(推荐,最清晰)
javascript
// 1. 先创建配置对象
const navigationConfig = {path: '/search', // 或者用 name: 'Search'(需要在routes中配置name)query: {keyword: 'vue',page: 1,sort: 'price'}
}// 2. 实际使用:两种导航方式都可以用同一个对象!
字符串写法(简洁,适合简单参数)
const urlString = '/search?keyword=vue&page=1&sort=price'
3. 动态路由传参
对象写法(必须用name,推荐)
// 0. 必须先配置路由:{ path: '/user/:id', name: 'User' }// 1. 创建配置对象
const navigationConfig = {name: 'User', // 必须使用命名路由!params: {id: 123, // 键名必须匹配路由配置的 :idfrom: 'home' // 额外参数(不在URL显示)}
}// 2. 实际使用
字符串写法(直接拼接路径)
const urlString = '/user/123'
🔄 两种导航方式的具体使用对比
声明式导航 (在模板中使用)
<!-- 查询参数 - 对象写法 -->
<router-link :to="{ path: '/search', query: { keyword: 'vue' } }">搜索Vue
</router-link><!-- 查询参数 - 使用预先定义的配置对象 -->
<router-link :to="navigationConfig">搜索Vue
</router-link><!-- 动态路由参数 - 对象写法 -->
<router-link :to="{ name: 'User', params: { id: 123 } }">用户详情
</router-link><!-- 字符串写法 -->
<router-link to="/search?keyword=vue">搜索</router-link>
<router-link to="/user/123">用户</router-link>
编程式导航 (在JavaScript中使用)
// 查询参数 - 对象写法
this.$router.push({ path: '/search', query: { keyword: 'vue' }
})// 查询参数 - 使用预先定义的配置对象
this.$router.push(navigationConfig)// 动态路由参数 - 对象写法
this.$router.push({name: 'User',params: { id: 123 }
})// 字符串写法
this.$router.push('/search?keyword=vue')
this.$router.push('/user/123')// 在方法中使用
methods: {searchProducts() {const config = {path: '/search',query: { keyword: this.searchText }}this.$router.push(config) // 使用配置对象},viewUserProfile(userId) {this.$router.push({name: 'User',params: { id: userId }})}
}
📍 唯一的重要区别:使用位置
特性 | 声明式导航 (<router-link> ) | 编程式导航 ($router.push() ) |
---|---|---|
使用位置 | Vue模板中 | JavaScript代码中 |
适用场景 | 静态导航链接 | 动态逻辑跳转(点击事件、异步操作后) |
写法示例 | <router-link :to="{...}"> | this.$router.push({...}) |
灵活性 | 相对固定 | 高度灵活,可在任何方法中使用 |
何时用哪种?
- 用声明式:普通的导航链接,比如导航菜单
- 用编程式:按钮点击后跳转、表单提交后跳转、异步操作完成后跳转
✅ 参数接收(完全统一)
无论用哪种方式传递参数,接收方式都是一样的:
<template><div><!-- 接收查询参数 --><p>关键词: {{ $route.query.keyword }}</p><p>页码: {{ $route.query.page }}</p><!-- 接收动态路由参数 --><p用户ID: {{ $route.params.id }}</p><p>来源: {{ $route.params.from }}</p></div>
</template>
一些小问题
为什么要使用name,怎么使用name?
核心结论先行:name 的作用是给路由一个唯一的、语义化的标识符,让导航不再依赖具体的URL路径。
这段话可能理解起来也不是很简单,我们在具体的例子里来分析
❌ 不使用 name(硬编码路径)
// 路由配置
{path: '/user/:userId/profile/settings', // 复杂路径component: UserSettings
}// 导航代码(硬编码,脆弱)
this.$router.push('/user/123/profile/settings')
this.$router.push({path: '/user/123/profile/settings' // 路径太长容易写错
})// 如果后端要求路径改为:'/member/:id/settings'
// 所有导航代码都要手动修改!
✅ 使用 name(解耦,推荐)
//==路由配置==
{path: '/user/:userId/profile/settings', // 实际路径可以很复杂name: 'UserSettings', // ⭐ 但名字很简单component: UserSettings
}// 导航代码(语义化,健壮)
this.$router.push({name: 'UserSettings', // ⭐ 只关心"要去哪",不关心"怎么去"params: { userId: 123 }
})// 即使路径改为:'/member/:id/settings'
// 只需要改路由配置,所有导航代码无需修改!
{path: '/member/:id/settings', // 路径变了name: 'UserSettings', // 但名字不变component: UserSettings
}
// 所有使用 name: 'UserSettings' 的导航自动适应新路径
接下来再去看那句话,会觉得说的很美妙了😋
name相当于去哪里,query/params相当于带什么东西去。name+params=动态路由传参
name+query=查询参数传参
path+query=查询参数传参
path+params是无效的写法😱
💡 总结记住三句话
- 语法是通用的:同样的配置对象,既可以用在
<router-link>
,也可以用在$router.push()
- 位置决定用法:在模板中用声明式,在代码中用编程式
- 接收完全一样:都用
$route.query
和$route.params
获取参数