一.用户组件初步搭建
router的index.js中增加user的路由:
import { createRouter, createWebHashHistory } from 'vue-router'
//指定路由规则
const routes = [
{
path: '/',
name: "main",
component: () => import('../views/Main.vue'),
redirect: '/home',
children: [
{
path: 'home',
name: "home",
component: () => import('../views/Home.vue'),
},
{
path: 'user',
name: "user",
component: () => import('../views/User.vue'),
},
]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
export default router;
创建User.vue组件后,改变hash值查看是否成功:
页面结构:
<template>
<div>
<div class="user-header">
<el-button type="primary">新增</el-button>
<el-form :inline="true">
<el-form-item label="请输入">
<el-input placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary">搜索</el-button>
</el-form-item>
</el-form>
</div>
<div class="table">
<el-table :data="tableData" style="width: 100%">
<el-table-column fixed prop="date" label="Date" width="150" />
<el-table-column prop="name" label="Name" width="120" />
<el-table-column prop="state" label="State" width="120" />
<el-table-column prop="city" label="City" width="120" />
<el-table-column prop="address" label="Address" width="600" />
<el-table-column prop="zip" label="Zip" width="120" />
<el-table-column fixed="right" label="Operations" min-width="120">
<template #default>
<el-button type="primary" size="small" @click="handleClick">
编辑
</el-button>
<el-button type="danger" size="small" >删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup>
const handleClick = () => {
console.log('click')
}
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
]
</script>
<style scoped lang="less">
.user-header {
display: flex;
justify-content: space-between;
}
</style>
实现效果:
二.用户表格数据的获取和渲染
我们需要在Data中增加一个user.js,并在里面添加数据;再在api.js进行api获取设置,mock.js中进行数据拦截的设置,然后在组件中写一个异步事件来获取数据。
user.js:
(这里的只是表格的内容,表格的头部,也就是标签那一行我们要在User.vue中去设置)
import Mock from 'mockjs';
// 将URL参数转换成对象
function param2obj(url) {
const search = url.split('?')[1];
if (!search) {
return {};
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
);
}
let List = [];
const count = 200;
// 模拟200条用户数据
for (let i = 0; i < count; i++) {
List.push(
Mock.mock({
id: Mock.Random.guid(),
name: Mock.Random.cname(),
addr: Mock.mock('@county(true)'),
'age|18-60': 1,
birth: Mock.Random.date(),
sex: Mock.Random.integer(0, 1)
})
);
}
export default {
/**
* 获取列表
* 要带参数 name, page, limit; name可以不填,page, limit有默认值。
* @param name, page, limit
* @return {code: number, count: number, data: *[]}
*/
getUserList: config => {
// limit默认是10,因为分页器默认也是一页10个
const { name, page = 1, limit = 10 } = param2obj(config.url);
const mockList = List.filter(user => {
// 如果name存在会,根据name筛选数据
if (name && user.name.indexOf(name) === -1) return false;
return true;
});
// 分页
const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1));
return {
code: 200,
data: {
list: pageList,
count: mockList.length // 数据总条数需要返回
}
};
}
};
api.js:
getUserData() {
return request({ url: '/api/home/getUserData' })
},
mock.js:
import userApi from './mockData/user'
mock.mock("/api/home/getUserData", 'get', userApi.getUserList)
User.vue:
表头通过reactive来设置
const tableLabel=reactive([
{
prop:'name',
label:'姓名'
},
{
prop:'age',
label:'年龄'
},
{
prop:'sexLabel',
label:'性别'
},
{
prop:'birth',
label:'出生日期',
width:200
},
{
prop:'addr',
label:'地址',
width:400
},
])
获取数据,并渲染:
const tableData = ref([])
const {proxy}=getCurrentInstance()
const getUserData = async () => {
try {
const data = await proxy.$api.getUserData()
tableData.value=data.list.map(item=>({
...item,
sexLabel:item.sex===1?'男':'女'
}))
} catch (error) {
console.error('Failed to fetch table data:', error)
}
}
onMounted(()=>{
getUserData()
})
html结构:使用 :data去渲染内容,v-for来设置表头
<div class="table">
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="item in tableLabel"
:key="item.prop"
:width="item.width ? item.width :125"
:prop="item.prop"
:label="item.label"
/>
<el-table-column fixed="right" label="Operations" min-width="120">
<template #default>
<el-button type="primary" size="small" @click="handleClick">
编辑
</el-button>
<el-button type="danger" size="small" >删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
完整代码:
<template>
<div>
<div class="user-header">
<el-button type="primary">新增</el-button>
<el-form :inline="true">
<el-form-item label="请输入">
<el-input placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary">搜索</el-button>
</el-form-item>
</el-form>
</div>
<div class="table">
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="item in tableLabel"
:key="item.prop"
:width="item.width ? item.width :125"
:prop="item.prop"
:label="item.label"
/>
<el-table-column fixed="right" label="Operations" min-width="120">
<template #default>
<el-button type="primary" size="small" @click="handleClick">
编辑
</el-button>
<el-button type="danger" size="small" >删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script setup>
import {ref,getCurrentInstance,onMounted, reactive} from 'vue'
const handleClick = () => {
console.log('click')
}
const tableData = ref([])
const {proxy}=getCurrentInstance()
const getUserData = async () => {
try {
const data = await proxy.$api.getUserData()
tableData.value=data.list.map(item=>({
...item,
sexLabel:item.sex===1?'男':'女'
}))
} catch (error) {
console.error('Failed to fetch table data:', error)
}
}
const tableLabel=reactive([
{
prop:'name',
label:'姓名'
},
{
prop:'age',
label:'年龄'
},
{
prop:'sexLabel',
label:'性别'
},
{
prop:'birth',
label:'出生日期',
width:200
},
{
prop:'addr',
label:'地址',
width:400
},
])
onMounted(()=>{
getUserData()
})
</script>
<style scoped lang="less">
.user-header {
display: flex;
justify-content: space-between;
}
</style>
实现效果: