亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码

組件封裝-基礎組件

組件封裝 - 基礎組件

動(dòng)態(tài)表格組件 (DynamicTable)

1. 組件功能特性

  • 列自定義顯示/隱藏
  • 固定列支持
  • 行選擇和操作
  • 排序和篩選
  • 分頁(yè)集成
  • 自定義渲染

2. 組件使用示例

// 基本使用
<DynamicTable
    id="ckgd"
    myKey="entryId"
    columns={columns}
    dataSource={dataSource}
    showSelectionCheckbox={true}
    onTableSelect={this.handleTableSelect}
    loading={loading}
/>

// 帶操作的表格
<DynamicTable
    id="goods"
    myKey="id"
    columns={goodsColumns}
    dataSource={goodsData}
    actions={[
        { label: '查看詳情', onClick: this.handleViewDetail },
        { label: '編輯', onClick: this.handleEdit }
    ]}
    onDoubleClick={this.handleRowDoubleClick}
/>

3. 列配置定義

const columns = [
    {
        title: '報關(guān)單號',
        dataIndex: 'entryId',
        key: 'entryId',
        width: 160,
        sorter: (a, b) => a.entryId - b.entryId,
        fixed: 'left'
    },
    {
        title: '出口日期',
        dataIndex: 'iEDate',
        key: 'iEDate',
        width: 90,
        sorter: (a, b) => new Date(a.iEDate) - new Date(b.iEDate),
        render: (text) => moment(text).format('YYYY-MM-DD')
    },
    {
        title: '申報狀態(tài)',
        dataIndex: 'sbztDm',
        key: 'sbztDm',
        render: (text) => {
            switch (text) {
                case 'Y': return '已申報';
                case 'N': return '未申報';
                case 'B': return '部分申報';
                default: return text;
            }
        }
    }
];

4. 組件核心實(shí)現

class DynamicTable extends Component {
    constructor(props) {
        super(props);
        this.state = {
            columns: this.initializeColumns(props.columns, props.fixedColumns),
            dataSource: props.dataSource || [],
            selectedRowKeys: props.selectedRowKeys || [],
            loading: props.loading || false
        };
    }

    // 初始化列配置
    initializeColumns = (columns, fixedColumns, dataSource) => {
        return columns
            .filter(col => !col.unShow) // 過(guò)濾隱藏列
            .map(col => {
                let width = this.calculateColumnWidth(col, dataSource);
                width = width < 350 ? width : 350;
                
                if (fixedColumns && fixedColumns.includes(col.key)) {
                    return { ...col, ellipsis: true, fixed: 'left', width };
                }
                return { ...col, ellipsis: true, width };
            });
    };

    // 計算列寬度
    calculateColumnWidth = (col, dataSource) => {
        const contentWidth = Math.max(
            col.title.length * 10, // 標題寬度
            ...dataSource.map(item => 
                String(item[col.dataIndex] || '').length * 8 // 內容寬度
            )
        );
        return Math.max(contentWidth + 20, 80); // 最小寬度80px
    };

    render() {
        const { columns, dataSource, loading } = this.state;
        const { id, myKey, showSelectionCheckbox } = this.props;

        return (
            <Table
                id={id}
                rowKey={record => record[myKey]}
                columns={columns}
                dataSource={dataSource}
                loading={loading}
                rowSelection={showSelectionCheckbox ? {
                    selectedRowKeys: this.state.selectedRowKeys,
                    onChange: this.handleSelectionChange
                } : null}
                scroll={{ x: 1500, y: 400 }}
                pagination={false}
            />
        );
    }
}

動(dòng)態(tài)表單組件 (DynamicForm)

1. 表單字段類(lèi)型支持

  • Input - 文本輸入
  • Select - 下拉選擇
  • DatePicker - 日期選擇
  • Checkbox - 復選框
  • Radio - 單選框
  • Button - 操作按鈕

2. 表單配置示例

const formConfig = {
    id: 'searchForm',
    formItems: [
        {
            type: 'input',
            field: 'entryId',
            label: '報關(guān)單號',
            placeholder: '請輸入報關(guān)單號'
        },
        {
            type: 'select',
            field: 'cusDecStatus',
            label: '結關(guān)狀態(tài)',
            options: [
                { value: '', label: '全部' },
                { value: '10', label: '已結關(guān)' },
                { value: 'wjg', label: '未結關(guān)' }
            ],
            fieldProps: {
                initialValue: ''
            }
        },
        {
            type: 'DatePicker',
            field: 'iEDate',
            label: '出口日期',
            nextType: 'RangePicker' // 支持范圍選擇
        },
        {
            type: 'button',
            action: 'submit',
            label: '查詢(xún)',
            btnType: 'primary'
        }
    ],
    layout: 'inline',
    onFormSubmit: this.handleSearchSubmit
};

3. 組件使用

<DynamicForm {...formConfig} />

布局組件系統

1. 雙欄布局 (twinlayout)

// 主要用于內容展示頁(yè)面
<Route name="txrp" path="/txrp" component={twinlayout}>
    <Route name="出口貨物明細采集" path="ckhwmxcj" component={ckhwmxcj} />
    <Route name="貨物資料采集" path="hwzlcj" component={hwzlcj} />
</Route>

2. 橫向布局 (hglayout)

// 用于橫向導航的頁(yè)面
<Route name="ckfp" path="ckfp" component={hglayout}>
    <Route name="出口關(guān)單" path="ckgd" component={ckgd} />
    <Route name="退稅率查詢(xún)" path="tslcx" component={tslcx} />
</Route>

3. 出口關(guān)單布局 (cklayout)

// 專(zhuān)門(mén)的出口關(guān)單頁(yè)面布局
<Route path="/" component={cklayout}>
    <IndexRoute component={Home} />
    <Route path="ckgd" component={ckgd} />
</Route>

基礎組件封裝

1. 動(dòng)態(tài)分頁(yè)組件 (DynamicPagination)

class DynamicPagination extends Component {
    render() {
        const { totalItems, currentPage, initialPageSize, onPageChange } = this.props;
        
        return (
            <Pagination
                current={currentPage}
                pageSize={initialPageSize}
                total={totalItems}
                showSizeChanger
                showQuickJumper
                showTotal={(total, range) => 
                    `第 ${range[0]}-${range[1]} 條,共 ${total} 條`
                }
                onChange={onPageChange}
                onShowSizeChange={onPageChange}
            />
        );
    }
}

2. 動(dòng)態(tài)卡片組件 (DynamicCard)

class DynamicCard extends Component {
    render() {
        const { title, extra, children, tabList, activeKey, onTabChange } = this.props;
        
        return (
            <Card
                title={title}
                extra={extra}
                tabList={tabList}
                activeTabKey={activeKey}
                onTabChange={onTabChange}
            >
                {children}
            </Card>
        );
    }
}

組件通信模式

1. Props傳遞

// 父組件傳遞數據和回調
<ChildComponent 
    data={this.state.data}
    onUpdate={this.handleChildUpdate}
/>

// 子組件接收和使用
class ChildComponent extends Component {
    handleClick = () => {
        this.props.onUpdate(newData);
    };
}

2. Context傳遞

// 創(chuàng  )建Context
const TableContext = React.createContext();

// 提供者組件
class TableProvider extends Component {
    state = { selectedRows: [] };
    
    render() {
        return (
            <TableContext.Provider value={{
                selectedRows: this.state.selectedRows,
                setSelectedRows: this.setSelectedRows
            }}>
                {this.props.children}
            </TableContext.Provider>
        );
    }
}

// 消費者組件
const TableConsumer = () => (
    <TableContext.Consumer>
        {({ selectedRows, setSelectedRows }) => (
            // 使用上下文數據
        )}
    </TableContext.Consumer>
);

組件性能優(yōu)化

1. 避免不必要的重新渲染

class OptimizedComponent extends React.PureComponent {
    // 自動(dòng)實(shí)現shouldComponentUpdate
    // 進(jìn)行淺比較props和state
}

// 或手動(dòng)實(shí)現
class OptimizedComponent extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        // 自定義比較邏輯
        return nextProps.data !== this.props.data;
    }
}

2. 使用React.memo

const MemoizedComponent = React.memo(function MyComponent(props) {
    // 組件實(shí)現
}, (prevProps, nextProps) => {
    // 自定義比較函數
    return prevProps.data === nextProps.data;
});

3. 代碼分割和懶加載

const LazyComponent = React.lazy(() => import('./LazyComponent'));

const MyComponent = () => (
    <Suspense fallback={<div>加載中...</div>}>
        <LazyComponent />
    </Suspense>
);

組件測試

1. 單元測試示例

import { render, screen, fireEvent } from '@testing-library/react';
import DynamicTable from './DynamicTable';

test('renders table with data', () => {
    const mockData = [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' }
    ];
    
    render(<DynamicTable dataSource={mockData} />);
    
    expect(screen.getByText('Item 1')).toBeInTheDocument();
    expect(screen.getByText('Item 2')).toBeInTheDocument();
});

test('handles row selection', () => {
    const mockData = [{ id: 1, name: 'Item 1' }];
    const mockOnSelect = jest.fn();
    
    render(<DynamicTable dataSource={mockData} onTableSelect={mockOnSelect} />);
    
    fireEvent.click(screen.getByText('Item 1'));
    expect(mockOnSelect).toHaveBeenCalledWith([1]);
});

文章目錄

    亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码