第7天

122 阅读2分钟

一.用户组件初步搭建

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值查看是否成功:

image.png 页面结构:

<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>

实现效果:

image.png

二.用户表格数据的获取和渲染

我们需要在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>

实现效果:

image.png