Vue3学习笔记:路由(Router)概念及使用教程

李胤
2025-11-17 / 0 评论 / 3 阅读 / 正在检测是否收录...

前置条件

使用语言

使用的是ts语言,不是js.

安装路由包

Vue3要使用路由,如果没有安装,先进行安装路由包,命令如下

npm install vue-router@4

路由的使用

创建路由

mi2s2xhq.png

  1. 创建目录
    在src目录下进行创建目录(文件夹):router
  2. 创建文件及路由定义
    在创建的目录下创建文件:index.ts,其内容如下:
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import Login from '@/views/LoginPage.vue';
import Home from '@/views/HomePage.vue';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/Login/LoginPage.vue'),
    children: [
      {
        path: '',
        name: 'LoginFrom',
        component: () => import('@/views/Login/components/LoginForm.vue'),
      },
    ],
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

// 全局前置守卫:路由跳转前设置页面标题(可选)
router.beforeEach((to, from, next) => {
  if (to.meta.title) {
    document.title = to.meta.title as string
  }
  next() // 必须调用 next() 放行
})
export default router;

以上内容中路由的路径、名称及组件包括子路由的都可以添加或修改以适应当下项目。

以以上路由进行举例:对应关系是路由名是Home,对应的组件也就是组件是上边导入的页面,也就是路由要展示的内容。而Login下的子路由有一个名为loginFrom的路由,可以在Login的组件中定义子路由页面,子路由没有路径,就是默认展示页面。以下文件内容就是展示。

App.vue 文件内容如下:

<template>
  <RouterView />
</template>

<script setup lang="ts">

</script>

LoginPage.vue 文件内容如下:

<template>
    <div class="common-layout">
        <el-container class="layout-container">
            <el-main class="layout-mian">
                <div class="login-title">
                    <div style="font-size: 30px; font-weight: bold;">欢迎使用运维管理系统</div>
                    <div style="margin-top: 10px;">本产品对各家系统进行整合使用</div>
                </div>
            </el-main>
            <el-aside class="layout-left-aside">
                <RouterView />
            </el-aside>
        </el-container>
    </div>
</template>

<script setup lang="ts">
</script>

<style lang="scss" scoped>
.common-layout {
    height: 100vh;
    background-image: url('../assets/imgs/bg-login.jpg');

    .login-title {
        position: absolute;
        bottom: 30px;
        left: 50px;
        color: #fff;
        text-shadow: 0 0 10px rgba(178, 178, 178, 0.5);
    }

    .layout-container {
        height: 100%;
    }

    .layout-left-aside {
        width: 500px;
        display: flex;
        justify-content: left;
        align-items: center;
        height: 100%;
    }
}
</style>

LoginForm.vue 文件内容如下:

<template>
    <el-card style="width: 400px;">
        <el-form
            ref="ruleFormRef"
            :model="ruleForm" 
            :rules="rules"
            label-width="auto" 
            style="max-width: 600px; min-width: 300px;"
            :size="size"
            :label-position="labelPosition">
            <div class="login-title">
                账号登录
            </div>
            <el-form-item label="用户名"  prop="username">
                <el-input v-model="ruleForm.username" placeholder="请输入用户名" :prefix-icon="Avatar"/>
            </el-form-item>
            <el-form-item label="密  码"  prop="password">
                <el-input v-model="ruleForm.password" placeholder="请输入密码" type="password" :prefix-icon="Lock" />
            </el-form-item>
            <el-form-item>
                <el-checkbox v-model="ruleForm.rememberMe" >记住我</el-checkbox>
            </el-form-item>
            <el-form-item >
                <el-row justify="space-between" style="width: 100%;">
                    <el-col :span="6">
                        <el-link href="#" type="primary">忘记密码?</el-link>
                    </el-col>
                    <el-col :span="12" style="text-align: right;">
                        <el-button plain type="primary" @click="goToRegister" link>还没有账号?立即注册</el-button>
                    </el-col>
                </el-row>
                
            </el-form-item>
            <el-form-item>
                <div class="login-button">
                    <el-button type="danger" size="large" @click="onSubmit" :loading="isLoading" style="width: 60%; text-align: center;">登录</el-button>
                </div>
            </el-form-item>
        </el-form>
        <el-divider><span>其他登录方式</span></el-divider>
        <!-- 三方登录 -->
        <div class="third-party-login">
            <el-button 
            icon="Github" 
            type="default" 
            @click="thirdPartyLogin('github')"
            class="third-btn"
            >
            GitHub 登录
            </el-button>
            <el-button 
            icon="Google" 
            type="default" 
            @click="thirdPartyLogin('google')"
            class="third-btn"
            >
            Google 登录
            </el-button>
        </div>
    </el-card>
</template>

<script setup lang="ts">
import { reactive,ref } from 'vue'
import { Search,Lock,Avatar,House } from '@element-plus/icons-vue'
import type { FormInstance, FormRules, FormProps, ElForm, ComponentSize } from 'element-plus'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'

const labelPosition = ref<FormProps['labelPosition']>('top');
const size = ref<ComponentSize>('large');
const isLoading = ref(false);
const router = useRouter();

interface RuleForm {
    username: string;
    password: string;
    rememberMe: boolean;
}
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  username: '',
  password: '',
  rememberMe: false,
})

const rules = reactive<FormRules<RuleForm>>({
    username: [
        { required: true, message: '请输入用户名', trigger: 'blur' },
    ],
    password: [
        { required: true, message: '请输入密码', trigger: 'blur' },
    ],
});
const goToRegister = () => {
  router.push('/register')
}
const onSubmit = () => {
    isLoading.value = true;
    if (!ruleFormRef.value) return;
    
    ruleFormRef.value.validate((valid) => {
        console.log(valid);
        if (valid) {
            // 模拟登录请求(实际项目中应调用后端登录接口)
            if (ruleForm.username === 'admin' && ruleForm.password === 'admin123') {
                ElMessage.success('登录成功!');
                // 存储用户信息和 token(实际项目中应根据后端返回的数据进行存储)
                const token = 'mock-token-' + Date.now();
                localStorage.setItem('userToken', token);
                isLoading.value = false;
            } else {
                ElMessage.error('用户名或密码错误!');
                isLoading.value = false;
            }
        }else {
            isLoading.value = false;
        }
    })
}

// 三方登录(模拟)
const thirdPartyLogin = (platform: 'github' | 'google') => {
  isLoading.value = true
  // 模拟三方登录授权流程(实际项目需对接对应平台的 OAuth2.0 接口)
  setTimeout(() => {
    const token = `third-party-token-${platform}-${Date.now()}`
    localStorage.setItem('userToken', token)
    localStorage.setItem('userInfo', JSON.stringify({ username: `github_user_${Date.now().toString().slice(-4)}` }));
    ElMessage.primary(`${platform} 登录成功!`)
    router.push('/')
    isLoading.value = false
  }, 1500)
}
</script>

<style scoped>
.login-title {
  font-size: 24px;
  font-weight: bold;
  text-align: center;
  margin-bottom: 30px;
}
.login-button {
    margin-top: 12px;
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
}
</style>
0

评论 (0)

取消