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.valueconst end = currentPage.value * pageSize.valueusers.value = users.value.slice(start,end)}const handleSelectionChange = (val)=>{selectedUsers.value = val}const handleSizeChange = (val:number)=>{pageSize.value=valsearch()//更新数据}const handleCurrentChange = (val:number)=>{currentPage.value=valsearch()//更新数据}const edit = (user)=>{//这里不能直接使用对象的内存地址,否则编辑的时候外面的内容会一同改变因为地址相同//所以应该使用对象的属性let temp = {username: '',name: '',sex: '',birthday: ''}//Object.keys()函数用于获取一个对象中定义的所有属性名的集合Object.keys(temp).forEach((key)=>{temp[key] = user[key]})userDialog.value.user = tempshowDialog(true)}const showDialog = (isUpdate:boolean) => {userDialog.value.isUpdate = isUpdateuserDialog.value.visible = true}const deleteUser = (username) =>{showConfirm(`确定要删除\"${username}\"的相关数据吗?`,()=>{console.log("用户删除数据操作")})}const userForm = ref<FormInstance>()const closeDialog = () => {userDialog.value.isUpdate = falseuserDialog.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-pickerv-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"backgroundlayout="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-dialogv-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/usertarget: 'http://localhost:8888',//表示会将请求代理至目标服务器changeOrigin: true, //表示允许跨域操作rewrite: path => path.replace(/^\/vue/, "") //路径重写}}}
})