XJQ124 / Some-notes

本仓库记录一些电脑方面的小技巧,包含各个方面
0 stars 0 forks source link

完善昨天的代码,把里面的内容弄懂(Day:22) #26

Open XJQ124 opened 11 months ago

XJQ124 commented 11 months ago

完善目前的代码,然后继续学习Ant Design内容(包括其Api和代码)


1、把昨天基于Ant Design的表格的代码看明白了,学习其API,改造自己的代码

import React, { useState } from 'react';
import { Button, Form, Input, Popconfirm, Table, Drawer } from 'antd';

const { Search } = Input;
//这是Search的回掉函数,接收三个参数,value是输入的文本值,_e表示事件对象(未被使用),info表示搜索的相关信息。
const onSearch = (value, _e, info) => console.log(info?.source, value);

//EditableRow组件用于渲染表格的行
//表示从传递给组件的属性中提取 index 属性,并将剩余的属性放入名为 props 的对象中。
//剩余属性语法 ...props 表示将其余的属性收集到一个名为 props 的对象中。
const EditableRow = ({ index, ...props }) => {
    //创建表单实例
    const [form] = Form.useForm();
    return (
        //将创建的表单实例‘form’绑定 Form 组件上
        //component={false} 表示不生成真正的 HTML 表单元素,而只是提供上下文给子组件使用。
        <Form form={form} component={false}>
            {/* 将从父组件传递过来的属性应用到这个表格行上 */}
            <tr {...props} />
        </Form>
    );
};
//EditableCell组件是表格中每个可编辑单元格的实现。
//它包含了编辑状态的管理、输入框的渲染以及保存编辑后的处理逻辑。
const EditableCell = ({
    title,  //列标题
    editable,//表示该单元格是否可编辑的标志。
    children,//单元格中的子元素,通常是显示当前值的内容。
    dataIndex,//列在数据源中的索引,用于获取或更新数据源中对应项的值。
    record,//表示该行的数据对象,包含了当前单元格所在行的所有数据。
    handleSave,//用于保存编辑后数据的回调函数。
    ...restProps//包含了除上述属性外的其他属性,将其传递给组件中的其他元素。
}) => {
    //创建一个editing 的状态变量,用于跟踪当前单元格是否处于编辑状态。
    //setEditing 是一个用于更新 editing 状态的函数。
    const [editing] = useState(false);
    //变量初始化,将 childNode 变量初始化为 children,即当前单元格的内容。
    let childNode = children;
    if (editable) {
        //如果是可编辑的,会出现一个输入框
        childNode = editing ? (
            <>
            </>
        ) : (
            <div>
            </div>
        );
    }
    return <td {...restProps}>{childNode}</td>;
};
const App = () => {
    //使用useState来创建了一个名为 drawerData 的状态变量,并通过 setDrawerData 函数来更新这个状态。初始状态为{}.
    //抽屉里的数据
    const [drawerData, setDrawerData] = useState({});
    //定义抽屉的可见和不可见,默认为不可见
    const [drawerVisible, setDrawerVisible] = useState(false);

    const [count, setCount] = useState(1);
    //dataSource 通常用于存储表格中的数据。通过 setDataSource 函数,你可以在其他地方更新 dataSource 的内容。
    const [dataSource, setDataSource] = useState([]);

    //编辑函数
    const handleEdit = (key) => {
        // 显示 Drawer
        setDrawerVisible(true);
        // 根据 key 获取被编辑行的数据
        const editedData = dataSource.filter((item) => item.key === key);
        // 设置 drawerData 状态为被编辑行的数据
        setDrawerData(editedData);
        //
        const newData = dataSource.map((item) => {
            //如果数组中的每个元素的值相同,那么给编辑权限
            if (item.key === key) {
                //...是展开运算符,一般用于展开数组和对象
                return { ...item, editing: true };
            }
            return item;
        });
        //更新新的内容
        setDataSource(newData);
    };

    //删除部分
    const handleDelete = (key) => {
        //filter 方法用于遍历 dataSource 数组中的每个元素。
        //((item) => item.key !== key)是一个过滤条件
        const newData = dataSource.filter((item) => item.key !== key);
        setDataSource(newData);
    };

    //默认的列
    const defaultColumns = [
        {
            title: '序号',
            //dataIndex: 表示该列在数据源中的索引
            //即在每个数据项中对应的属性名称。这里是 'name'。
            dataIndex: 'number',
            width: '25%',
            render: (_, __, index) => index + 1,
        },
        {
            title: '公司名称',
            dataIndex: 'name',
            width: '25%',
        },
        {
            title: '公司地址',
            dataIndex: 'address',
            width: '25%',
        },
        {
            title: '操作',
            dataIndex: 'operation',
            width: '25%',
            render: (_, record) => (
                <div>
                    <Button style={{ marginRight: '5px' }} onClick={() => handleEdit(record.key)} >编辑</Button>
                    <Popconfirm title="确认删除吗?" onConfirm={() => handleDelete(record.key)}>
                        <Button danger>删除</Button>
                    </Popconfirm>
                </div>
            ),
        },
    ];

    const handleAdd = () => {
        setDrawerVisible(true);
        //重置drawerData状态
        setDrawerData({});
        // setCount(count + 1);
    }

    const handleSave = (row) => {
        //展开原来的DataSource数组,设置为新的newData
        const newData = [...dataSource];
        const index = newData.findIndex((item) => row.key === item.key);
        if (index !== -1) {
            const item = newData[index];
            //splice是js的数组中的一个方法,用于在数组中添加或者是删除元素
            newData.splice(index, 1, {
                ...item,
                ...row,
            });
        } else {
            // 添加新行
            newData.push({
                key: count,
                ...row,
            });
            setCount(count + 1);
        }
        setDataSource(newData);
    };
    //自带Api
    const components = {
        body: {
            row: EditableRow,
            cell: EditableCell,
        },
    };

    //通过遍历 defaultColumns 数组,生成一个新的 columns 数组。
    const columns = defaultColumns.map((col) => {
        if (!col.editable) {
            return col;
        }
        return {
            ...col,
            onCell: (record) => ({
                record,
                editable: col.editable,
                dataIndex: col.dataIndex,
                title: col.title,
                handleSave,
            }),
        };
    });
    return (
        <div style={{ padding: '20px' }}>
            <Button
                onClick={handleAdd}
                //按钮类型,是antd的 主按钮
                type="primary"
                style={{
                    marginBottom: 16, marginRight: '20px'
                }}
            >
                添加企业用户
            </Button>

            <Search
                placeholder="查询企业信息"
                onSearch={onSearch}
                style={{
                    width: 200,
                }}
            />
            <Table
                //传递了 components 对象
                components={components}
                //为表格的行设置样式类名。
                rowClassName={() => 'editable-row'}
                //显示表格边框。
                bordered
                //表格的数据源,即要展示的数据。
                dataSource={dataSource}
                //表格的列配置
                columns={columns}
            />
            <Drawer
                title="添加企业用户"
                placement="right"  //右侧出现
                closable={true}   // 是否显示右上角的关闭按钮
                onClose={() => setDrawerVisible(false)}
                visible={drawerVisible} //控制抽屉的可见性,这里使用 drawerVisible 状态来控制。
                width={400}
            >
                <Form
                    onFinish={(values) => {
                        // 将 values 与 drawerData 合并
                        const mergedData = { ...drawerData, ...values };

                        // 使用 handleSave 更新表格数据
                        handleSave(mergedData);

                        // 隐藏 Drawer
                        setDrawerVisible(false);
                    }}
                    //将抽屉中的数据设置为 drawerData,可以保证每次点击编辑里面有当前行的数据
                    initialValues={drawerData}
                >

                    {/* 在这里添加表单字段 */}
                    {/* rules是表单规则,意思是要我们必填,然后显示提示信息 */}
                    <Form.Item label="公司名称" name="name" rules={[{ required: true, message: '请输入公司名称' }]}>
                        <Input />
                    </Form.Item>

                    <Form.Item label="公司地址" name="address" rules={[{ required: true, message: '请输入公司地址' }]}>
                        <Input />
                    </Form.Item>
                    {/* 这里的 htmlType="submit"位于 Form 内部时,会触发Form内部的提交 */}
                    <Button type="primary" htmlType="submit">
                        提交
                    </Button>
                </Form>
            </Drawer>
        </div>
    );
};
export default App;

这个部分相比昨天的内容精简了一些,把不要的代码都删掉了

2、明日任务:

本来已经把编辑的部分实现了,但是今天修改的过程中又改没了 明天几个任务: 1、实现点击编辑按钮时,Drawer的名称实现改变(目前是显示:添加企业用户) 2、编辑按钮,保存时,自动修改成功(目前是自动增加下一行) 3、新增企业信息时,输入框里原来的内容要消失 4、实现查找功能