Vue3——使用Vue Router实现路由

使用Vue Router实现路由

在单页Web应用中,整个项目只有一个HTML文件,不同视图(组件的模板)的内容都是在同一个页面中渲染的。当用户切换页面时,页面之间的跳转都是在浏览器端完成的,这时就需要使用前端路由。

1、路由基础

路由实际上就是一种映射关系。例如,多个选项卡之间的切换就可以使用路由功能来实现。在切换时,根据鼠标的单击事件显示不同的页面内容,这相当于事件和事件处理程序之间的映射关系。

1.1、引入Vue Router

在使用Vue Router之前需要在页面中进行引入,可以使用CDN方式引入Vue Router。代码如下:

js 复制代码
<script src="https://unpkg.com/vue-router@next"></script>

如果在项目中使用Vue Router,则可以使用npm方式进行安装。在命令提示符窗口中输入如下命令:

shell 复制代码
 npm install vue-router@next --save

在安装Vue Router时,安装支持Vue 3.0版本的Vue Router需要使用vue-router@next,安装支持Vue 2.x版本的Vue Router需要使用vue-router。

1.2、基本用法

使用Vue.js创建的应用程序可以由多个组件组成,而VueRouter的作用是将每个路径映射到对应的组件,并通过路由进行组件之间的切换。

Vue.js路由的思想是通过不同的URL访问不同的内容。要想通过路由实现组件之间的切换,需要使用Vue Router提供的router-link组件,该组件用于设置一个导航链接, 通过设置to属性链接到一个目标地址,从而切换不同的HTML内容。

下面是一个实现路由的简单示例,实现步骤如下。

  1. 使用router-link组件设置导航链接,代码如下:
html 复制代码
<div id="app">
    <div>
        <!-- 使用router-link组件设置导航-->
        <!-- 通过to属性设置目标地址-->
        <!-- <router-link>默认被渲染成<a>标签-->
        <router-link to="/homepage">首页</router-link>    
        <router-link to="/course">课程</router-link>
        <router-link to="/read">读书</router-link>
    </div>
    <!-- 路由出口,路由匹配到的组件渲染的位置-->
    <router-view></router-view>
</div>

如果要将<router-link>渲染成其他标签,可以使用v-slot API完全定制<router-link>。例如,将<router-link>渲染成<button>标签,代码如下:

html 复制代码
<router-link to="/course" custom v-slot="{navigate}">
<button @click="navigate"@keypress.enter="navigate">课程</button></router-link>
  1. 通过<router-link>指定组件在何处渲染,代码如下:
html 复制代码
 <!-- 当单击链接时,会在<router-link>所在的位置渲染组件的模板内容。 -->
 <router-view></router-view>
  1. 定义路由组件,代码如下:
js 复制代码
    //定义路由组件,可以使用import从其他文件引入
    const homepage = {
        template: '<p>首页内容</p>'
    };
    const course = {
        template: '<p>课程页面内容</p>'
    };
    const read = {
        template: '<p>读书页面内容</p>'
    };
  1. 定义路由,将前面设置的链接和定义的组件一一对应,代码如下:
js 复制代码
    //定义路由,每个路由映射一个组件
    const routes = [
        {path: '/homepage', component: homepage},
        {path: '/course', component: course},
        {path: '/read', component: read}
    ];
  1. 创建VueRouter实例,将上一步定义的路由配置作为选项传递进来,代码如下:
js 复制代码
    //创建VueRouter实例,传入路由配置
    const router = VueRouter.createRouter({
        //提供要使用的history实现,这里使用hash history
        history: VueRouter.createWebHashHistory(),
        routes  //相当于routes: routes的缩写
    });
  1. 创建应用程序实例,调用use()方法,传入上一步创建的router对象,使整个应用程序具备路由功能,代码如下:
js 复制代码
    const vm = Vue.createApp({});
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');

到这里就完成了路由的配置。完整代码如下:

html 复制代码
<div id="app">
    <div>
        <!-- 使用router-link组件设置导航-->
        <!-- 通过to属性设置目标地址-->
        <!-- <router-link>默认被渲染成<a>标签-->
        <router-link to="/homepage">首页</router-link>    
        <router-link to="/course">课程</router-link>
        <router-link to="/read">读书</router-link>
    </div>
    <!-- 路由出口,路由匹配到的组件渲染的位置-->
    <router-view></router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    //定义路由组件,可以使用import从其他文件引入
    const homepage = {
        template: '<p>首页内容</p>'
    };
    const course = {
        template: '<p>课程页面内容</p>'
    };
    const read = {
        template: '<p>读书页面内容</p>'
    };

    //定义路由,每个路由映射一个组件
    const routes = [
        {path: '/homepage', component: homepage},
        {path: '/course', component: course},
        {path: '/read', component: read}
    ];

    //创建VueRouter实例,传入路由配置
    const router = VueRouter.createRouter({
        //提供要使用的history实现,这里使用hash history
        history: VueRouter.createWebHashHistory(),
        routes  //相当于routes: routes的缩写
    });
    const vm = Vue.createApp({});
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');
</script>

上述代码中,<router-link>会被渲染成<a>标签。例如,第一个<router-link>会被渲染成<ahref="#/homepage">首页。当单击第一个<router- link>对应的标签时,由于to属性的值是/homepage,因此实际的路径地址就是当前URL路径后加上#/homepage。这时,Vue会找到定义的路由routes中path为/homepage的路由,并将对应的组件homepage渲染到<router-view>中。运行结果如图所示。

1.3、动态路由匹配

在实际开发中,经常需要将匹配到的所有路由全部映射到同一个组件。例如,对于所有不同ID的新闻,都需要使用同一个组件News来渲染。那么,可以在路由路径中使用动态路径参数来满足这个需求。示例代码如下:

html 复制代码
<div id="app">
    <div>
        <router-link to="/news/1">新闻1</router-link>
        <router-link to="/news/2">新闻2</router-link>
    </div>
    <router-view></router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const News = {
        template: '<p>新闻ID:{{$route.params.id}}</p>'
    }
    const routes = [
        //动态路径参数,以冒号开头
        {path: '/news/:id', component: News}
    ]

    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    })
    const vm = Vue.createApp({});
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');
</script>

上述代码中,:id即为设置的动态路径参数。这时,像/news/1、/news/2这样的路径都会映射到相同的组件。当匹配到一个路由时,通过$route.params的方式可以获取参数值,并且可以在每个组件内使用。运行结果如图所示。

在同一个路由中可以有多个路径参数,它们将映射到$route.params中的相应字段。例如,路径为"/user/:username/post/:id"​,匹配路径为"/user/tom/post/10"​,则通过$route.params获取的值为:

js 复制代码
 { "username": "tom", "id": "10" }

1.4、命名路由

在某些时候,在进行路由跳转时,通过一个名称来标识路由会更方便一些。可以在创建VueRouter实例时,在routes配置中为某个路由设置名称。示例代码如下:

js 复制代码
const routes = [
	{
		path: '/news',
		name: 'news',//为路由设置名称
		component: News
	}
]

在设置了路由的名称后,要想链接到该路径,可以将<router-link>的to属性设置成一个对象,同时需要使用v-bind指令。代码如下:

html 复制代码
 <router-link :to="{ name : 'news'}">新闻</router-link>

这样,当单击"新闻"链接时,会跳转到/news路径的路由。

2、编程式导航

定义导航链接除了使用<router-link>创建<a>标签,还可以使用router实例的push()方法实现导航的功能。在Vue实例内部,通过$router可以访问路由实例,因此通过调用this.$router.push即可实现页面的跳转。

该方法的参数可以是一个字符串路径,还可以是一个描述跳转目标地址的对象。示例代码如下:

js 复制代码
//跳转到字符串表示的路径
this.$router.push('music')
//跳转到指定路径
this.$router.push({path: 'music'})
//跳转到指定命名的路由
this.$router.push({name: 'user'})
//跳转到带有查询参数的指定路径
this.$router.push({path: 'music', query: {id: '5'})
//跳转到带有查询参数的指定命名的路由
this.$router.push({name: 'user', params: {id: '1'}})

示例:实现新闻类别选项卡。

实现切换新闻类别选项卡的效果。页面中有"最新"​"热门"和"推荐"3个新闻类别选项卡,单击不同的类别选项卡,页面下方会显示不同的新闻信息。实现步骤如下。

  1. 定义<div>元素,并设置其id属性值为app,在该元素中定义一个id属性值为tabBox的div元素,然后在该元素中添加一个ul列表和一个div元素,ul列表用于显示3个选项卡,将选项卡对应的文本内容渲染到div元素的router-view中。代码如下:
html 复制代码
<div id="app">
    <div class="tabBox">
        <ul class="tab" :class="current">
            <li class="newest" @click="show('newest')">最新</li>
            <li class="hot" @click="show('hot')">热门</li>
            <li class="recommend" @click="show('recommend')">推荐</li>
        </ul>
        <div class="option">
            <router-view></router-view>
        </div>
    </div>
</div>
  1. 编写CSS代码,为页面元素设置样式
  2. 首先定义3个组件,然后定义路由,接着创建router实例,最后在创建的根组件实例中定义数据和方法。在定义的show方法中,通过push()方法跳转到指定名称的路由,从而实现选项卡下方文本内容的切换。代码如下:
html 复制代码
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const newest = {
        template: `<div>
            <ul class="newslist">
                <li>C语言零起点<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>每月18日会员福利日<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>明日之星-明日科技<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li> 
                <li>写给初学前端工程师的一封信<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>C语言零起点<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
                <li>Java零起点入门<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
            </ul>
        </div>`
    };
    const hot = {
        template: `<div>
            <ul class="newslist">
                <li>外星人登录地球<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>全部技能<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>HTML5+CSS3<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li> 
                <li>玩Java就这3件事<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>C#精彩编程200例<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
                <li>每天编程一小时<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
            </ul>
        </div>`
    };
    const recommend = {
        template: `<div>
            <ul class="newslist">
                <li>晒作品 赢学分<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>最新上线电子书<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>程序设计互联网+图书<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li> 
                <li>八年锤炼,打造经典<span class="top">【置顶】</span>
                    <span class="time">2023-05-01</span>
                </li>
                <li>专业讲师精心打造<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
                <li>让学习创造属于你的生活<span class="top">【置顶】</span>
                    <span class="time">2023-05-02</span>
                </li>
            </ul>
        </div>`
    };
    const routes = [
        {path: '', component: newest},
        {path: '/newest', name: 'newest', component: newest},
        {path: '/hot', name: 'hot', component: hot},
        {path: '/recommend', name: 'recommend', component: recommend}
    ];
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    });

    const vm = Vue.createApp({
        data() {
            return {
                current: 'newest'
            }
        },
        methods: {
            show: function(v) {
                switch(v) {
                    case 'newest':
                        this.current = 'newest';
                        this.$router.push({name: 'newest'});//跳转到名称是newest的路由
                        break;
                    case 'hot':
                        this.current = 'hot';
                        this.$router.push({name: 'hot'});//跳转到名称是hot的路由
                        break;
                    case 'recommend': 
                        this.current = 'recommend';
                        this.$router.push({name: 'recommend'});//跳转到名称是recommend的路由
                        break;
                }
            }
        }
    });
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');
</script>

运行上述代码,当单击不同的选项卡时,下方会显示对应的文本内容。结果如图所示。

3、嵌套路由

二级导航菜单一般是由嵌套的组件组合而成的。使用简单的路由不能实现这种需求,这时就需要使用嵌套路由实现导航功能。使用嵌套路由时,URL中各段动态路径会按某种结构对应嵌套的各层组件。

在前面的示例中,<router-view>是最顶层的出口,该出口用于渲染最高级路由匹配到的组件。同样,一个被渲染的组件的模板中可以包含嵌套的<router-view>。要在嵌套的出口中渲染组件,需要在定义路由时配置children参数。

例如有这样一个应用,代码如下:

html 复制代码
<div id="app">
    <router-view></router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const Music = {
        template: `<div>音乐</div>`
    }
    const routes = [
        {
            path: '/music',
            name: 'music',
            component: Music
        }
    ];
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    });
    const vm = Vue.createApp({
    });
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');
</script>

上述代码中,<router-view>是最顶层的出口,它会渲染一个最高级路由匹配到的组件。同样,在组件的内部也可以包含嵌套的<router-view>。例如,在Music组件的模板中添加一个<router-view>,代码如下:

html 复制代码
    const Music = {
        template: `<div>
                <span>音乐</span>
                <router-view></router-view>
            </div>`
    }

如果要在嵌套的出口中渲染组件,需要在定义路由时配置children参数。代码如下:

js 复制代码
    const routes = [
        {
            path: '/music',
            name: 'music',
            component: Music,
            children: [
                {
                    // /music/pop 匹配成功后,popMusic会被渲染在Music的<router-view>中
                    path: '/pop',
                    component: popMusic
                },
                {
                    // /music/rock 匹配成功后,rockMusic会被渲染在Music的<router-view>中
                    path: '/rock',
                    compnent: rockMusic
                }
            ]
        }
    ];

如果访问的路由不存在,则渲染组件的出口不会显示任何内容。这时可以提供一个空的路由。

在上述示例代码中添加一个空路由,代码如下:

js 复制代码
    const routes = [
        {
            path: '/music',
            name: 'music',
            component: Music,
            children: [
                {
                    // /music匹配成功后,popMusic会被渲染在Music的<router-view>中
                    path: '',
                    compenent: popMusic
                },
                {
                    // /music/pop 匹配成功后,popMusic会被渲染在Music的<router-view>中
                    path: '/pop',
                    component: popMusic
                },
                {
                    // /music/rock 匹配成功后,rockMusic会被渲染在Music的<router-view>中
                    path: '/rock',
                    compnent: rockMusic
                }
            ]
        }
    ];

示例:企业各部门的切换。

某企业按职能划分为研发中心和营销中心,每个中心下面又包括不同的部门。使用嵌套路由实现企业各部门切换的效果,实现步骤如下。

  1. 编写HTML代码,首先定义
    元素,并设置其id属性值为app,在该元素中应用<router-link>组件定义两个一级导航链接,并应用<router-view>渲染两个一级导航链接对应的组件内容。代码如下:
html 复制代码
<div id="app">
    <div class="nav">
        <ul>
            <li>
                <router-link to="/development">研发中心</router-link>
            </li>
            <li>
                <router-link to="/marketing">营销中心</router-link>
            </li>
        </ul>
    </div>
    <div class="content">
        <router-view></router-view>
    </div>
</div>
  1. 编写CSS代码,为页面元素设置样式。具体代码如下:
css 复制代码
<style>
    body{
        font-family: 微软雅黑;
    }
    a{
        text-decoration: none;
    }
    .nav{
        width: 300px;
        height: 30px;
        line-height: 30px;
        background: blue;
    }
    ul{
        list-style: none;
    }
    .nav ul li{
        float: left;
        margin-left: 20px;
    }
    .nav ul li a{
        color: white;
    }
    .content{
        clear: both;
    }
    .content ul li{
        float: left;
        margin-left: 20px;
        font-size: 14px;
    }
    h3{
        clear: both;
        margin-left: 30px;
        padding-top: 20px;
    }
</style>
  1. 定义两个一级导航链接对应的组件,在组件的模板中定义二级导航链接,然后定义嵌套路由,最后创建VueRouter实例和根组件实例。代码如下:
html 复制代码
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const Development = {
        template: `<div>
                <ul>
                    <li><router-link to="/development/design">设计部</router-link></li>
                    <li><router-link to="/development/technology">技术部</router-link></li>
                </ul>
                <router-view></router-view>
            </div>`
    } 
    const Marketing = {
        template: `<div>
                <ul>
                    <li><router-link to="/marketing/market">市场部</router-link></li>
                    <li><router-link to="/marketing/sale">市场部</router-link></li>
                    <li><router-link to="/marketing/logistics">市场部</router-link></li>
                </ul>
                <router-view></router-view>
            </div>`
    }
    const routes = [
        {
            path: '/',
            component: Development,
        },
        {
            path: '/development',
            component: Development,
            children: [
                {
                    path: 'design',
                    component: {
                        template: `<h3>Tony、Kelly</h3>`
                    }
                },
                {
                    path: 'technology',
                    component: {
                        template: `<h3>Tom、Jerry</h3>`
                    }
                }
            ]
        },
        {
            path: '/marketing',
            component: Marketing,
            children: [
                {
                    path: 'market',
                    component: {
                        template: `<h3>John、Alice</h3>`
                    }
                },
                {
                    path: 'sale',
                    component: {
                        template: `<h3>Rose、Jack</h3>`
                    }
                },
                {
                    path: 'logistics',
                    component: {
                        template: `<h3>Smith、Jenny</h3>`
                    }
                }
            ]
        }
    ]
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    });
    const vm = Vue.createApp({
    });
    //调用应用程序实例的use()方法,传入创建的router对象
    vm.use(router);
    vm.mount('#app');
</script>

运行上述代码,当单击"研发中心"中的"设计部"链接时,URL路由为/development/design,结果如图所示;

当单击"营销中心"中的"市场部"链接时,URL路由为/marketing/market,结果如图所示。

4、命名视图

有些页面布局分为顶部、左侧导航栏和主显示区三个部分。这就需要将每个部分定义为一个视图。为了在界面中同时展示多个视图,需要为每个视图(router-view)设置一个名称,通过名称渲染对应的组件。在界面中可以有多个单独命名的视图,而不是只有一个单独的出口。如果没有为router-view设置名称,那么它的名称默认为default。例如,在页面中设置三个视图,代码如下:

html 复制代码
<router-view class="top"></router-view>
<router-view class="left" name="left"></router-view>
<router-view class="main" name="main"></router-view>

一个视图需要使用一个组件进行渲染,因此对于同一个路由,多个视图就需要使用多个组件进行渲染。为上述三个视图应用组件进行渲染的代码如下:

js 复制代码
const routes = [
	{
		path: '/',
		components: {
			default: Top,
			left: Left,
			main: Main
		}
	}
]
const router = VueRouter.createRouter({
    history: VueRouter.createWebHashHistory(),
    routes
});
const vm = Vue.createApp({});
vm.use(router);
vm.mount('#app');

下面是一个应用多视图的示例,实现"首页"和"关于我们"两个栏目之间的切换。代码如下:

html 复制代码
<style>
    body{
        font-family: 微软雅黑;
        font-size: 14px;
    }
    a{
        text-decoration: none;
    }
    ul{
        list-style: none;
        width: 300px;
        height: 30px;
        line-height: 30px;
        background: green;
    }
    ul li{
        float: left;
        margin-left: 20px;
    }
    ul li a{
        color: white;
    }
    .left{
        float: left;
        width: 100px;
        height: 50px;
        padding-top: 10px;
        text-align: center;
        border-right: 1px solid #666666;
    }
    .main{
        float: left;
        width: 200px;
        padding: 20px;
    }
</style>
<div id="app">
    <ul>
        <li>
            <router-link to="/homepage">首页</router-link>
        </li>
        <li>
            <router-link to="/about">关于我们</router-link>
        </li>
    </ul>
    <router-view class="left" name="left"></router-view>
    <router-view class="main" name="main"></router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const HomeLeft = {
        template: `<div>行业咨询</div>`
    };
    const HomeRight = {
        template: `<div>
                <div>大数据时代长我数据分析技能</div>
                <div>编程超级魔卡强势来袭</div>
            </div>`
    };
    const AbountLeft = {
        template: `<div>
                <div>公司简介</div>
                <div>特色项目</div>
            </div>`
    };
    const AbountRight = {
        template: `<div>吉林省明日科技有限公司倾力打造</div>`
    };

    const routes = [
        {
            path: '/',
            //默认渲染的组件
            components: {
                left: HomeLeft,
                main: HomeRight
            }
        },
        {
            path: '/homepage',
            // /homepage匹配成功后渲染的组件
            components: {
                left: HomeLeft,
                main: HomeRight
            }
        },
        {
            path: '/about',
            // /about匹配成功后渲染的组件
            components: {
                left: AbountLeft,
                main: AbountRight
            }
        }
    ]
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    });
    const vm = Vue.createApp({
    });
    vm.use(router);
    vm.mount('#app');
</script>

5、高级用法

5.1、beforeEach钩子函数

beforeEach是Vue Router提供的一个钩子函数,该函数会在路由即将发生改变之前触发。使用beforeEach钩子函数,可以在路由发生变化时进行一些特殊的处理。该函数的语法如下:

js 复制代码
beforeEach((to, from, next) => {
 // ...
})
  • to:即将进入的目标路由对象。
  • from:当前导航即将离开的路由对象。
  • next:调用该方法后进入下一个钩子。

在设置网页标题时经常会用到beforeEach钩子函数。因为单页应用只有一个固定的HTML,当使用路由切换到不同页面时,HTML标题并不会发生变化。这时就可以使用beforeEach钩子函数来设置网页的标题。

示例:设置网页标题。

设置"注册"和"登录"两个链接,在切换路由时,实现设置网页标题的效果。当单击某个链接时,网页的标题也会随着变化。实现步骤如下。

  1. 定义<div>元素,并设置其id属性值为app,在该元素中定义一个class属性值为middle-box的div元素,然后在该元素中使用<router-link>组件定义"注册"和"登录"两个链接,并将对应的组件模板渲染到router-view中。下面应用<template>标签分别定义两个组件的模板。代码如下:
html 复制代码
<div id="app">
    <div class="middle-box">
        <span>
            <router-link to="/">注册</router-link>
            <router-link to="/login">登录</router-link>
        </span>
        <router-view></router-view>
    </div>
</div>
<template id="reg">
    <div>
        <form id="regform" name="form" method="post" action="" autocomplete="off">
            <div class="form-group">
                <label for="name">用户名:</label>
                <input name="name" id="name" type="text" class="from-control" placeholder="用户名">
            </div>
            <div class="form-group">
                <label for="password">密 码:</label>
                <input name="password" id="password" type="name" class="from-control" placeholder="密码">
            </div>
            <div class="form-group">
                <label for="password">确认密码:</label>
                <input name="password" id="password" type="name" class="from-control" placeholder="确认密码">
            </div>
            <div class="form-group">
                <div class="agreement">
                    <input type="checkbox" checked="checked">阅读并同意<a href="#">《注册协议》</a>
                </div>
            </div>
            <button type="submit" id="send" class="btn-primary">注 册</button>
        </form>
    </div>
</template>
<template id="log">
    <div>
        <form id="logform" name="form" method="post" action="" autocomplete="off">
            <div class="form-group">
                <label>账 号:</label>
                <input name="username" id="username" type="text" class="form-control" placeholder="用户名">
            </div>
            <div class="form-group">
                <label>密 码:</label>
                <input name="password" id="password" type="password" class="form-control" placeholder="密码">
            </div>
            <!-- 滑块区域 -->
             <div class="form-group">
                <div class="drag-out">
                    <span>按住滑块,拖动到最右侧</span>
                    <div class="drag-area">》</div>
                    <div class="drag-code"></div>
                </div>
             </div>
             <button type="submit" id="login" class="btn-primary">登 录</button>
        </form>
    </div>
</template>
  1. 编写CSS代码,为页面元素设置样式,关键代码如下:
css 复制代码
<style>
    .router-link-exact-active{
        width: 80px;
        height: 40px;
        line-height: 40px;
        color: #66CCFF;
        border-bottom: 5px solid #66CCFF;
    }
</style>

router-link-exact-active是为当前路由对应的导航链接自动添加的class类名。在实现导航栏时,可以使用该类名高亮显示当前页面对应的导航菜单项。类名中加exact表示精确匹配,不加exact的类名表示模糊匹配。例如,为嵌套路由中的导航菜单项设置高亮显示可以使用router-link-active类。

  1. 先定义Register和Login两个组件,然后定义路由,在定义路由时通过meta字段设置每个页面的标题。接着创建router实例,再使用beforeEach钩子函数,当使用路由切换到不同页面时设置网页的标题,最后挂载根实例并使用路由功能。代码如下:
html 复制代码
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const Register = {
        template: "#reg"
    }
    const Login = {
        template: "#log"
    }

    const routes = [
        {
            path: '/',
            component: Register,
            meta: {
                title: '注册页面'
            }
        },
        {
            path: '/register',
            name: 'register',
            component:  Register,
            meta: {
                title: '注册页面'
            }
        },
        {
            path: '/login',
            name: 'login',
            component: Login,
            meta: {
                title: '登录页面'
            } 
        }
    ];
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes
    });
    router.beforeEach((to, from, next) => {
        document.title = to.meta.title;
        next();
    })
    const vm = Vue.createApp({
    });
    vm.use(router);
    vm.mount('#app');
</script>

运行上述代码,页面中有"注册"和"登录"两个链接,当单击不同的链接时,网页的标题也会随着变化。结果如图:

5.2、scrollBehavior方法

在单页应用中使用路由功能,如果在切换到新的路由之前页面中出现了滚动条,那么在默认情况下,切换路由之后的页面并不会滚动到顶部。如果想要使页面滚动到顶部,或者保持原来的滚动位置,需要使用Vue Router提供的scrollBehavior方法。该方法可以自定义路由切换时页面如何滚动。scrollBehavior方法的语法如下:

js 复制代码
scrollBehavior (to, from, savedPosition) {
 //return 期望滚动到哪个位置
}
  • to:即将进入的目标路由对象。
  • from:当前导航即将离开的路由对象。
  • savedPosition:当导航通过浏览器的前进或后退按钮触发时才可用。

scrollBehavior方法会返回一个滚动位置对象,用于指定新页面的滚动位置。该对象的两个位置属性是top和left,top属性指定沿Y轴滚动后的位置,left属性指定沿X轴滚动后的位置。

下面是一个路由切换时使页面滚动到顶部的示例,代码如下:

html 复制代码
<style>
    p{
        margin-top: 200px;
    }
</style>
<div id="app">
    <p>
        <router-link to="/">课程</router-link>
        <router-link to="/read">读书</router-link>
    </p>
    <router-view></router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue-router@next"></script>
<script type="text/javascript">
    const Course = {
        template: `<div style="height: 1500px;" >课程页面</div>`
    }
    const Read = {
        template: `<div style="height: 1500px;">读书页面</div>`
    }
    
    const routes = [
        {
            path: '/',
            component: Course
        },
        {
            path: '/read',
            component: Read
        }
    ];
    const router = VueRouter.createRouter({
        history: VueRouter.createWebHashHistory(),
        routes,
        //跳转页面后置顶
        scrollBehavior (to, from, savedPosition) {
            if(savedPosition) {
                return  savedPosition;
            } else {
                return {top: 0, left: 0}
            }
        }
    });
    const vm = Vue.createApp({
    });
    vm.use(router);
    vm.mount('#app');
</script>

上述代码中,单击"课程"或"读书"超链接,在页面内容切换的同时,页面会自动滚动到顶部。而当导航通过浏览器的"前进"或"后退"按钮触发时,页面的滚动条不会发生变化。

相关推荐
烛衔溟2 小时前
TypeScript 函数重载(Overloads)
javascript·ubuntu·typescript
CDwenhuohuo2 小时前
小程序全局使用api
javascript·vue.js·小程序
whinc2 小时前
Node.js技术周刊 2026年第16周
前端·javascript
DyLatte2 小时前
我做了个AI项目后才发现:会做事的人,正在输给会讲故事的人
前端·后端·程序员
深海鱼在掘金2 小时前
从Claude Code泄露源码看工程架构:第三章 — CLI 启动链路的分流策略与按需加载机制
前端·人工智能·设计模式
踩着两条虫2 小时前
VTJ:低代码平台原理
前端·低代码·ai编程
颜酱2 小时前
提示词强化1:三个让大模型更「听话」的习惯
前端·javascript·人工智能
破茧成蝶8102 小时前
修复播报缺失文字的bug,改为“播放单个 -> 等待结束 -> 延迟 10ms秒 -> 播放下一个”的递归/循环模式
前端
颜酱2 小时前
提示词强化 2:元提示(Meta-Prompt)与动态提示词
前端·javascript·人工智能