Vue路由

发布于:2024-07-30 ⋅ 阅读:(70) ⋅ 点赞:(0)

Vue路由

安装插件:

yarn add vue-router

import {createRouter, createWebHashHistory} from "vue-router";

const routes =[
    {
        path: '/',
        redirect: '/login'//首页需要重定向到一个显示的路由页面,这个重定向的页面必须在路由中有定义
    },
    {
        path: '/login',//路由的路径
        name: 'Login',
        //懒加载,可以节省浏览器的使用内存
        component: () => import('../views/Login.vue')
    },
    {
        path: '/manage',//管理页面路径
        name: 'Manage',
        //懒加载,可以节省浏览器的使用内存
        component: () => import('../views/Manage.vue'),
        //子路由,即页面中的页面,子路由是在路由中配置的一个数组,数组中配置路由的信息
        children: [
        {
        path: '/setting',
        name: 'Setting',
        //懒加载,可以节省浏览器的使用内存
        component: () => import('../views/Setting.vue')
},
    {
        path: '/user',
            name: 'User',
                //懒加载,可以节省浏览器的使用内存
                component: () => import('../views/User.vue')
    },
        {
            path: '/position',
                name: 'Position',
                    //懒加载,可以节省浏览器的使用内存
                    component: () => import('../views/Position.vue')
        }
]
},

    ]

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

    export default router;

也就是说当开启项目后会自动进入/login页面,手动进入/manage页面后里面包含了三个子页面,即/setting,/user,/position,这三个页面存在于/manage页面之中。需要对其进行弹性布局。

弹性布局(折叠菜单)

<script setup lang="ts">
import {ref} from "vue";
let isCollapse = ref(false)
const menus = [
{
    id: 1,
        name: '系统设置',
        icon: "Setting",//图标为Setting样式,在Element-plus官网查看
        route: '/setting'
},
{
    id: 2,
        name: '用户管理',
        icon: "User",
        route: '/user'
},
{
    id: 3,
        name: '地址管理',
        icon: "Position",
        route: '/position'
}
]

</script>

<template>
<div class="main-container">
<header>
<el-icon>
<!--隐藏菜单,即点击切换Expand和Fold状态-->
<component :is="isCollapse ? 'Expand' : 'Fold'" @click="isCollapse = !isCollapse"/>
    </el-icon>
    </header>
    <main>
    <!--default-active表示默认使用的菜单,其值为菜单的index属性
    collapse属性表示菜单是否折叠,router属性用来开启vue-router模式
    开启后使用的菜单的index属性值作为路由的path-->
    <el-menu default-active="1" :collapse="isCollapse" :router="true">
    <el-menu-item v-for="m in menus" :index="m.route">
    <el-icon>
    <!--如果图标需要发生变化就要使用component标签-->
    <component :is="m.icon"/>
    </el-icon>
{{m.name}}
</el-menu-item>
</el-menu>
<section>
<nav>操作导航</nav>
<article>
<!--由于父容器使用的是弹性布局,因此子路由容器不能再使用弹性布局
应该使用绝对定位布局防止组件外溢-->
<router-view class="child-container"/>
</article>
<footer> 632 2024-2030 版权所有</footer>
</section>
</main>
</div>
</template>

<style scoped>
.main-container {
    width: 100%;
    height: 100%;
    overflow: hidden;/*超出部分隐藏*/
    display: flex;/*浮动*/
    flex-direction: column;/*上下排列*/
}
header{
    height: 50px;
    border-bottom: 1px solid #ddd;
}
main{
    flex-grow: 1.0;/*空间足够会自动拉伸*/
    flex-shrink: 0.8;/*空间不足会自动缩小*/
    display: flex;
    flex-direction: row;/*主体部分为横向排列*/
}
.el-menu{
    color: #535bf2!important;
    background-color: transparent;
    width: 150px;
    border-right: 1px solid #ddd;/*右边框*/
    overflow: hidden;
    transition: width .1s;/*当‘el-menu’类的元素宽度发生变化时以0.1s平滑过渡*/
}
section{

    flex-grow: 1.0;
    flex-shrink: 0.8;
    display: flex;
    flex-direction: column;
}
article{

    flex-grow: 1.0;
    flex-shrink: 0.8;
    position: relative;/*相对定位,因为子组件要进行绝对定位所以需要将自己的位置作为参照物*/
}
nav{

    height: 22px;
    border-bottom: 1px solid #ddd;
    font-size: 14px;
    line-height: 22px;/*行高*/
    text-indent: 10px;/*首行缩进*/
}
footer{

    height: 40px;
    line-height: 40px;
    border-top: 1px solid #ddd;
    text-indent: 10px;
}
.child-container{
    position: absolute;/*绝对定位*/
    top: 5px;
    right: 5px;
    bottom: 5px;
    left: 5px;
}
</style>
<!--element-plus中的css样式,在修改的时候如果样式的名称存在双横杠,
那么这些css样式必须在全局样式中调整才能生效-->
<style>
.el-menu--collapse{
    width: 60px !important;/*提高此样式规则的优先级,使其覆盖其他任何可能影响宽度的样式规则。*/
}
</style>

查询列表 + 对话框 + 消息提示框:

<script setup lang="ts">
    import {onMounted, ref} from "vue";
    import {showConfirm} from "../tip";
    import {FormInstance} from "element-plus";
    const condidtion = ref({
        name: '',
        sex: '',
        birthday: []
    })
    const sexArr = ref(['男','女','其他'])

    const selectedUsers = ref([])
    const currentPage = ref(1)
    const pageSize = ref(5)
    const pageSizes = ref([5,10,20])
    const total = ref(20)
    const users = ref([])
    const userDialog= ref({
        visible: false,
        isUpdate: false,
        user: {
            username: '',name: '',sex: '',birthday: ''
        },
        userRules: ''
    })
    const search = ()=>{
        //假数据
        users.value=[{
            username: "boduo",name: '波多',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoy",name: '波多y',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoye",name: '波多ye',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyej",name: '波多yej',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie1",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie12",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie123",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie1234",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie12345",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie123456",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie1234567",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        },{
            username: "boduoyejie12345678",name: '波多yeji',sex: '女',birthday: '2002-11-30'
        }
                    ];
        const start = (currentPage.value-1) * pageSize.value
        const end = currentPage.value * pageSize.value
        users.value = users.value.slice(start,end)
    }
    const handleSelectionChange = (val)=>{
        selectedUsers.value = val
    }
    const handleSizeChange = (val:number)=>{
        pageSize.value=val
        search()//更新数据
    }
    const handleCurrentChange = (val:number)=>{
        currentPage.value=val
        search()//更新数据
    }
    const edit = (user)=>{
        //这里不能直接使用对象的内存地址,否则编辑的时候外面的内容会一同改变因为地址相同
        //所以应该使用对象的属性
        let temp = {username: '',name: '',sex: '',birthday: ''}
        //Object.keys()函数用于获取一个对象中定义的所有属性名的集合
        Object.keys(temp).forEach((key)=>{temp[key] = user[key]})
        userDialog.value.user = temp
        showDialog(true)
    }
    const showDialog = (isUpdate:boolean) => {
        userDialog.value.isUpdate = isUpdate
        userDialog.value.visible = true
    }
    const deleteUser = (username) =>{
        showConfirm(`确定要删除\"${username}\"的相关数据吗?`,()=>{
            console.log("用户删除数据操作")
        })
    }
    const userForm = ref<FormInstance>()
    const closeDialog = () => {
        userDialog.value.isUpdate = false
        userDialog.value.user = {username: '',name: '',sex: '',birthday: ''}
        userForm.value.resetFields()
        userDialog.value.visible = false
    }
    const save = () =>{
        userForm.value.validate(valid =>{
            if (valid) {}
        })
    }
    //onMounted()函数是vue3提供的钩子函数,用于页面挂载后的初始化动作
    onMounted (()=>search())

</script>

<template>
<div>
    <!--inline属性表示能在一行中展示-->
    <el-form :model="condidtion" :inline="true">
        <el-form-item label="姓名">
            <el-input v-model="condidtion.name" placeholder="请输入姓名" clearable/>
    </el-form-item>
        <el-form-item label="性别" style="width: 192px">
            <el-select v-model="condidtion.sex">
                <el-option v-for="(s,index) in sexArr" :label="s" :value="index"></el-option>
    </el-select>
    </el-form-item>
        <el-form-item label="出生日期">
            <!--type表示日期选择器的类型,可以是单个日期也可以是一个时间范围
单个日期就是单个值,日期范围是数组,数组中会存在一个开始值和结束值-->
            <el-date-picker
                            v-model="condidtion.birthday"
                            type="daterange"
                            range-separator="至"
                            start-placeholder="请选择开始日期"
                            end-placeholder="请选择结束日期"
                            value-format="yyyy-MM-dd"/>
    </el-form-item>
        <el-form-item>
            <el-button icon="Search" type="primary" @click="search">查询</el-button>
            <el-button icon="RefreshLeft">重置</el-button>
            <el-button icon="plus" type="danger" @click="showDialog(false)">增加</el-button>
    </el-form-item>

    </el-form>
    <!--
page-sizes表示每页条数
background属性表示分页按钮的背景色
layout属性表示分页组件要展示的内容,给定的内容顺序为展示顺序
total属性表示查询结果的总条数
size-change属性表示绑定一个每页显示条数改变触发的事件
current-change属性表示绑定一个分页页码改变的时间
-->
    <el-pagination style="float: right"
                   v-show="total>0"
                   v-model:current-page="currentPage"
                   v-model:page-size="pageSize"
                   :page-sizes="pageSizes"
                   background
                   layout="total,sizes,prev,pager,next"
                   :total="total"
                   @size-change="handleSizeChange"
                   @current-change="handleCurrentChange"
                   size="small"
                   />

    <!--data属性表示表格要展示的数据,一般都是与一个数组绑定,height属性表示表格的高度,
只有设置了这个属性表格才会在内容溢出的时候出现滚动条-->
    <el-table :data="users" height="500px" style="width: 100%" border
              @selection-change="handleSelectionChange">

        <el-table-column type="selection" width="50px"/><!--选择-->
        <el-table-column prop="username" label="账号" />
        <el-table-column prop="name" label="姓名" />
        <el-table-column label="性别" >
            <template #defalut="scope">
                <el-tag v-if="scope.row.sex===0" type="primary"></el-tag>
                <el-tag v-if="scope.row.sex===1" type="success"></el-tag>
                <el-tag v-if="scope.row.sex===2" type="danger">其他</el-tag>
</template>
</el-table-column>
<el-table-column prop="birthday" label="出生日期" />
<el-table-column label="操作">
    <!--如果列中展示的内容需要使用到一些模板就必须使用template标签
default属性表示操作这个表格的对象,值就是一个对象名,对象名.row就能拿到当前行的数据-->
    <template #default="s">
<el-button link type="primary" size="small" @click="edit(s.row)" >编辑</el-button>
<el-button link type="warning" size="small">冻结</el-button>
<el-button link type="success" size="small">解冻</el-button>
<el-button link type="danger" size="small" @click="deleteUser(s.row.username)" >删除</el-button>
    </template>
</el-table-column>
</el-table>
<!--title属性表示对话框而定标题内容
before-class属性表示关闭对话框之前要执行的函数-->
<el-dialog
           v-model="userDialog.visible"
           :title="userDialog.isUpdate ? '编辑用户信息':'新增用户信息'"
           width="500"
           :before-close="closeDialog"
           >
    <el-form :model="userDialog.user" :rules="userDialog.userRules" ref="userForm">
        <el-form-item label="账号" prop="username">
            <el-input v-model="userDialog.user.username" placeholder="请输入账号" clearable/>
        </el-form-item>
        <el-form-item label="姓名" prop="name">
            <el-input v-model="userDialog.user.name" placeholder="请输入姓名" clearable/>
        </el-form-item>
        <el-form-item label="性别" prop="sex">
            <el-select v-model="userDialog.user.sex" placeholder="请选择性别" clearable>
                <el-option v-for="(s,index) in sexArr" :label="s" :value="index"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="生日">
            <el-date-picker v-model="userDialog.user.birthday" type="date" placeholder="请选择生日" clearable/>
        </el-form-item>
    </el-form>
    <template #footer>
<div class="dialog-footer">
    <el-button @click="closeDialog()">取消</el-button>
    <el-button type="primary" @click="save()">保存</el-button>
        </div>
    </template>
</el-dialog>
</div>

</template>

<style scoped>
    div{
        background-color: transparent;
    }
    el-dialog{
        background-color: transparent;
    }
</style>

ajax:vue提供的ajax

安装:yarn add axios

请求代理:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {//服务器配置
    port: 7777, //服务器端口
    proxy:{//这里就是对请求做代理
      //下面的内容就是代理的规则
      // /vue表示凡是以/vue开始的请求都会被代理
      '/vue':{
        // http://localhost:7777/vue/user => http://localhost:8888/vue/user => http://localhost:8888/user
        target: 'http://localhost:8888',//表示会将请求代理至目标服务器
        changeOrigin: true, //表示允许跨域操作
        rewrite: path => path.replace(/^\/vue/, "") //路径重写
      }
    }
  }
})