文章目录
一、非路由组件和路由组件
1. 非路由组件
-
非路由文件存放在 components 文件夹下
-
非路由组件包含:Header【首页、登录、注册、搜索】、Footer【首页、搜索页】
-
非路由组件的使用步骤
- 新建 src / components / Header / index.vue
- 新建 src / components / Footer / index.vue
- App.vue 中引入和使用
<template>
<!-- 头部组件 -->
<Header></Header>
<!-- 底部组件 -->
<Footer></Footer>
</template>
<script setup>
import Header from '@/components/Header'
import Footer from '@/components/Footer'
</script>
<style lang="scss"></style>
2. 路由组件
- 路由组件存放在
src / views
文件夹下
1. 配置路由
src / router / index.js
import { createRouter, createWebHashHistory } from 'vue-router'
const routes = [
// 重定向:运行项目时,立即定位到首页,而不是 /
{
path: '/',
redirect: '/home'
}, {
path: '/home',
component: () => import('@/views/Home')
}, {
path: '/search',
component: () => import('@/views/Search')
}, {
path: '/login',
component: () => import('@/views/Login')
}, {
path: '/register',
component: () => import('@/views/Register')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
2. 引入和注册
- vue3 在创建的时候如果选择安装路由,则会在 main.js 自动引入和注册
- 如果没有在创建项目时安装,则需要手动安装 vue-router,再在 main.js 中引入和注册
main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router' // 引入路由
import store from './store'
// 重置样式
import 'normalize.css'
import '@/assets/styles/common.css'
createApp(App).use(store).use(router).mount('#app')
3. App.vue 中设置路由出口
<template>
<!-- 头部组件 -->
<Header></Header>
<!-- 路由出口 -->
<router-view></router-view>
<!-- 底部组件 -->
<Footer></Footer>
</template>
<script setup>
import Header from '@/components/Header'
import Footer from '@/components/Footer'
</script>
<style lang="scss"></style>
3. 非路由组件和路由组件的区别
- 路由组件一般存放在
views
文件夹,非路由组件一般存放在components
文件夹 - 路由组件一般需要在router文件中进行注册(使用的即为组件的名字),非路由组件一般是以标签的形式使用
- 路由一旦被注册,不管是路由还是非路由组件都会拥有
$ toute、$ router
属性
4. 路由的跳转
4.1 声明式导航: router-link
- 必须带有
to
属性,用于指明要跳转的位置
<router-link to="/login">登录</router-link>
4.2 编程式导航:push、replace
import { useRouter } from 'vue-router'
const router = useRouter()
// 搜索按钮的回调函数
const handleSearch = () => {
router.push('/search')
}
4.3 两者区别
- 声明式导航能做的,编程式导航都可以做
- 编程式导航除了路由跳转,还可以处理其他业务逻辑
5. 路由元信息
- 通过配置 meta 字段
- 本项目中通过meta来控制 底部的显示与隐藏
<!-- 底部组件:在home、search页面显示,在登录、注册页面隐藏 -->
<Footer v-if="$route.meta.showFooter"></Footer>
const routes = [
// 重定向:运行项目时,立即定位到首页,而不是 /
{
path: '/',
redirect: '/home'
}, {
path: '/home',
component: () => import('@/views/Home'),
meta: {
showFooter: true
}
}, {
path: '/search',
component: () => import('@/views/Search'),
meta: {
showFooter: true
}
}, {
path: '/login',
component: () => import('@/views/Login'),
meta: {
showFooter: false
}
}, {
path: '/register',
component: () => import('@/views/Register'),
meta: {
showFooter: false
}
}
]
6. 路由传参
6.1 params参数
- 属于路径中的一部分,在配置路由时需要进行
占位
,如path:'/search/:id'
6.2 query参数
- 不属于路径中,不用在路由中进行占位,在路径中会自动展示为
?key=value&key1=value1
的拼接形式
6.3 路由传参的几种写法
6.3.1 字符串形式
```javascript
// 方法一:通过字符串直接传参
// params形式
router.push('/search/'+this.searchValue)
// query形式
router.push('/search?key='+this.searchValue)
// params+query
router.push('/search/'+this.searchValue+'?key='+this.searchValue.toUpperCase())
6.3.2 模板字符串
router.push(`/search/${this.searchValue}?k=${this.searchValue.toUpperCase()}`)
6.3.3 对象写法(最常用的)
// 通过name命名路由
{
name: 'search',
path: '/search/:keyword',
component: () => import('@/views/Search'),
meta: {
showFooter: true
}
}
// 方法三:对象的写法(常用的),要对路由命名(name)
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
// 搜索框的数据
const keyword = ref('')
// 搜索按钮的回调函数
const handleSearch = () => {
router.push({
name: 'search', //name要和路由中配置的name一致
params: {
keyword: keyword.value
},
query: {
key: keyword.value.toUpperCase()
}
})
}
6.4 路由传参的对象写法中的常见问题
6.4.1 对象写法中 path 和 params 结合使用会报错
- 对象写法中如果要用params参数,只能通过name指定跳转路由,不能用path
router.push({
path: '/search',
params: {
keyword: keyword.value
},
query: {
key: keyword.value.toUpperCase()
}
})
- 控制台会抛出警告
- URL路径中也没有正确添加params
6.4.2 如何指定params参数可传可不传
- 如果路由中配置了占位,但是不传params,路由不会进行跳转,并且控制台会报错
router.push({
name: 'search',
query: {
key: keyword.value.toUpperCase()
}
})
- 可以在占位时将可选的参数后面加上
问号?
,则表示该params参数可传可不传
{
...
path: '/search/:keyword?'
...
}
6.4.3 路由组件传递props(三种写法)
1. 布尔值的写法
{
name: 'search',
path: '/search/:keyword',
component: () => import('@/views/Search'),
meta: {
showFooter: true
},
props: true // 传递props
}
- 这种写法可以将
params
作为路由组件的属性,组件中可以通过defineProps接收params参数 - 这种写法只能接收 params参数
// search / index.vue
import { defineProps } from 'vue'
// 接收路由组件中的props
const props = defineProps({
keyword: {
type: String
}
})
console.log(props.keyword)
2. 对象写法
- 可以配置额外的参数
- 组件中可以通过 defineProps 接收路由中配置的props
{
name: 'search',
path: '/search/:keyword',
component: () => import('@/views/Search'),
// 对象写法
props: {
name: 'dudu',
age: 18
}
}
// search页面
import { defineProps } from 'vue'
// 接收路由组件中的props
const props = defineProps({
name: {
type: String
},
age: {
type: Number
}
})
console.log(props)
3. 函数写法
- 可以把
params
和query
参数传递给路由组件 - 组件中可以通过 defineProps 接收路由中配置的props
{
name: 'search',
path: '/search/:keyword',
component: () => import('@/views/Search'),
meta: {
showFooter: true
},
props: route => {
return {
keyword: route.params.keyword,
keyy: route.query.key
}
}
}