背景
技术菜鸟尝试写前端,用vue,路由跳转使用搞了好久才会用。
底层说不太清,单从使用角度,和大家分享下。
重点
- app.vue是唯一的入口文件
- 用router路由必须要有router-view占位符 才可以渲染成功
- router-view 可以在其他页面覆盖使用,必须命名name
效果图
准备
必须安装并引用vue-router模块:
1.指令创建项目时勾选引用Router模块:npm init vue@latest
2.如果没有引用:
2.1: 终端先cd项目的根目录,执行npm install vue-router
2.2: 在src下创建目录router,在这个文件夹里创建 index.js
2.3: 在main.js文件夹里引用:import router from './router/index.js',然后在注入到app中: app.use(router); 即可
2.4: 编写如下路由文件(以我自己的文件为例子):
import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '../views/LoginView.vue'
import PersonView from '../views/PersonView.vue'
const routes1 = [
{ path: '/',
component: LoginView
},
{ path: '/com',
component: TopBar,
children: [ // 添加子路由
{
path: 'bloglist', // 注意点:路径前面不要带/,否则无法跳转,在这里吃过亏
name: 'bloglist',
components: { // 注意参数名带s
table: () => import('@/views/BlogList.vue') // 这里的table跟首页的router-view标签的name一致,才会在首页的路由视图进行跳转,看3.2
}
},
{
path: 'blog', // 注意点:路径前面不要带/,否则无法跳转,在这里吃过亏
name: 'blog',
components: { // 注意参数名带s
table: () => import('@/views/BlogView.vue') // 这里的table跟首页的router-view标签的name一致,才会在首页的路由视图进行跳转,看3.2
}
},
{
path: 'my', // 注意点:路径前面不要带/,否则无法跳转,在这里吃过亏
name: 'my',
components: { // 注意参数名带s
table: () => import('@/views/PersonView.vue') // 这里的table跟首页的router-view标签的name一致,才会在首页的路由视图进行跳转,看3.2
}
},
]
},
{
path: "/me",
component:PersonView
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL), //开启Hash模式,请求跳转的时候没有#符号
routes:routes1
})
export default router
项目实践
1.处理app.vue文件
因为app.vue是唯一入口,所以我删除了全部内容,如下:
<template>
<router-view></router-view>
</template>
<script>
</script>
<style scoped>
</style>
注意:这里的 作为真实页面的占位区域,不写的话,this.$router.push()使用之后,路径会变,页面不会变化!
2.配置默认访问界面
如上述配置的index.js,默认路径’/'配置访问的是:…/views/LoginView.vue。
3.默认界面操作
在默认界面中可以直接使用 this.$router.push实现页面跳转并渲染到app.vue的router-view中:
如下是我LoginView.vue的代码:
<template>
<div class="login">
<h2>Login</h2>
<form>
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" v-model="username" required>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" v-model="password" required>
</div>
<div class="button-group">
<button type="submit" @click.prevent="login">Login</button>
<button type="button" @click="goToRegister">Register</button>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'LoginView',
data(){
return{
username:"",
password:""
}
},
methods:{
goToRegister(){
console.log("跳转")
this.$router.push( "/register")
},
login(){
console.log("登录")
this.$router.push("/com/bloglist")
}
}
};
</script>
<style scoped>
.login {
margin-top: 10%;
margin-left:38%;
margin: 0 auto;
max-width: 300px;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
.form-group {
margin-bottom: 10px;
}
label {
display: block;
margin-bottom: 5px;
}
input[type="text"],
input[type="password"] {
width: 100%;
padding: 5px;
border: 1px solid #ccc;
border-radius: 3px;
}
.button-group {
display: flex;
justify-content: space-between;
align-items: center;
}
button {
padding: 10px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 3px;
cursor: pointer;
}
</style>
其他界面还要使用router-view渲染怎么办?
1.首先我们要在需要用路由渲染的界面添加router-view ,并添加 name属性!
如下:
<template>
<nav class="navbar">
<div class="navbar-left">
<img :src="profile.photo" alt="Image" @click="openImagePicker">
<p>欢迎你:{{name}}</p>
<div v-if="showImagePicker">
<input type="file" accept="image/*" @change="handleImageChange">
<button @click="saveImage">保存</button>
</div>
</div>
<div class="navbar-right">
<p> <router-link to="/com/bloglist">博客列表</router-link></p>
<p><router-link to="/com/blog">创建博客</router-link></p>
<p><router-link to="/com/my">修改个人信息</router-link></p>
<button @click="logout">退出登录</button>
</div>
</nav>
//这里是重点!!!
<router-view name="table"></router-view>
</template>
<script>
import image from '@/assets/1.jpg'
export default {
data() {
return {
profile:{photo: image},
showImagePicker: false,
selectedImage: null,
name:"Simmons"
};
},
methods: {
logout() {
this.$router.push('/')
},
openImagePicker() {
this.showImagePicker = true;
},
handleImageChange(event) {
const file = event.target.files[0];
this.selectedImage = URL.createObjectURL(file);
},
saveImage() {
if (this.selectedImage) {
this.profile.photo = this.selectedImage;
}
this.showImagePicker = false;
}
}
};
</script>
<style>
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
background-color: #f0f0f0;
}
.navbar-left img {
width: 40px;
height: 40px;
object-fit: cover;
}
.navbar-left p {
display: inline-block;
margin-left: 10px;
}
.navbar-right {
display: flex;
gap: 10px;
}
.navbar-right a {
text-decoration: none;
color: #333;
}
.navbar-right p {
margin-right: 10px;
font-size: 15px;
font-weight:bold;
color: black;
border: 2px;
}
.navbar-right button {
padding: 5px 10px;
background-color: #333;
color: #fff;
border: none;
cursor: pointer;
margin-left: 5px;
}
</style>
2.然后这个路由渲染 按照准备工作配置的 children 即可实现。