Vue3魔法手册 作者 张天禹 012_路由_(二)

037_路由-query参数

笔记

蓝色的是News组件,红色的是Detail组件

导航区和展示区

在 vue 里面,路由传参有两种参数 query 和 params

query传参就是在 如下绿色的路由跳转的地方加?,绿色是路由的具体规则路径

我们在路由规则后面加?然后在传具体参数,如下所示

a为key,哈哈为value,多组之间用&分割

用query将 数据传给了 Detail 组件

Detail 开始接收数据了 以前讲路由的时候就说了 route 是路由,router是路由器。

route 是路由 你有什么路径,我给你看什么组件。

router 是路由器 路由器是管理一个一个路由的

useRoute 是一个 hooks 我们还写了 useDog useSum

模板字符串

复制代码
<ul>
    <li v-for="news in newsList" :key="news.id">
        <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">
            {{ news.title }}
        </RouterLink>
    </li>
</ul>

模板字符串:
:to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`"

绿色为起始标签,中间红色的[{{news.title}}]是标签体,粉色的[:to="{}"]为标签属性

v-for标签内news当然可以使用

query传参的第一种写法 src/pages/News.vue

复制代码
<RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">
    {{ news.title }}
</RouterLink>

query传参的第二种写法 src/pages/News.vue

复制代码
<RouterLink 
    :to="{
        path:'/news/detail',
        query:{
            id: news.id,
            title: news.title,
            content: news.content
        }
    }">
    {{ news.title }}
 </RouterLink>

响应式对象参数直接解构,肯定出问题,会丢失响应式

你从一个响应式对象身上直接解构属性,属性就此失去响应式,如果你不响失去响应式,你就直接引入 toRes(),直接用toRefs()包裹一下属性,就不会失去原来数据的响应式属性了

此时的query也不对啊,还需要路由的 props 配置

有了 props,就可以轻松把query干掉

能让你干干净净的写 id,title,content等属性

_路由-query参数 实现代码如下

复制代码
1, src/pages/Detail.vue
<template>
	<ul class="news-list">
		<li>编号: {{ query.id }}</li>
		<li>标题: {{ query.title }}</li>
		<li>内容: {{ query.content }}</li>
		<!-- <li>编号: {{ $route.query.id }}</li>
		<li>标题: {{ $route.query.title }}</li>
		<li>内容: {{ $route.query.content }}</li> -->
	</ul>
</template>

<script setup lang="ts" name="Detail">
	// console.log('创建');
	import { useRoute } from 'vue-router';
	import { toRefs } from 'vue';
	let route = useRoute();
	// 解构query赋值给query对象
	let {query} = toRefs(route);

	// console.log('@', route);
	
</script>

<style scoped>
	.news-list {
		list-style: none;
		padding-left: 20px;
	}
	.news-list>li {
		line-height: 30px;
	}
</style>




2, src/pages/News.vue
<script setup lang="ts" name="News">
/*! @file
*******************************************************
<PRE>
文件实现功能      : 新闻详情页面
作 者            : mary
版本             : 1.0
-------------------------------------------------------
备注             : -
-------------------------------------------------------
修改记录  :
日期           版本         修改人      修改内容
2025/6/18      1.0          mary         创建
</PRE>
******************************************************/
import { reactive } from 'vue'
import {RouterView,RouterLink} from 'vue-router'

// defineOptions({name: ''})
//====================================================
// == 类型定义
const newsList = reactive([
    {id:'zg01',title:'很好的抗癌食物',content:'西兰花'},
    {id:'zg02',title:'如何一夜暴富',content:'学IT'},
    {id:'zg03',title:'震惊,万万没想到',content:'明天是周一'},
    {id:'zg04',title:'好消息!好消息!',content:'快过年了'},
])


//====================================================
// == 初始化


//====================================================
//== 事件处理
</script>

<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- 第一种写法: -->
                <!-- <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">
                    {{ news.title }}
                </RouterLink> -->
                <!-- 第二种写法: -->
                 <RouterLink 
                    :to="{
                        // name: 'detail', // 路由名称,可以不写,默认就是当前路由的name属性值
                        path:'/news/detail', // 路由路径,可以不写,默认就是当前路由的path属性值
                        query:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                    }">
                    {{ news.title }}
                 </RouterLink>
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>        
    </div>
</template>


<style scoped>
    /*新闻*/
    .news {
        padding: 0 20px;
        display: flex;
        justify-content: space-between;
        height: 100%;
    }
    .news ul {
        margin-top: 30px;
        /* list-style: none; 隐藏 ul 小圆点*/
        padding-left: 10px;
    }
    .news li::marker {
        /* ul 小圆点样式 */
        color: #64967E;
    }
    .news li>a {
        font-size: 18px;
        line-height: 40px;
        text-decoration: none;
        color: #64967E;
        text-shadow: 0 0 1px rgb(0, 84, 0);
    }
    .news-content {
        width: 70%;
        height: 90%;
        border: 1px solid;
        margin-top: 20px;
        border-radius: 10px;
    }
</style>




3, src/router/index.ts
// 创建一个路由器,并暴露出去

// 第一步: 引入vue-router模块的createRouter方法
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'

// 第三步:引入一个一个可能要呈现的组件,也就是页面组件
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'



// 第二步: 创建路由器
const router = createRouter({
    history:createWebHistory(), // 路由器的工作模式
    // history:createWebHashHistory(), // 路由器的工作模式
    routes:[    // 一个一个路由规则 路由规则数组
        {
			path: "/",
			redirect: "/home" // 重定向
		},
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'news',
            path:'/news',
            component:News,
            // 添加一个子集属性children,在里面写子路由规则数组
            children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
                {
                    name:'detail',
                    path:'detail',
                    component:Detail
                },
            ]
        },
        {
            name:'about',
            path:'/about',
            component:About
        },        
    ]
})

// 第四步: 把创建的路由器暴露出去
export default router;

038_路由-params参数

备注1: 传递 params 参数时,若使用 to 的对象写法,必须使用 name 配置项,不能用path
备注2: 传递 params 参数时,需要提前在规则中占位。
params参数
复制代码
1, 传递参数
<!--跳转并携带params参数(to的字符串写法)-->
<!-- params传参的第一种写法 -->
<RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
    {{ news.title }}
</RouterLink> 

<!--跳转并携带params参数(to的对象写法)-->
<!-- params传参的第二种写法 -->
<RouterLink 
    :to="{
        name:'detail', 
        params:{
            id: news.id,
            title: news.title,
            content: news.content
        }
}">
    {{ news.title }}
</RouterLink>  


2, 接收参数
import { useRoute } from 'vue-router';
const route = useRoute();
console.log(route);

备注1:  传递 params 参数时,若使用 to 的对象写法,必须使用 name 配置项,不能用path
备注2:  传递 params 参数时,需要提前在规则中占位。

笔记

params传参 直接在路径'/news/detail/'后添加你要传的参数,如下图所示

在 params 里面红色的'/news/detail'为路径,绿色的 '/哈哈/您好/嘿嘿' 是params的传参。

params 返回没有这样的路由规则,找不到与之对应的,你心里明白'/哈哈/您好/嘿嘿' 是params的传参,但是路由的规则不明白

路由规则不明白,params的传参,继续找,就没有找到,就报警了,所以对于params你确实可以这样写传参,但是你必须提前到路由里面去占位,比如 "path:'detail/:id/:title/:content',"

params参数原理:拿到浏览器上的路径去路由中去找去匹配

'/哈哈/您好/嘿嘿' 是params的传参,去对应的路由寻找,'哈哈,您好,嘿嘿'他们都是参数

接收参数

query传参必须是 key=value还得通过&链接

query 传参路径里面能体现传参,Detail也能正常跳转

params传参的第一种方式:params传参,在router/index.js中配置路由时,使用动态路径参数 :id,:title,:content 代码如下

复制代码
{
    name:'news',
    path:'/news',
    component:News,
    // 添加一个子集属性children,在里面写子路由规则数组
    children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
        {
            name:'detail',
            path:'detail/:id/:title/:content',
            component:Detail
        },
    ]
},

params传参的第一种写法 src/pages/News.vue

复制代码
<ul>
    <li v-for="news in newsList" :key="news.id">
        <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
            {{ news.title }}
        </RouterLink>                
    </li>
</ul>
params传参的第二种写法 src/pages/News.vue
params传参只能用name传参,不能用path传参 不能传对象和数组 路由(src/router/index.ts)里面传什么参数,接收(src/pages/Detail.vue)的时候就得写什么参数
params传参 必须做三件事情
复制代码
1,路由传参:占位 src/router/index.ts
{
    name:'news',
    path:'/news',
    component:News,
    // 添加一个子集属性children,在里面写子路由规则数组
    children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
        {
            name:'detail',
            path:'detail/:id/:title/:content',
            component:Detail
        },
    ]
},

2, src/pages/News.vue 导航传参:
 <!-- 导航区 -->
<ul>
    <li v-for="news in newsList" :key="news.id">
        <!-- params传参的第一种方式:params传参,在router/index.js中配置路由时,使用动态路径参数 :id -->
        <!-- params传参的第二种方式:params传参,在router/index.js中配置路由时,使用占位符 -->

        <!-- params传参的第一种写法 -->
        <!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
            {{ news.title }}
        </RouterLink>     -->
        <!-- params传参的第二种写法 -->
    <RouterLink 
        :to="{  // 只能用name传参,不能用path传参 不能传对象和数组
            name:'detail', 
            params:{
                id: news.id,
                title: news.title,
                content: news.content
            }
    }">
            {{ news.title }}
        </RouterLink>             
    </li>
</ul>


3, 接收参数: 去 src/pages/Detail 
原则:路由(src/router/index.ts)里面传什么参数,接收(src/pages/Detail.vue)的时候就得写什么参数
<template>
	<ul class="news-list">
		<li>编号: {{ route.params.id }}</li>
		<li>标题: {{ route.params.title }}</li>
		<li>内容: {{ route.params.content }}</li>
	</ul>
</template>

<script setup lang="ts" name="Detail">
	import { useRoute } from 'vue-router';
	const route = useRoute();
	console.log(route);
</script>

动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数

可选的动态路由参数 在参数后面添加? 就可以实现

复制代码
{
    name:'news',
    path:'/news',
    component:News,
    // 添加一个子集属性children,在里面写子路由规则数组
    // 动态路由参数 :id/:title/:content? 问号表示可选的动态路由参数,也就是可有可无的动态路由参数
    children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
        {
            name:'detail',
            path:'detail/:id/:title/:content?', 
            component:Detail
        },
    ]
},

params 接收参数的写法 src/pages/Detail.vue

复制代码
<template>
	<ul class="news-list">
		<li>编号: {{ route.params.id }}</li>
		<li>标题: {{ route.params.title }}</li>
		<li>内容: {{ route.params.content }}</li>
	</ul>
</template>

<script setup lang="ts" name="Detail">
	import { useRoute } from 'vue-router';
	const route = useRoute();
	console.log(route);
</script>

query传参 必须做三件事情

复制代码
1, 去 src/router/index.ts 配置路由项目
{
    name:'news',
    path:'/news',
    component:News,
    children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
        {
            name:'detail',
            path:'detail', // query传参 动态路由参数 
            // path:'detail/:id/:title/:content?',//params传参 动态路由参数 
            component:Detail,
            props(route) {
                return route.query 
            }
        },
    ]
},


2, 去 src/pages/News.vue
<RouterLink 
    :to="{
        path:'/news/detail', 
        // name:'detail', 
        query:{
            id: news.id,
            title: news.title,
            content: news.content
        }
    }">
    {{ news.title }}
</RouterLink>


3, 去 src/pages/Detail.vue 添加如下代码
<script setup lang="ts" name="Detail">
	defineProps(['id', 'title', 'content'])
</script>

如果是query参数,绿色箭头的地方既可以用name写法,也可以用path写法

如果是params参数,绿色箭头的地方只能用name写法

params占位的时候是什么名,到接收的地方就是什么名

_路由-params参数 实现代码如下

复制代码
1, src/pages/News.vue
<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- params传参的第一种方式:params传参,在router/index.js中配置路由时,使用动态路径参数 :id -->
                <!-- params传参的第二种方式:params传参,在router/index.js中配置路由时,使用占位符 -->

                <!-- params传参的第一种写法 -->
                <!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
                    {{ news.title }}
                </RouterLink>     -->
                <!-- params传参的第二种写法 -->
                <RouterLink 
                    :to="{
                        name:'detail', 
                        params:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                }">
                    {{ news.title }}
                </RouterLink>             
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>        
    </div>
</template>

<script setup lang="ts" name="News">
    import { reactive } from 'vue'
    import {RouterView,RouterLink} from 'vue-router'

    const newsList = reactive([
        {id:'zg01',title:'很好的抗癌食物',content:'西兰花'},
        {id:'zg02',title:'如何一夜暴富',content:'学IT'},
        {id:'zg03',title:'震惊,万万没想到',content:'明天是周一'},
        {id:'zg04',title:'好消息!好消息!',content:'快过年了'},
    ])
</script>

<style scoped>
    /*新闻*/
    .news {
        padding: 0 20px;
        display: flex;
        justify-content: space-between;
        height: 100%;
    }
    .news ul {
        margin-top: 30px;
        /* list-style: none; 隐藏 ul 小圆点*/
        padding-left: 10px;
    }
    .news li::marker {
        /* ul 小圆点样式 */
        color: #64967E;
    }
    .news li>a {
        font-size: 18px;
        line-height: 40px;
        text-decoration: none;
        color: #64967E;
        text-shadow: 0 0 1px rgb(0, 84, 0);
    }
    .news-content {
        width: 70%;
        height: 90%;
        border: 1px solid;
        margin-top: 20px;
        border-radius: 10px;
    }
</style>




2, src/pages/Detail.vue
<template>
	<ul class="news-list">
		<li>编号: {{ route.params.id }}</li>
		<li>标题: {{ route.params.title }}</li>
		<li>内容: {{ route.params.content }}</li>
	</ul>
</template>

<script setup lang="ts" name="Detail">
	import { useRoute } from 'vue-router';
	const route = useRoute();
	console.log(route.params);
</script>

<style scoped>
	.news-list {
		list-style: none;
		padding-left: 20px;
	}
	.news-list>li {
		line-height: 30px;
	}
</style>





3, src/router/index.ts
// 创建一个路由器,并暴露出去

// 第一步: 引入vue-router模块的createRouter方法
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'

// 第三步:引入一个一个可能要呈现的组件,也就是页面组件
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'



// 第二步: 创建路由器
const router = createRouter({
    history:createWebHistory(), // 路由器的工作模式
    // history:createWebHashHistory(), // 路由器的工作模式
    routes:[    // 一个一个路由规则 路由规则数组
        {
			path: "/",
			redirect: "/home" // 重定向
		},
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'news',
            path:'/news',
            component:News,
            // 添加一个子集属性children,在里面写子路由规则数组
            // 动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数
            children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
                {
                    name:'detail',
                    path:'detail/:id/:title/:content?', // 动态路由参数 :id/:title/:content
                    component:Detail
                },
            ]
        },
        {
            name:'about',
            path:'/about',
            component:About
        },        
    ]
})

// 第四步: 把创建的路由器暴露出去
export default router;

039_路由-props配置

4.9 [路由的 props 配置]
作用: 让路由组件更方便的收到参数(可以将路由参数作为 props 传给组件)
复制代码
{
	name: 'xiang',
	path: 'detail/:id/:title/:content',
	component: Detail,
	
	// props 的对象写法,作用:把对象中的每一组key-value作为 props 传给Detail组件
	// props: {a:1,b:2,c:3}
	
	// props的布尔值写法,作用:把收到了每一组params参数,作为 props 传给Detail组件
	// props:true
	
	// props的函数写法,作用:把返回的对象中每一组key-value作为props传给Detail组件
	props(route) {
		return route.query
	}
}

笔记

当你点击'新闻'(src/pages/News.vue),他就会去寻找名字为'xiang'的路由,同时带着三个参数 id,title,content去(src/router/index.ts)

到(src/router/index.ts)找到了名字为 'xiang'的路由需要传(id,title,content)红色框里面的三个参数

接下来找到是Detail组件,相当于<Detail />组件

相当于你自己写了一个Detail组件

接下来 props相当于Detail组件传入 id=?? title=?? content=??

只要我们加上 props:true这一行,就是路由收到的所有参数

路由收到的所有参数全部都传给了 props 组件了

黄色是占位收到的 props 参数

绿色的是props:true这行代码底层帮你传给组件的参数

你收到了哪些参数,defineProps就给你传哪些传数

如何实现props传参

复制代码
1, 去 src/router/index.ts 文件去添加 props:true 这一行
{
    name:'news',
    path:'/news',
    component:News,
    // 添加一个子集属性children,在里面写子路由规则数组
    // 动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数
    children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
        {
            name:'detail',
            path:'detail/:id/:title/:content?', // 动态路由参数 :id/:title/:content
            component:Detail,
            props:true // 开启props传参,这样就可以在Detail组件中使用this.$route.params来获取动态路由参数了
        },
    ]
},


2, 去 src/pages/Detail.vue 通过 defineProps() 接收参数 你收到 props 哪些参数,他就给你传哪些参数
<script setup lang="ts" name="Detail">
	defineProps(['id', 'title', 'content'])	
</script>

使用 props 传参最优雅

首先去路由设置开启 props:true 传参

如果未开启 props:true 下面就真是[<Detail />]组件传参,数据就收不到。可以测试一下。

没有设置组件路由 props:true,就收不到数据

props参数的三种写法

复制代码
// 第一种写法: 将路由收到的所有parans参数作为props传递给Detail路由组件
props:true

qwe就是 route

如果你传的是params,就直接使用props:true就OK

复制代码
1, 去 src/pages/Detail.vue 添加 params 传参
<RouterLink 
    :to="{
        name:'detail', 
        params:{
            id: news.id,
            title: news.title,
            content: news.content
        }
    }">
    {{ news.title }}
</RouterLink>          


2, 去 src/router/index.ts 添加
props:true


3, 去 src/pages/Detail.vue 添加如下代码
<script setup lang="ts" name="Detail">	
	defineProps(['id', 'title', 'content'])	
</script>

如果你传的是query,你写如下函数

复制代码
1, 去 src/pages/Detail.vue 添加 query 传参
<RouterLink 
    :to="{
        name:'detail', 
        query:{
            id: news.id,
            title: news.title,
            content: news.content
        }
    }">
    {{ news.title }}
</RouterLink>


2, 去 src/router/index.ts 
props(route) {
    return route.query//将路由收到的所有query参数作为props传递给Detail路由组件
    //return route.params // 将路由收到的所有parans参数作为props传递给Detail路由组件
}


3, 去 src/pages/Detail.vue 添加如下代码
<script setup lang="ts" name="Detail">	
	defineProps(['id', 'title', 'content'])	
</script>

只要以后你走这个绿色规则,底层逻辑一定是

复制代码
<Detail a=100,b=200,c=300 />

_路由-props配置 实现代码如下

复制代码
1, src/pages/News.vue
<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- params传参的第一种方式:params传参,在router/index.js中配置路由时,使用动态路径参数 :id -->
                <!-- params传参的第二种方式:params传参,在router/index.js中配置路由时,使用占位符 -->

                <!-- params传参的第一种写法 -->
                <!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
                    {{ news.title }}
                </RouterLink>     -->
                <!-- params传参的第二种写法 -->
                <!-- <RouterLink 
                    :to="{
                        name:'detail', 
                        params:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                    }">
                    {{ news.title }}
                </RouterLink>              -->
                <!-- query传参的第三种写法 -->
                 <RouterLink 
                    :to="{
                        path:'/news/detail', 
                        // name:'detail', 
                        query:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                    }">
                    {{ news.title }}
                </RouterLink>
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>        
    </div>
</template>

<script setup lang="ts" name="News">
    import { reactive } from 'vue'
    import {RouterView,RouterLink} from 'vue-router'

    const newsList = reactive([
        {id:'zg01',title:'很好的抗癌食物',content:'西兰花'},
        {id:'zg02',title:'如何一夜暴富',content:'学IT'},
        {id:'zg03',title:'震惊,万万没想到',content:'明天是周一'},
        {id:'zg04',title:'好消息!好消息!',content:'快过年了'},
    ])
</script>

<style scoped>
    /*新闻*/
    .news {
        padding: 0 20px;
        display: flex;
        justify-content: space-between;
        height: 100%;
    }
    .news ul {
        margin-top: 30px;
        /* list-style: none; 隐藏 ul 小圆点*/
        padding-left: 10px;
    }
    .news li::marker {
        /* ul 小圆点样式 */
        color: #64967E;
    }
    .news li>a {
        font-size: 18px;
        line-height: 40px;
        text-decoration: none;
        color: #64967E;
        text-shadow: 0 0 1px rgb(0, 84, 0);
    }
    .news-content {
        width: 70%;
        height: 90%;
        border: 1px solid;
        margin-top: 20px;
        border-radius: 10px;
    }
</style>





2, src/pages/Detail.vue
<template>
	<ul class="news-list">
		<li>编号: {{ id }}</li>
		<li>标题: {{ title }}</li>
		<li>内容: {{ content }}</li>
	</ul>
</template>

<script setup lang="ts" name="Detail">
	defineProps(['id', 'title', 'content'])
</script>

<style scoped>
	.news-list {
		list-style: none;
		padding-left: 20px;
	}
	.news-list>li {
		line-height: 30px;
	}
</style>






3, src/router/index.ts

// 创建一个路由器,并暴露出去

// 第一步: 引入vue-router模块的createRouter方法
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'

// 第三步:引入一个一个可能要呈现的组件,也就是页面组件
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'



// 第二步: 创建路由器
const router = createRouter({
    history:createWebHistory(), // 路由器的工作模式
    // history:createWebHashHistory(), // 路由器的工作模式
    routes:[    // 一个一个路由规则 路由规则数组
        {
			path: "/",
			redirect: "/home" // 重定向
		},
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'news',
            path:'/news',
            component:News,
            // 添加一个子集属性children,在里面写子路由规则数组
            // 动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数
            children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
                {
                    name:'detail',
                    path:'detail', // query传参 动态路由参数 
                    // path:'detail/:id/:title/:content?', // params传参 动态路由参数 :id/:title/:content
                    component:Detail,

                    // 第一种写法: 将路由收到的所有parans参数作为props传递给Detail路由组件
                    // props:true // 开启props传参,这样就可以在Detail组件中使用this.$route.params来获取动态路由参数了

                    // 第二种写法: 函数写法 可以自己决定将什么参数作为props传递给Detail路由组件
                    props(route) {
                        return route.query // 将路由收到的所有query参数作为props传递给Detail路由组件
                        // return route.params // 将路由收到的所有parans参数作为props传递给Detail路由组件
                    }
                    // props: (route) => ({id: route.params.id, title: route.params.title})
                    // props: (route) => ({...route.params}) // 展开运算符,将对象中的所有属性都展开到新的对象中
                    // 第三种写法: 对象写法n基本不用 将路由收到的所有parans参数作为props传递给Detail路由组件,但是会多一些额外的属性,比如params,query等
                    // props:(route)=>({...route.params,...route.query})
                    // props: {
                    //     a:100,
                    //     b:200,
                    //     c:300
                    // }
                },
            ]
        },
        {
            name:'about',
            path:'/about',
            component:About
        },        
    ]
})

// 第四步: 把创建的路由器暴露出去
export default router;

040_路由-replace属性

4.10 [replace属性]
复制代码
1, 作用: 控制路由跳转时操作浏览器历史记录的模式。
2, 浏览器的历史记录有两种写入方式: 分别为 push 和 replace
	a, push 是追加历史记录(默认值)。
	b, replace 是替换当前记录。
3, 开启 replace 模式:
<RouterLink replace ...>News</RouterLink>

笔记

路由器跳转时会操作浏览器历史记录,路由器操作浏览器的历史记录有两个动作,一个是push,一个是replace,push相当于有指针,一直指着栈顶,就是你最后看的一个东西,可以借助浏览器的前进后退,就可以调整小指针。

可以借助浏览器的前进,后退就可以调整小指针。

点击后退箭头,小指针就调整到下面位置,这就是push模式。push就是推入栈内。

replace你现在看的是唯品会,过一会儿看的是今日头条,今日头条就把唯品会覆盖掉。这就是replace模式。replace就是替换的意思。

在导航区添加 replace 此时路由器就变成了replace模式

你希望他看完路由回不去,就用replace模式,一般情况下我们都用push模式。

_路由-replace属性 实现代码如下

复制代码
1, src/App.vue
<template>
  <div class="app">
    <!-- 标题 -->
    <Header></Header>
    <!-- 导航区 -->
    <div class="navigate">
      <!--第一种: to的字符串写法-->
      <!-- <RouterLink to="/home" active-class="active">首页</RouterLink>
      <RouterLink to="/news" active-class="active">新闻</RouterLink>
      <RouterLink to="/about" active-class="active">关于</RouterLink> -->
      <!--第二种: to的对象写法 path跳转-->
      <!-- <RouterLink :to="{path:'/home'}" active-class="active">首页</RouterLink>
      <RouterLink :to="{path:'/news'}" active-class="active">新闻</RouterLink>
      <RouterLink :to="{path:'/about'}" active-class="active">关于</RouterLink> -->
      <!--第三种: to的对象写法 名字跳转-->
      <RouterLink replace :to="{name:'home'}" active-class="active">首页</RouterLink>
      <RouterLink replace :to="{name:'news'}" active-class="active">新闻</RouterLink>
      <RouterLink replace :to="{name:'about'}" active-class="active">关于</RouterLink>
    </div>
    <!-- 展示区 -->
    <div class="main-content">
      <!-- 占位符,此处将来要展示不同的组件内容 -->
      <RouterView></RouterView>
      <!-- 此处以后可能要展示各种组件内容,到底展示哪个组件,取决于路由的匹配结果 -->
    </div>
  </div>
</template>

<script setup lang="ts" name="App">
  import { RouterView,RouterLink } from 'vue-router';
  import Header from '@/components/Header.vue';
</script>

<style scoped>
	/*App*/
  .navigate {
    display: flex;
    justify-content: space-around;
    margin: 0 100px;
  }

  .navigate a {
    display: block;
    text-align: center;
    width: 90px;
    height: 40px;
    line-height: 40px;
    border-radius: 10px;
    background-color: gray;
    text-decoration: none;
    color: white;
    font-size: 18px;
    letter-spacing: 5px;
  }

  .navigate a.active {
    background-color: #64967E;
    color: #ffc268;
    font-weight: 900;
    text-shadow: 0 0 1px black;
    font-family: 微软雅黑;
  }

  .main-content {
    margin: 0 auto;
    margin-top: 30px;
    border-radius: 10px;
    width: 90%;
    height: 400px;
    border: 1px solid;
  }
</style>

041_路由-编程式路由导航

4.11 [编程式导航]
路由组件的两个重要的属性: route和router变成了两个hooks
复制代码
import {useRoute,useRouter} from 'vue-router'

const route = useRoute()
const router = useRouter()

console.log(route.query)
console.log(route.params)
console.log(router.push)
console.log(router.replace)

笔记

到目前为止,所有的导航区都是用RouterLink写的

下面三个 首页 新闻 关于 都是导航区 效果-代码

这些新闻也是导航,也是用RouterLink写的 效果-代码

RouterLink他是一个组件,浏览器他认识h1,h2,h3,但是他不认识RouterLink标签。

RouterLink标签最终会转成html标签===>是a标签

如果你只会RouterLink去跳转路由,意味着你所有的导航只能是a元素。

使用RouterLink标签根本就无法实现====>需求: 首页看3秒钟自动跳转到新闻。我们该如何处理?

3秒钟打印@ 代码-效果

绿色这里使用RouterLink实现跳转,这是根本就不可能的事情,因为RouterLink是结构标签。把结构标签放在脚本里面,没有这样的用法。你会发现你是无法进行下去的。

我们的需求是: 在这里编写一段代码让路由实现跳转到/news页面,此时不再是RouterLink==>a标签了。此时就涉及到编程式路由导航。

脱离RouterLink实现路由跳转,就是编程式路由导航。

一旦调用 router 路由器,你想去哪里就去哪里

一下代码实现需求: 进入首页,3秒钟以后跳转到新闻页面

路由跳转的时候有两个动作 :
push(跳转时留下历史记录) 和
replace(跳转时直接替换,没有留下历史记录)

这才是开发时常用的编程式路由导航

只有你输入正确的用户名和密码才能跳转到个人中心,都需要使用如下编程式路由导航。

在开发中,编程式路由导航是使用频率要远远大于RouterLink导航

在绿色的部分有四个小按钮,只要一点击就可以查看新闻.

绿色的RouterLink是页面中的一个一个红色导航 代码-效果

点击就能看详情 代码-详情

展示新闻详情

push() 里面写什么,to能写什么,push()括号就能写什么。

to 的属性写法,to能写的,push()也能写。

to有两种写法: 1,字符串写法,2, 对象写法。

你摸到了路由器router,你调 push() 你也想跳转路由,上面 to 可以实现跳转路由

既然to是跳转路由,push()也是跳转路由,他俩语法是统一的,所以push()里面传字符串和对象都可以。

news的使用范围

news 传参

编程式跳转push(?) 跟 to里面的写法一模一样

总结: 编程式导航的场景

1, 只有符合某些条件,我们才跳转,不是说用户一点击,我们就跳转,我们不让你一点击就跳转,到十点整自动跳转到秒杀路由,只有用户登录成功才跳转到个人中心,这种场景只能用编程式导航。

2, 鼠标滑过一个东西,我们就跳转,我们就得用编程式导航,总之我们不想用RouterLink的时候,也想实现路由跳转,就得用编程式路由导航。

_路由-编程式路由导航 实现代码如下

复制代码
1, src/pages/Home.vue
<template>
    <div class="home">
        <img src="http://www.atguigu.com/images/index_new/logo.png" alt="">
    </div>
</template>

<script setup lang="ts" name="Home">
    import {onMounted} from 'vue'
    import {useRouter} from 'vue-router'

    const router = useRouter()

    onMounted(() => {
        setTimeout(() => {
            // 在这里编写一段代码让路由实现跳转到/news页面           
            router.push('/news')
        }, 3000)
    })
</script>

<style scoped>
    .home {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100%;
    }
</style>




2, src/pages/News.vue
<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <!-- params传参的第一种方式:params传参,在router/index.js中配置路由时,使用动态路径参数 :id -->
                <!-- params传参的第二种方式:params传参,在router/index.js中配置路由时,使用占位符 -->

                <!-- params传参的第一种写法 -->
                <!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">
                    {{ news.title }}
                </RouterLink>     -->
                <!-- params传参的第二种写法 -->
                <!-- <RouterLink 
                    :to="{
                        name:'detail', 
                        params:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                    }">
                    {{ news.title }}
                </RouterLink>              -->
                <!-- query传参的第三种写法 -->


                <button @click="showNewsDetail(news)">查看新闻</button>
                <RouterLink 
                    :to="{
                        //path:'/news/detail', 
                        name:'detail', 
                        query:{
                            id: news.id,
                            title: news.title,
                            content: news.content
                        }
                    }">
                    {{ news.title }}
                </RouterLink>
            </li>
        </ul>
        <!-- 展示区 -->
        <div class="news-content">
            <RouterView></RouterView>
        </div>        
    </div>
</template>

<script setup lang="ts" name="News">
    import { reactive } from 'vue'
    import {RouterView,RouterLink,useRouter} from 'vue-router'

    const newsList = reactive([
        {id:'zg01',title:'很好的抗癌食物',content:'西兰花'},
        {id:'zg02',title:'如何一夜暴富',content:'学IT'},
        {id:'zg03',title:'震惊,万万没想到',content:'明天是周一'},
        {id:'zg04',title:'好消息!好消息!',content:'快过年了'},
    ])

    const router = useRouter()

    interface NewsInter {
        id: string,
        title: string,
        content: string,
    }

    function showNewsDetail(news:NewsInter) {
        router.push({
            //path:'/news/detail', 
            name:'detail', 
            query:{
                id: news.id,
                title: news.title,
                content: news.content
            }
        })
    }
</script>

<style scoped>
    /*新闻*/
    .news {
        padding: 0 20px;
        display: flex;
        justify-content: space-between;
        height: 100%;
    }
    .news ul {
        margin-top: 30px;
        /* list-style: none; 隐藏 ul 小圆点*/
        padding-left: 10px;
    }
    .news li::marker {
        /* ul 小圆点样式 */
        color: #64967E;
    }
    .news li>a {
        font-size: 18px;
        line-height: 40px;
        text-decoration: none;
        color: #64967E;
        text-shadow: 0 0 1px rgb(0, 84, 0);
    }
    .news-content {
        width: 70%;
        height: 90%;
        border: 1px solid;
        margin-top: 20px;
        border-radius: 10px;
    }
</style>





3, src/router/index.ts
// 创建一个路由器,并暴露出去

// 第一步: 引入vue-router模块的createRouter方法
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'

// 第三步:引入一个一个可能要呈现的组件,也就是页面组件
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'



// 第二步: 创建路由器
const router = createRouter({
    history:createWebHistory(), // 路由器的工作模式
    // history:createWebHashHistory(), // 路由器的工作模式
    routes:[    // 一个一个路由规则 路由规则数组
        {
			path: "/",
			redirect: "/home" // 重定向
		},
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'news',
            path:'/news',
            component:News,
            // 添加一个子集属性children,在里面写子路由规则数组
            // 动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数
            children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
                {
                    name:'detail',
                    path:'detail', // query传参 动态路由参数 
                    // path:'detail/:id/:title/:content?', // params传参 动态路由参数 :id/:title/:content
                    component:Detail,

                    // 第一种写法: 将路由收到的所有parans参数作为props传递给Detail路由组件
                    // props:true // 开启props传参,这样就可以在Detail组件中使用this.$route.params来获取动态路由参数了

                    // 第二种写法: 函数写法 可以自己决定将什么参数作为props传递给Detail路由组件
                    props(route) {
                        return route.query // 将路由收到的所有query参数作为props传递给Detail路由组件
                        // return route.params // 将路由收到的所有parans参数作为props传递给Detail路由组件
                    }
                    // props: (route) => ({id: route.params.id, title: route.params.title})
                    // props: (route) => ({...route.params}) // 展开运算符,将对象中的所有属性都展开到新的对象中
                    // 第三种写法: 对象写法n基本不用 将路由收到的所有parans参数作为props传递给Detail路由组件,但是会多一些额外的属性,比如params,query等
                    // props:(route)=>({...route.params,...route.query})
                    // props: {
                    //     a:100,
                    //     b:200,
                    //     c:300
                    // }
                },
            ]
        },
        {
            name:'about',
            path:'/about',
            component:About
        },        
    ]
})

// 第四步: 把创建的路由器暴露出去
export default router;

042_路由-重定向

_路由-重定向 实现代码
复制代码
1, src/router/index.ts
// 创建一个路由器,并暴露出去

// 第一步: 引入vue-router模块的createRouter方法
import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'

// 第三步:引入一个一个可能要呈现的组件,也就是页面组件
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'



// 第二步: 创建路由器
const router = createRouter({
    history:createWebHistory(), // 路由器的工作模式
    // history:createWebHashHistory(), // 路由器的工作模式
    routes:[    // 一个一个路由规则 路由规则数组
        {
			path: "/",
			redirect: "/home" // 重定向
		},
        {
            name:'home',
            path:'/home',
            component:Home
        },
        {
            name:'news',
            path:'/news',
            component:News,
            // 添加一个子集属性children,在里面写子路由规则数组
            // 动态路由参数 :id/:title/:content? 表示可选的动态路由参数,也就是可有可无的动态路由参数
            children:[ // 子路由规则数组 子集路由前不需要写'/',否则会找不到路径
                {
                    name:'detail',
                    path:'detail', // query传参 动态路由参数 
                    // path:'detail/:id/:title/:content?', // params传参 动态路由参数 :id/:title/:content
                    component:Detail,

                    // 第一种写法: 将路由收到的所有parans参数作为props传递给Detail路由组件
                    // props:true // 开启props传参,这样就可以在Detail组件中使用this.$route.params来获取动态路由参数了

                    // 第二种写法: 函数写法 可以自己决定将什么参数作为props传递给Detail路由组件
                    props(route) {
                        return route.query // 将路由收到的所有query参数作为props传递给Detail路由组件
                        // return route.params // 将路由收到的所有parans参数作为props传递给Detail路由组件
                    }
                    // props: (route) => ({id: route.params.id, title: route.params.title})
                    // props: (route) => ({...route.params}) // 展开运算符,将对象中的所有属性都展开到新的对象中
                    // 第三种写法: 对象写法n基本不用 将路由收到的所有parans参数作为props传递给Detail路由组件,但是会多一些额外的属性,比如params,query等
                    // props:(route)=>({...route.params,...route.query})
                    // props: {
                    //     a:100,
                    //     b:200,
                    //     c:300
                    // }
                },
            ]
        },
        {
            name:'about',
            path:'/about',
            component:About
        },        
    ]
})

// 第四步: 把创建的路由器暴露出去
export default router;

重定向一般在一级路由实现

复制代码
{
    path: "/",
    redirect: "/home" // 重定向
},
相关推荐
木斯佳1 小时前
前端八股文面经大全:2026-01-29 字节-AIDP前端实习一面面经深度解析
前端·状态模式
We་ct2 小时前
LeetCode 100. 相同的树:两种解法(递归+迭代)详解
前端·算法·leetcode·链表·typescript
哆啦A梦15882 小时前
Vue3魔法手册 作者 张天禹 08_回顾TS中的-接口-泛型-自定义事件
前端·vue.js·typescript
星火开发设计2 小时前
序列式容器:list 双向链表的特性与用法
开发语言·前端·数据结构·数据库·c++·链表·list
014-code2 小时前
ESLint 详解
前端·eslint
xjf77112 小时前
TypDom框架分析
javascript·typescript·前端框架·typedom
GISer_Jing2 小时前
前端营销I(From AIGC)
前端·aigc·ai编程
明月_清风2 小时前
向 Native 借力:深度拆解 SIMD 加速与 Node.js 异步原生解析
前端·json
明月_清风2 小时前
无感监控:深度拆解监控 SDK 的性能平衡术与调度策略
前端·监控