哪些网站专门做动漫的目前做的比较好的法律网站有哪些
哪些网站专门做动漫的,目前做的比较好的法律网站有哪些,如何自己建一个网站,视觉设计工作室文章目录 一、自然语言描述转化的基础组件代码#xff08;React TypeScript#xff09;二、组件二次优化#xff08;性能 体验 扩展性升级#xff09;优化 1#xff1a;性能优化#xff08;避免重复渲染 数据缓存#xff09;优化 2#xff1a;交互体验升级优化 3React TypeScript二、组件二次优化性能 体验 扩展性升级优化 1性能优化避免重复渲染 数据缓存优化 2交互体验升级优化 3扩展性升级支持自定义配置优化后组件核心优势一、自然语言描述转化的基础组件代码React TypeScriptimport React, { useState, useEffect } from react; import { Input, Select, Checkbox, Pagination, Card, Spin, Empty } from antd; import { SearchOutlined, FilterOutlined } from ant-design/icons; // 商品类型定义 interface Product { id: number; name: string; price: number; category: string; brand: string; sales: number; image: string; } // 筛选条件类型 interface FilterParams { keyword: string; category: string; brand: string[]; priceRange: [number, number]; } const ProductList: React.FC () { // 状态管理 const [products, setProducts] useStateProduct[]([]); const [filteredProducts, setFilteredProducts] useStateProduct[]([]); const [filters, setFilters] useStateFilterParams({ keyword: , category: all, brand: [], priceRange: [0, 10000], }); const [loading, setLoading] useStateboolean(true); const [currentPage, setCurrentPage] useStatenumber(1); const [pageSize] useStatenumber(12); // 模拟接口请求商品数据 useEffect(() { const fetchProducts async () { setLoading(true); // 模拟延迟 await new Promise(resolve setTimeout(resolve, 800)); // 模拟商品数据 const mockData: Product[] Array.from({ length: 60 }, (_, i) ({ id: i 1, name: 智能防蓝光眼镜 ${i 1}代 - ${[商务款, 休闲款, 运动款][i % 3]}, price: 199 Math.floor(Math.random() * 800), category: [防蓝光, 近视镜, 太阳镜, 老花镜][i % 4], brand: [暴龙, 陌森, 雷朋, 帕森, 海伦凯勒][i % 5], sales: Math.floor(Math.random() * 1000), image: https://picsum.photos/200/200?random${i}, })); setProducts(mockData); setFilteredProducts(mockData); setLoading(false); }; fetchProducts(); }, []); // 筛选逻辑 useEffect(() { let result [...products]; // 关键词筛选 if (filters.keyword) { result result.filter(product product.name.toLowerCase().includes(filters.keyword.toLowerCase()) ); } // 分类筛选 if (filters.category ! all) { result result.filter(product product.category filters.category); } // 品牌筛选 if (filters.brand.length 0) { result result.filter(product filters.brand.includes(product.brand)); } // 价格范围筛选 result result.filter( product product.price filters.priceRange[0] product.price filters.priceRange[1] ); setFilteredProducts(result); setCurrentPage(1); // 筛选后重置到第一页 }, [filters, products]); // 处理筛选条件变更 const handleFilterChange (key: keyof FilterParams, value: any) { setFilters(prev ({ ...prev, [key]: value })); }; // 分页数据计算 const paginatedProducts filteredProducts.slice( (currentPage - 1) * pageSize, currentPage * pageSize ); // 分类选项从商品数据中提取唯一值 const categoryOptions Array.from(new Set(products.map(p p.category))).map(cat ({ label: cat, value: cat, })); // 品牌选项从商品数据中提取唯一值 const brandOptions Array.from(new Set(products.map(p p.brand))).map(brand ({ label: brand, value: brand, })); return ( div style{{ padding: 20px, maxWidth: 1400px, margin: 0 auto }} h2 style{{ marginBottom: 20px, fontWeight: 600 }}眼镜商品列表/h2 {/* 筛选区域 */} div style{{ background: #f8f9fa, padding: 20px, borderRadius: 8px, marginBottom: 20px, display: flex, flexWrap: wrap, gap: 16px, alignItems: center }} div style{{ flex: 1, minWidth: 200px }} Input placeholder搜索商品名称... prefix{SearchOutlined /} value{filters.keyword} onChange{e handleFilterChange(keyword, e.target.value)} style{{ width: 100% }} / /div div style{{ width: 180px }} Select placeholder选择分类 value{filters.category} onChange{value handleFilterChange(category, value)} style{{ width: 100% }} Select.Option valueall全部分类/Select.Option {categoryOptions} /Select /div div style{{ flex: 1, minWidth: 250px }} div style{{ marginBottom: 8px, fontSize: 14px, color: #666 }}选择品牌/div div style{{ display: flex, flexWrap: wrap, gap: 8px }} {brandOptions.map(brand ( Checkbox key{brand.value} checked{filters.brand.includes(brand.value)} onChange{e { const newBrands e.target.checked ? [...filters.brand, brand.value] : filters.brand.filter(b b ! brand.value); handleFilterChange(brand, newBrands); }} {brand.label} /Checkbox ))} /div /div div style{{ width: 220px }} div style{{ marginBottom: 8px, fontSize: 14px, color: #666 }}价格范围/div div style{{ display: flex, gap: 8px }} Input typenumber placeholder最低 value{filters.priceRange[0] || } onChange{e handleFilterChange(priceRange, [ Number(e.target.value) || 0, filters.priceRange[1] ])} style{{ width: 50% }} / Input typenumber placeholder最高 value{filters.priceRange[1] || } onChange{e handleFilterChange(priceRange, [ filters.priceRange[0], Number(e.target.value) || 10000 ])} style{{ width: 50% }} / /div /div div button style{{ background: #1890ff, color: white, border: none, borderRadius: 4px, padding: 8px 16px, cursor: pointer, display: flex, alignItems: center, gap: 4px }} onClick{() setFilters({ keyword: , category: all, brand: [], priceRange: [0, 10000], })} FilterOutlined / 重置筛选 /button /div /div {/* 商品列表区域 */} Spin spinning{loading} tip加载商品中... {filteredProducts.length 0 ? ( Empty description暂无符合条件的商品 style{{ padding: 50px 0 }} / ) : ( div style{{ display: grid, gridTemplateColumns: repeat(auto-fill, minmax(220px, 1fr)), gap: 20px, marginBottom: 20px }} {paginatedProducts.map(product ( Card key{product.id} hoverable cover{img src{product.image} alt{product.name} style{{ height: 200px, objectFit: cover }} /} style{{ borderRadius: 8px, border: 1px solid #e8e8e8 }} Card.Meta title{ div style{{ fontSize: 14px, fontWeight: 500, marginBottom: 8px, display: -webkit-box, WebkitLineClamp: 2, WebkitBoxOrient: vertical, overflow: hidden }} {product.name} /div } description{ div span style{{ color: #ff4d4f, fontSize: 18px, fontWeight: 600 }} ¥{product.price} /span div style{{ fontSize: 12px, color: #999, marginTop: 4px, display: flex, justifyContent: space-between }} span品牌{product.brand}/span span销量{product.sales}/span /div /div } / /Card ))} /div {/* 分页区域 */} div style{{ display: flex, justifyContent: center, marginTop: 30px }} Pagination current{currentPage} pageSize{pageSize} total{filteredProducts.length} onChange{setCurrentPage} showSizeChanger{false} showQuickJumper showTotal{(total) 共 ${total} 件商品} / /div / )} /Spin /div ); }; export default ProductList;二、组件二次优化性能 体验 扩展性升级优化 1性能优化避免重复渲染 数据缓存// 1. 引入React.memo和useMemo/useCallback import React, { useState, useEffect, useMemo, useCallback } from react; // 2. 商品卡片组件单独抽离并使用memo缓存 const ProductCard React.memo(({ product }: { product: Product }) ( Card hoverable cover{img src{product.image} alt{product.name} style{{ height: 200px, objectFit: cover }} /} style{{ borderRadius: 8px, border: 1px solid #e8e8e8, transition: transform 0.3s ease }} onMouseEnter{(e) e.currentTarget.style.transform translateY(-5px)} onMouseLeave{(e) e.currentTarget.style.transform translateY(0)} Card.Meta title{ div style{{ fontSize: 14px, fontWeight: 500, marginBottom: 8px, display: -webkit-box, WebkitLineClamp: 2, WebkitBoxOrient: vertical, overflow: hidden }} {product.name} /div } description{ div span style{{ color: #ff4d4f, fontSize: 18px, fontWeight: 600 }} ¥{product.price} /span div style{{ fontSize: 12px, color: #999, marginTop: 4px, display: flex, justifyContent: space-between }} span品牌{product.brand}/span span销量{product.sales}/span /div /div } / /Card )); // 3. 筛选逻辑用useMemo缓存依赖变化才重新计算 const filteredProducts useMemo(() { return products.filter(product { const matchKeyword product.name.toLowerCase().includes(filters.keyword.toLowerCase()); const matchCategory filters.category all ? true : product.category filters.category; const matchBrand filters.brand.length 0 ? true : filters.brand.includes(product.brand); const matchPrice product.price filters.priceRange[0] product.price filters.priceRange[1]; return matchKeyword matchCategory matchBrand matchPrice; }); }, [filters, products]); // 4. 事件处理函数用useCallback缓存 const handleFilterChange useCallback((key: keyof FilterParams, value: any) { setFilters(prev ({ ...prev, [key]: value })); }, []); const resetFilters useCallback(() { setFilters({ keyword: , category: all, brand: [], priceRange: [0, 10000], }); }, []);优化 2交互体验升级// 1. 价格筛选改为滑块组件更直观 import { Slider } from antd; // 价格筛选区域替换为 div style{{ width: 250px }} div style{{ marginBottom: 8px, fontSize: 14px, color: #666 }} 价格范围¥{filters.priceRange[0]} - ¥{filters.priceRange[1]} /div Slider range min{0} max{10000} step{10} value{filters.priceRange} onChange{value handleFilterChange(priceRange, value as [number, number])} style{{ width: 100% }} / /div // 2. 品牌筛选添加全选/取消全选 div style{{ flex: 1, minWidth: 250px }} div style{{ display: flex, justifyContent: space-between, alignItems: center, marginBottom: 8px }} span style{{ fontSize: 14px, color: #666 }}选择品牌/span Checkbox checked{filters.brand.length brandOptions.length brandOptions.length 0} indeterminate{filters.brand.length 0 filters.brand.length brandOptions.length} onChange{e { const newBrands e.target.checked ? brandOptions.map(b b.value) : []; handleFilterChange(brand, newBrands); }} 全选 /Checkbox /div div style{{ display: flex, flexWrap: wrap, gap: 8px }} {brandOptions.map(brand ( Checkbox key{brand.value} checked{filters.brand.includes(brand.value)} onChange{e { const newBrands e.target.checked ? [...filters.brand, brand.value] : filters.brand.filter(b b ! brand.value); handleFilterChange(brand, newBrands); }} {brand.label} /Checkbox ))} /div /div // 3. 添加排序功能 const [sortType, setSortType] useStatedefault | priceAsc | priceDesc | salesDesc(default); // 排序后的商品数据 const sortedProducts useMemo(() { const copy [...filteredProducts]; switch (sortType) { case priceAsc: return copy.sort((a, b) a.price - b.price); case priceDesc: return copy.sort((a, b) b.price - a.price); case salesDesc: return copy.sort((a, b) b.sales - a.sales); default: return copy.sort((a, b) a.id - b.id); } }, [filteredProducts, sortType]); // 排序选择器添加在筛选区域下方 div style{{ display: flex, justifyContent: flex-end, marginBottom: 16px }} Select placeholder选择排序方式 value{sortType} onChange{setSortType} style{{ width: 200px }} Select.Option valuedefault默认排序/Select.Option Select.Option valuepriceAsc价格从低到高/Select.Option Select.Option valuepriceDesc价格从高到低/Select.Option Select.Option valuesalesDesc销量从高到低/Select.Option /Select /div // 分页数据改为基于排序后的数据 const paginatedProducts sortedProducts.slice( (currentPage - 1) * pageSize, currentPage * pageSize );优化 3扩展性升级支持自定义配置// 1. 定义组件Props支持外部传入配置 interface ProductListProps { pageSize?: number; maxPrice?: number; placeholder?: string; onProductClick?: (product: Product) void; } // 2. 组件接收Props并设置默认值 const ProductList: React.FCProductListProps ({ pageSize 12, maxPrice 10000, placeholder 搜索商品名称..., onProductClick, }) { // 3. 价格筛选最大值使用外部传入的maxPrice const [filters, setFilters] useStateFilterParams({ keyword: , category: all, brand: [], priceRange: [0, maxPrice], }); // 4. 商品卡片添加点击事件 ProductCard key{product.id} product{product} onClick{() onProductClick?.(product)} / }; // 5. 暴露默认导出 export default ProductList;优化后组件核心优势性能更优通过memo、useMemo、useCallback减少重复渲染筛选逻辑惰性计算体验更好滑块价格筛选、品牌全选、排序功能操作更直观高效扩展性强支持自定义分页大小、价格上限、搜索占位符以及商品点击回调视觉更美观商品卡片 hover 动画、布局响应式适配适配不同屏幕尺寸。