Vue 用户管理系统(路由相关练习二)
Vue 用户管理系统(路由相关练习二)
- 1. 内容介绍
- 2. json-server 数据的增删改查
- 2.1 查询
- 2.2 新增
- 2.3 编辑
- 2.4 删除
- 3. 完整代码示例
- 4. 系统增删改查设计思路
- 5. 关键路由代码讲解
- 5.1 useRouter(获取app路由实例,用于路由跳转)
- 5.2 useRoute(获取当前路由及其参数信息)
1. 内容介绍
本章是对上一章 《Vue 用户管理系统(路由相关练习)》内容的知识补充。主要包括:
(1)如何对 json-server 的数据进行增删改查;
(2)一般系统的增删改查设计思路;
(2)useRouter 和 useRoute 的用法和区别。
2. json-server 数据的增删改查
对 api/userApi.js 进行改造:
// 封装具体的请求函数
import request from './request.js'/*** 获取用户列表*/
export function getUserListApi() {return request({url: '/users',method: 'GET'})
}/*** 添加用户*/
export function addUserApi(data) {return request({url: '/users',method: 'POST',data})
}/*** 根据 id 来获取用户的信息* @param {*} id* @returns*/
export function getUserByIdApi(id) {return request({url: `/users/${id}`,method: 'GET'})
}// 根据 id 删除用户
export function deleteUserByIdApi(id) {return request({url: `/users/${id}`,method: 'DELETE'})
}// 根据 id 编辑用户
export function editUserByIdApi(id, data) {return request({url: `/users/${id}`,method: 'PATCH',data})
}
2.1 查询
(1)查询整个用户列表。
直接使用 get 请求 /users(接口路径) 即可:
/*** 获取用户列表*/
export function getUserListApi() {return request({url: '/users',method: 'GET'})
}
(2)根据 id 查询指定用户信息。
还是使用 get 请求,请求路径后再加上具体的 /${id} 即可:
/*** 根据 id 来获取用户的信息* @param {*} id* @returns*/
export function getUserByIdApi(id) {return request({url: `/users/${id}`,method: 'GET'})
}
2.2 新增
新增用户。使用 post 请求,请求路径不变,请求体和单个用户的 json 格式保持一致。
/*** 添加用户*/
export function addUserApi(data) {return request({url: '/users',method: 'POST',data})
}
2.3 编辑
编辑用户。使用 patch 请求,请求路径后再加上具体的 /${id} ,请求体和单个用户的 json 格式保持一致。
// 根据 id 编辑用户
export function editUserByIdApi(id, data) {return request({url: `/users/${id}`,method: 'PATCH',data})
}
2.4 删除
删除用户。使用 delete 请求,请求路径后再加上具体的 /${id} 即可:
// 根据 id 删除用户
export function deleteUserByIdApi(id) {return request({url: `/users/${id}`,method: 'DELETE'})
}
3. 完整代码示例
(1)router/index.js:
// 前端路由配置文件
import { createRouter, createWebHistory } from 'vue-router'
// 页面组件
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import AddOrEdit from '../views/AddOrEdit.vue'
import Detail from '../views/Detail.vue'
import Email from '../views/Email.vue'
import Tel from '../views/Tel.vue'// 该方法会创建一个路由的实例
// 在创建路由实例的时候,可以传入一个配置对象
const router = createRouter({history: createWebHistory(), // 指定前端路由的模式,常见的有 hash 和 history 两种模式// 路由和组件的映射routes: [{path: '/home', // 路由的路径name: 'Home',component: Home // 路由对应的组件},{path: '/about',name: 'About',component: About,// 创建嵌套的路由children: [{path: 'email',component: Email},{path: 'tel',component: Tel},{path: '',redirect: '/about/email'}]},{path: '/add',name: 'AddOrEdit',component: AddOrEdit},{// 这里的详情就应该是一个动态路由path: '/detail/:id',component: Detail},{path: '/edit/:id',component: AddOrEdit}]
})
export default router
(2)components/Alert.vue(提示组件,由外部提供提示数据、类型和关闭功能):
<template><div :class="['alert', 'alert-dismissible', `alert-${type}`]" role="alert"><button type="button" class="close" @click="closeAlert" aria-label="Close"><span aria-hidden="true">×</span></button><strong>提示!</strong> {{ alert }}</div>
</template><script setup>
defineProps({type: String, // 提示的类型alert: String // 提示的内容
})const emit = defineEmits(['close'])
function closeAlert() {// 触发父组件的 close 事件emit('close')
}
</script>
(3)App.vue:
<template><div id="app" class="container"><nav class="navbar navbar-inverse navbar-fixed-top"><div class="container"><div class="navbar-header"><buttontype="button"class="navbar-toggle collapsed"data-toggle="collapse"data-target="#navbar"aria-expanded="false"aria-controls="navbar"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><div class="navbar-brand">用户管理系统</div></div><div id="navbar" class="collapse navbar-collapse"><ul class="nav navbar-nav"><router-link to="/home" class="navigation">主页</router-link><router-link to="/about" class="navigation">关于我们</router-link></ul><ul class="nav navbar-nav navbar-right"><router-link to="/add" class="navigation">添加用户</router-link></ul></div></div></nav><!-- 由 vue-router 这个库提供的 --><!-- 路由所匹配上的组件,会渲染到这个位置 --><router-view class="content" /></div>
</template><script setup></script><style scoped></style>
(4)views 文件夹下的页面级组件。
Home.vue:
<template><div><Alert v-if="alert" v-bind="alert" @close="closeAlert" /><h1>用户列表</h1><!-- 搜索框 --><inputtype="text"class="form-control"placeholder="搜索内容"v-model="searchItem"@input="changeHandle"/><!-- 表格:显示用户信息 --><table class="table table-striped table-bordered"><thead><tr><th>姓名</th><th>年龄</th><th>联系方式</th><th>操作</th></tr></thead><tbody><tr v-for="item in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.age }}</td><td>{{ item.phone }}</td><td><router-link :to="`/detail/${item.id}`">详情</router-link></td></tr></tbody></table></div>
</template><script setup>
import { onMounted, ref, computed } from 'vue'
import { getUserListApi } from '../api/userApi.js'
import Alert from '../components/Alert.vue'
import { useRoute } from 'vue-router'const userList = ref([])
const searchItem = ref('')
const searchList = ref([]) // 存储搜索后的数据const alert = ref(null)// 当前路由对象
const route = useRoute()onMounted(() => {// 获取用户的数据getUserListApi().then(({ data }) => {userList.value = data})if (route.query && route.query.alert) {alert.value = route.query}
})function changeHandle() {// 根据用户输入的内容进行信息的过滤searchList.value = userList.value.filter((item) => {return item.name.includes(searchItem.value)})
}function closeAlert() {alert.value = null
}const list = computed(() => (searchItem.value ? searchList.value : userList.value))
</script><style scoped></style>
Detail.vue:
<template><div class="details container"><button class="btn btn-default" @click="navigateToHome">返回</button><h1 class="page-header">{{ user.name }}<span class="pull-right"><button class="btn btn-primary" @click="navigateToEdit" style="margin-right: 10px">修改</button><button class="btn btn-danger" @click="deleteUser">删除</button></span></h1><!-- 第一组 --><ul class="list-group"><li class="list-group-item"><span class="glyphicon glyphicon-phone">电话:{{ user.phone }}</span></li><li class="list-group-item"><span class="glyphicon glyphicon-envelope">邮箱:{{ user.email }}</span></li></ul><!-- 第二组 --><ul class="list-group"><li class="list-group-item"><span class="glyphicon glyphicon-book">文化水平:{{ user.education }}</span></li><li class="list-group-item"><span class="glyphicon glyphicon-flag">毕业院校:{{ user.graduationschool }}</span></li><li class="list-group-item"><span class="glyphicon glyphicon-briefcase">专业:{{ user.profession }}</span></li><li class="list-group-item"><span class="glyphicon glyphicon-user">个人简介:{{ user.profile }}</span></li></ul></div>
</template><script setup>
import { getUserByIdApi, deleteUserByIdApi } from '../api/userApi.js'
import { onMounted, reactive } from 'vue'
import { useRoute, useRouter } from 'vue-router'// 得到当前路由对象
const router = useRouter()
const route = useRoute()
const id = route.params.idconst user = reactive({name: '',age: '',phone: '',email: '',education: '本科',graduationschool: '',profession: '',profile: ''
})onMounted(() => {if (id) {getUserByIdApi(id).then(({ data }) => {Object.assign(user, data)})}
})// 跳转到首页
function navigateToHome() {router.push('/home')
}// 跳转到修改用户
function navigateToEdit() {router.push(`/edit/${id}`)
}// 删除用户
function deleteUser() {if (window.confirm('您是否确定要删除此用户?')) {deleteUserByIdApi(id).then(() => {router.push({path: '/home',query: {alert: '删除用户成功!',type: 'warning'}})})}
}
</script><style scoped></style>
AddOrEdit.vue:
<template><div class="container"><h1 class="page-header">{{ id ? '修改用户' : '添加用户' }}</h1><form id="my-form" @submit.prevent="submitUserInfo"><div class="well"><!-- 里面就是每一项表单控件 --><div class="form-group"><label>姓名</label><inputtype="text"class="form-control"placeholder="请输入用户姓名"v-model="user.name"/></div><div class="form-group"><label>年龄</label><inputtype="text"class="form-control"placeholder="请填写用户年龄"v-model.trim="user.age"/></div><div class="form-group"><label>电话</label><inputtype="text"class="form-control"placeholder="请填写用户电话号码"v-model.trim="user.phone"/></div><div class="form-group"><label>邮箱</label><inputtype="text"class="form-control"placeholder="请填写用户邮箱地址"v-model.trim="user.email"/></div><div class="form-group"><label>学历</label><select class="form-control" v-model="user.education"><option>小学</option><option>初中或职中</option><option>高中或职高</option><option>专科</option><option>本科</option><option>硕士</option><option>博士</option></select></div><div class="form-group"><label>毕业学校</label><inputtype="text"class="form-control"placeholder="请填写用户毕业院校"v-model.trim="user.graduationschool"/></div><div class="form-group"><label>职业</label><inputtype="text"class="form-control"placeholder="请填写用户从事的相关职业"v-model.trim="user.profession"/></div><div class="form-group"><label>个人介绍</label><textareaclass="form-control"rows="10"placeholder="请简单的介绍一下你自己,包括兴趣、爱好等信息..."v-model.trim="user.profile"/></div><button class="btn btn-primary">{{ id ? '确认修改' : '确认新增' }}</button></div></form></div>
</template><script setup>
import { reactive, onMounted } from 'vue'
import { addUserApi, getUserByIdApi, editUserByIdApi } from '../api/userApi.js'
import { useRouter, useRoute } from 'vue-router'const user = reactive({name: '',age: '',phone: '',email: '',education: '本科',graduationschool: '',profession: '',profile: ''
})// 得到 router 的实例对象
const router = useRouter()
const route = useRoute()
const id = route.params.idonMounted(() => {// 跳转过来有两种情况:1. 新增用户 2. 修改用户// 新增用户 id 是没有值的// 修改用户 id 是有值的if (id) {getUserByIdApi(id).then(({ data }) => {Object.assign(user, data)})}
})function submitUserInfo() {// 这只是一个简单的验证,验证不能有空项for (const key in user) {if (!user[key]) {alert('请填写完整的用户信息')return}}if (id) {// 修改用户editUserByIdApi(id, user).then(() => {router.push({path: '/home',query: {alert: '修改用户成功!',type: 'success'}})})} else {// 新增用户addUserApi(user).then(() => {router.push({path: '/home',query: {alert: '新增用户成功!',type: 'success'}})})}
}
</script><style scoped></style>
About.vue:
<template><div class="about container"><h1 class="page-header">使用说明</h1><p>通过此系统来熟悉 vue 以及 vue router 的使用</p><p>联系方式</p><router-link to="/about/email" class="navigation">邮箱</router-link><router-link to="/about/tel" class="navigation">电话</router-link><router-view /></div>
</template><script setup></script><style scoped></style>
Email.vue:
<template><div>邮箱地址:xxx@.com</div>
</template>
Tel.vue:
<template><div>电话号码:131-xxxx-xxxx</div>
</template>
4. 系统增删改查设计思路
(1)点击添加用户,进行新增.


(2)修改用户。
点击详情,进入详情页面。可进行修改和删除。

点击修改


(3)删除用户。
进入详情,点击删除,确认。


5. 关键路由代码讲解
5.1 useRouter(获取app路由实例,用于路由跳转)
以 AddOrEdit.vue 为例,关键代码如下:
import { useRouter, useRoute } from 'vue-router' const router = useRouter()router.push({path: '/home',query: {alert: '修改用户成功!',type: 'success'}})
可以看到,useRouter 主要获取app路由实例,用于路由跳转。
5.2 useRoute(获取当前路由及其参数信息)
以 AddOrEdit.vue 为例,关键代码如下:
import { useRouter, useRoute } from 'vue-router'
const route = useRoute()
const id = route.params.idonMounted(() => {// 跳转过来有两种情况:1. 新增用户 2. 修改用户// 新增用户 id 是没有值的// 修改用户 id 是有值的if (id) {getUserByIdApi(id).then(({ data }) => {Object.assign(user, data)})}
})
可以看到,useRoute 主要获取当前路由实例,用于获取当前路由及其参数信息。
上一章 《Vue 用户管理系统(路由相关练习一)》
