百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

25个React最佳实践小技巧_reactor设计模式

myzbx 2025-09-18 23:48 4 浏览

以下是 25 个 React 开发中实用的最佳实践与小技巧,覆盖组件设计、状态管理、性能优化、代码规范、错误处理等核心场景,每个技巧均附示例和核心原因,帮助你写出更高效、可维护的 React 代码。

一、组件设计基础(1-5)

1. 优先使用函数组件 + Hooks,替代类组件

React 16.8+ 推荐的开发模式,函数组件更简洁、易读,Hooks(如useState/useEffect)能替代类组件的生命周期,避免this指向问题。

// 推荐:函数组件
function Counter() {
    const [count, setCount] = useState(0);
    return (
        <button onClick={() => setCount(prev => prev + 1)}>
          计数:{count}
        </button>
    );
}

// 不推荐:类组件(除非维护旧代码)
class Counter extends React.Component {
    state = { count: 0 };
    render() {
        return (
            <button onClick={() => this.setState({ count: this.state.count + 1 })}>
              计数:{this.state.count}
            </button>
        );
    }
}

2. 组件拆分遵循 “单一职责” 原则

每个组件只负责一件事,避免大组件(如几百行的 “万能组件”),拆分后更易维护、复用和测试。

// 反例:一个组件包含“筛选+列表+分页”所有逻辑
function UserPage() {
  const [users, setUsers] = useState([]);
  const [filterText, setFilterText] = useState("");
  const [page, setPage] = useState(1);

  // 筛选逻辑、分页逻辑、请求逻辑混在一起...
  return (
    <div>
        <input onChange={(e) => setFilterText(e.target.value)} />
        <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>
        <button onClick={() => setPage(prev => prev - 1)}>上一页</button>
    </div>
  );
}

// 正例:拆分为3个独立组件
function UserFilter({ onFilter }) {
	  return <input onChange={(e) => onFilter(e.target.value)} />;
}

function UserList({ users }) {
 	 return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

function Pagination({ page, onPageChange }) {
 	 return <button onClick={() => onPageChange(page - 1)}>上一页</button>;
}

// 父组件仅负责“组合”,不处理具体逻辑
function UserPage() {
  const [users, setUsers] = useState([]);
  const [filterText, setFilterText] = useState("");
  const [page, setPage] = useState(1);

  // 仅保留核心逻辑(如请求、状态同步)
  return (
      <div>
          <UserFilter onFilter={setFilterText} />
          <UserList users={users} />
          <Pagination page={page} onPageChange={setPage} />
      </div>
  );
}

3. 用 PropTypes/TypeScript 约束 Props 类型

避免因 Props 类型错误导致的运行时问题,提升代码可读性(TypeScript 更推荐,支持全项目类型校验)。

// 1. PropTypes(轻量,适合小型项目)
import PropTypes from 'prop-types';

function UserCard({ name, age, isVip }) {
  	return <div>{name}({age}岁){isVip ? "VIP" : ""}</div>;
}

UserCard.propTypes = {
    name: PropTypes.string.isRequired, // 必传字符串
    age: PropTypes.number, // 可选数字
    isVip: PropTypes.bool.defaultProps.false, // 可选布尔,默认false
};

// 2. TypeScript(推荐,强类型约束)
interface UserCardProps {
    name: string; // 必传
    age?: number; // 可选
    isVip?: boolean;
}

function UserCard({ name, age = 18, isVip = false }: UserCardProps) {
   return <div>{name}({age}岁){isVip ? "VIP" : ""}</div>;
}

4. 合理设置 Props 默认值

通过defaultProps(旧)或 “解构赋值默认值”(新)设置 Props 默认值,避免undefined导致的渲染错误。

// 推荐:解构赋值设置默认值(更直观)
function Button({ 
    type = "button", // 默认按钮类型
    children = "点击", // 默认文本
    disabled = false 
}) {
 		 return <button type={type} disabled={disabled}>{children}</button>;
}

// 调用时可省略默认Props
<Button /> // 等效于 <Button type="button" children="点击" disabled={false} />
<Button type="submit" children="提交" />

5. 使用 Fragment 避免多余 DOM 节点

当组件需要返回多个同级元素时,用<></>(短语法)或<React.Fragment>包裹,避免添加无意义的<div>。

使用场景

  • 列表渲染:需唯一标识子元素时,必须使用<React.Fragment>。
  • 简单分组:无需额外属性时,优先使用<></>以保持代码简洁。


// 推荐:Fragment
function UserInfo({ name, age }) {
  return (
    <>
      <p>姓名:{name}</p>
      <p>年龄:{age}</p>
    </>
  );
}

// 不推荐:多余div
function UserInfo({ name, age }) {
  return (
    <div> {/* 无意义的DOM节点,增加DOM树复杂度 */}
      <p>姓名:{name}</p>
      <p>年龄:{age}</p>
    </div>
  );
}

二、Hooks 正确使用(6-9)

6. 避免直接修改 State,用 “函数式更新” 依赖前状态

当 State 更新依赖前一次状态(如计数、累加)时,必须用函数式更新(setState(prev => prev + 1)),避免因 React 状态异步更新导致的错误。

// 错误:直接依赖当前state(可能获取到旧值)
function Counter() {
  const [count, setCount] = useState(0);
  const handleAdd = () => {
    // 若连续调用,可能只加1(因count是闭包中的旧值)
    setCount(count + 1);
    setCount(count + 1);
  };
  return <button onClick={handleAdd}>{count}</button>;
}

// 正确:函数式更新(确保获取最新state)
function Counter() {
  const [count, setCount] = useState(0);
  const handleAdd = () => {
    setCount(prev => prev + 1);
    setCount(prev => prev + 1); // 最终count+2
  };
  return <button onClick={handleAdd}>{count}</button>;
}

7. useEffect 必做 “副作用清理”,避免内存泄漏

useEffect用于处理副作用(如请求、定时器、事件监听),若副作用有 “持续消耗”(如定时器),必须在返回函数中清理,防止组件卸载后仍执行。

function Timer() {
  const [time, setTime] = useState(0);

  useEffect(() => {
    // 副作用:启动定时器
    const timer = setInterval(() => {
      setTime(prev => prev + 1);
    }, 1000);

    // 清理函数:组件卸载/依赖变化时执行
    return () => {
      clearInterval(timer); // 清除定时器,避免内存泄漏
    };
  }, []); // 空依赖:仅执行一次(组件挂载时)

  return <div>已运行:{time}秒</div>;
}

8. 不在循环 / 条件 / 嵌套函数中调用 Hooks

Hooks 依赖 “调用顺序稳定” 实现状态管理,若在循环、if或嵌套函数中调用,会导致 React 无法匹配 Hooks 与状态,触发报错。

// 错误:在if中调用useState
function WrongComponent({ isShow }) {
  if (isShow) {
    const [count, setCount] = useState(0); // 可能不执行,破坏顺序
  }
  return <div></div>;
}

// 正确:Hooks置顶调用
function RightComponent({ isShow }) {
  const [count, setCount] = useState(0); // 始终执行,顺序稳定
  return isShow ? <div>{count}</div> : <div>隐藏</div>;
}

9. 用自定义 Hooks 抽取复用逻辑

将组件中重复的逻辑(如表单处理、请求、定时器)抽为自定义 Hooks,提升复用性(命名必须以use开头,符合 Hooks 规则)。

// 自定义Hook:处理表单输入
function useFormInput(initialValue) {
  const [value, setValue] = useState(initialValue);
  const handleChange = (e) => {
    setValue(e.target.value);
  };
  // 返回“状态+操作函数”
  return { value, onChange: handleChange };
}

// 复用Hook:登录表单
function LoginForm() {
  const username = useFormInput("");
  const password = useFormInput("");
  return (
    <div>
      <input type="text" placeholder="用户名" {...username} />
      <input type="password" placeholder="密码" {...password} />
    </div>
  );
}

// 复用Hook:注册表单
function RegisterForm() {
  const email = useFormInput("");
  return <input type="email" placeholder="邮箱" {...email} />;
}

三、状态管理优化(10-12)

10. 复杂状态用 useReducer 替代多个 useState

当状态逻辑包含多个子值(如表单多字段、复杂状态切换)或状态更新依赖复杂逻辑时,useReducer比多个useState更清晰。

// 反例:多个useState管理表单,逻辑分散
function Form() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState("");

  const handleSubmit = async () => {
    setIsLoading(true);
    setError("");
    try {
      await api.login(username, password);
    } catch (err) {
      setError(err.message);
    } finally {
      setIsLoading(false);
    }
  };
}

// 正例:useReducer集中管理状态
const initialState = {
  username: "",
  password: "",
  isLoading: false,
  error: ""
};

function formReducer(state, action) {
  switch (action.type) {
    case "UPDATE_FIELD":
      return { ...state, [action.field]: action.value };
    case "SUBMIT_START":
      return { ...state, isLoading: true, error: "" };
    case "SUBMIT_ERROR":
      return { ...state, isLoading: false, error: action.error };
    case "SUBMIT_SUCCESS":
      return { ...state, isLoading: false };
    default:
      return state;
  }
}

function Form() {
  const [state, dispatch] = useReducer(formReducer, initialState);

  const handleSubmit = async () => {
    dispatch({ type: "SUBMIT_START" });
    try {
      await api.login(state.username, state.password);
      dispatch({ type: "SUBMIT_SUCCESS" });
    } catch (err) {
      dispatch({ type: "SUBMIT_ERROR", error: err.message });
    }
  };

  return (
    <div>
      <input
        value={state.username}
        onChange={(e) => dispatch({
          type: "UPDATE_FIELD",
          field: "username",
          value: e.target.value
        })}
      />
      {/* 其他表单元素... */}
    </div>
  );
}

11. 区分 “局部状态” 与 “全局状态”,避免过度全局化

  • 局部状态:仅组件内部或子组件使用(如按钮计数、表单输入)→ 用useState/useReducer。
  • 全局状态:多组件共享(如用户信息、主题配置)→ 用Context + useReducer或Redux Toolkit(避免用Context管理频繁变化的状态,会导致全局重渲染)。
// 全局状态示例:用户信息Context
const UserContext = createContext(null);

// Provider组件:包裹应用,提供全局状态
function UserProvider({ children }) {
  const [user, setUser] = useState(null);

  const login = (userInfo) => setUser(userInfo);
  const logout = () => setUser(null);

  return (
      <UserContext.Provider value={{ user, login, logout }}>
       	 {children}
      </UserContext.Provider>
  );
}

// 任意子组件使用全局状态
function Navbar() {
    const { user, logout } = useContext(UserContext);
    return user ? (
      <div>欢迎{user.name} <button onClick={logout}>退出</button></div>
    ) : (
      <div>请登录</div>
    );
}

12. 避免 “Prop Drilling”(属性透传)

当组件层级较深(如 A→B→C→D),且 D 需要 A 的状态时,不要逐层传递 Props,用Context或状态管理库(如 Redux)直接获取。

// 反例:Prop Drilling(B、C无意义地传递user)
function A() {
  const [user] = useState({ name: "张三" });
  return <B user={user} />;
}

function B({ user }) {
  return <C user={user} />; // B不需要user,仅透传
}

function C({ user }) {
  return <D user={user} />; // C不需要user,仅透传
}

function D({ user }) {
  return <div>{user.name}</div>; // 仅D需要user
}

// 正例:Context直接获取(B、C无需关心)
const UserContext = createContext(null);

function A() {
  const [user] = useState({ name: "张三" });
  return (
      <UserContext.Provider value={user}>
          <B />
      </UserContext.Provider>
  );
}

function B() {
    return <C />; // 无需透传
}

function C() {
    return <D />; // 无需透传
}

function D() {
    const user = useContext(UserContext);
    return <div>{user.name}</div>; // 直接获取
}

四、性能优化(13-18)

13. 用 React.memo 缓存纯 UI 组件

当组件的 Props 未变化时,用React.memo避免不必要的重渲染(仅适用于 “纯组件”:Props 相同则输出相同)。

// 子组件:纯UI组件(仅依赖Props渲染)
const UserCard = React.memo(function UserCard({ user }) {
  console.log("UserCard重渲染"); // Props不变时不执行
  return <div>{user.name}</div>;
});

// 父组件
function UserList() {
  const [count, setCount] = useState(0);
  const user = { name: "张三" }; // 注意:对象每次渲染会新建,导致UserCard误重渲染!

  return (
    <div>
      <button onClick={() => setCount(prev => prev + 1)}>计数:{count}</button>
      <UserCard user={user} />
    </div>
  );
}

注意:若 Props 是对象 / 函数,需配合useMemo/useCallback缓存,否则React.memo失效(见 14、15)。

14. 用 useMemo 缓存计算密集型结果

当组件中有复杂计算(如大数据过滤、排序),用useMemo缓存结果,避免每次渲染重复计算。

function UserList({ users, filterText }) {
  // 复杂计算:过滤用户(若users/filterText不变,直接复用缓存结果)
  const filteredUsers = useMemo(() => {
    console.log("执行过滤计算"); // 依赖不变时不执行
    return users.filter(user => user.name.includes(filterText));
  }, [users, filterText]); // 依赖数组:仅当users或filterText变化时重新计算

  return <ul>{filteredUsers.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

15. 用 useCallback 缓存函数,避免子组件重渲染

当父组件向子组件传递函数时,函数每次渲染会新建(导致子组件React.memo失效),用useCallback缓存函数引用。

function Parent() {
  const [count, setCount] = useState(0);
  const user = useMemo(() => ({ name: "张三" }), []); // 缓存对象

  // 缓存函数:仅当count变化时新建函数
  const handleClick = useCallback(() => {
    console.log("点击", count);
  }, [count]);

  return (
    <div>
      <button onClick={() => setCount(prev => prev + 1)}>计数:{count}</button>
      {/* 子组件Props(user+handleClick)均缓存,不会误重渲染 */}
      <UserCard user={user} onClick={handleClick} />
    </div>
  );
}

16. 列表渲染必须用 “稳定的 key”

key是 React 识别列表项的唯一标识,必须满足:

  • 不重复(同列表内);
  • 稳定(不随渲染顺序变化,如不用index作为 key)。
// 错误:用index作为key(删除中间项时,后续项key变化,导致DOM复用错误)
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map((todo, index) => (
        <li key={index}>{todo.text}</li> // 危险!
      ))}
    </ul>
  );
}

// 正确:用数据唯一ID作为key(如后端返回的id)
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li> // 稳定、唯一
      ))}
    </ul>
  );
}

17. 长列表用 “虚拟列表” 优化

当列表数据量极大(如 1000 + 项),直接渲染所有 DOM 会导致性能问题,用虚拟列表(如
react-window/react-virtualized)只渲染 “可视区域” 的项。

import { FixedSizeList as List } from 'react-window';

// 虚拟列表:仅渲染可视区域的20项(无论总数据多少)
function LongUserList({ users }) {
  const Row = ({ index, style }) => (
    <div style={style}> {/* 必须传递style(定位可视区域) */}
      {users[index].name}
    </div>
  );

  return (
    <List
      height={500} // 列表容器高度
      width="100%" // 列表容器宽度
      itemCount={users.length} // 总数据量
      itemSize={50} // 每一项高度
    >
      {Row}
    </List>
  );
}

18. 组件懒加载(React.lazy + Suspense)

用React.lazy动态导入组件,配合Suspense显示加载状态,减少首屏 JS 体积,提升首屏加载速度(仅支持默认导出组件)。

// 1. 懒加载组件(动态导入,不在首屏加载)
const Home = React.lazy(() => import('./Home'));
const About = React.lazy(() => import('./About'));

// 2. 路由中使用(配合Suspense)
function App() {
  return (
    <Router>
      <Suspense fallback={<div>加载中...</div>}> {/* 加载时显示的占位 */}
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

五、路由与样式(19-21)

19. React Router v6+ 最佳实践

  • 用useNavigate替代useHistory(v6 移除useHistory);
  • 用Routes包裹Route(替代 v5 的Switch);
  • 路由守卫(PrivateRoute)控制权限。
// 1. 路由守卫:PrivateRoute(仅登录用户可访问)
function PrivateRoute({ children }) {
  const { user } = useContext(UserContext);
  const navigate = useNavigate();

  if (!user) {
    navigate("/login"); // 未登录跳转登录页
    return null;
  }
  return children; // 已登录显示子组件
}

// 2. 路由配置
function App() {
  return (
    <Router>
      <Suspense fallback={<div>加载中...</div>}>
        <Routes>
          <Route path="/login" element={<Login />} />
          {/* 受保护路由:用PrivateRoute包裹 */}
          <Route path="/dashboard" element={
            <PrivateRoute>
              <Dashboard />
            </PrivateRoute>
          } />
        </Routes>
      </Suspense>
    </Router>
  );
}

// 3. 页面跳转(useNavigate)
function Login() {
  const navigate = useNavigate();
  const handleLogin = () => {
    // 登录成功后跳转仪表盘
    navigate("/dashboard");
  };
  return <button onClick={handleLogin}>登录</button>;
}

20. 样式隔离:用 CSS Modules 或 Styled Components

避免样式全局污染,推荐两种方案:

  • CSS Modules:样式文件与组件绑定,类名自动哈希;
  • Styled Components:CSS-in-JS,组件与样式一体化。
// 1. CSS Modules(推荐,无额外依赖)
// UserCard.module.css
.userCard {
      color: #333;
      border: 1px solid #eee;
}

// UserCard.jsx
import styles from './UserCard.module.css';

function UserCard() {
  return <div className={styles.userCard}>用户卡片</div>;
  // 渲染后类名:userCard__123(哈希值,避免冲突)
}

// 2. Styled Components(适合动态样式)
import styled from 'styled-components';

// 定义样式组件
const StyledButton = styled.button`
  padding: 8px 16px;
  background: ${props => props.disabled ? '#ccc' : '#007bff'};
  color: white;
  border: none;
`;

function Button({ disabled, children }) {
  return <StyledButton disabled={disabled}>{children}</StyledButton>;
}

21. 避免内联样式(除非动态样式)

内联样式(style={{...}})优先级高、无法使用伪类(如:hover)、难以维护,仅在需要动态计算样式时使用。

// 不推荐:内联样式(无法用伪类,维护难)
function Button() {
  return (
    <button style={{
      padding: "8px 16px",
      backgroundColor: "#007bff",
      color: "white"
    }}>点击</button>
  );
}

// 推荐:CSS Modules/Styled Components(支持伪类)
// Button.module.css
.button {
  padding: 8px 16px;
  background: #007bff;
  color: white;
}
.button:hover {
  background: #0056b3; // 支持伪类
}

function Button() {
  import styles from './Button.module.css';
  return <button className={styles.button}>点击</button>;
}

六、错误处理与测试(22-25)

22. 用 Error Boundary 捕获组件树错误

React 16+ 提供Error Boundary组件,捕获子组件树的运行时错误(如渲染错误、Props 错误),避免整个应用崩溃。

// 1. 定义Error Boundary组件(必须是类组件)
class ErrorBoundary extends React.Component {
  state = { hasError: false, errorMsg: "" };

  // 捕获子组件错误
  static getDerivedStateFromError(error) {
    return { hasError: true, errorMsg: error.message };
  }

  // 日志上报(可选)
  componentDidCatch(error, errorInfo) {
    console.error("组件错误:", error, errorInfo);
    // 上报到监控平台:如Sentry
    // sentry.captureException(error, { extra: errorInfo });
  }

  render() {
    if (this.state.hasError) {
      // 错误UI:替代崩溃的子组件
      return <div>出错了:{this.state.errorMsg}</div>;
    }
    // 无错误时渲染子组件
    return this.props.children;
  }
}

// 2. 使用Error Boundary包裹易出错组件
function App() {
  return (
    <div>
      <h1>我的应用</h1>
      {/* 包裹可能出错的组件(如请求数据的组件) */}
      <ErrorBoundary>
        <UserList />
      </ErrorBoundary>
    </div>
  );
}

23. 异步逻辑错误处理(try/catch + useEffect)

useEffect中异步请求的错误无法被Error Boundary捕获,必须用try/catch手动处理。

function UserList() {
  const [users, setUsers] = useState([]);
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 异步请求必须用try/catch
    const fetchUsers = async () => {
      try {
        setLoading(true);
        const res = await api.get("/users");
        setUsers(res.data);
      } catch (err) {
        // 捕获错误,更新状态显示
        setError("获取用户失败:" + err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUsers();
  }, []);

  if (loading) return <div>加载中...</div>;
  if (error) return <div style={{ color: "red" }}>{error}</div>;
  return <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}

24. 统一代码规范:ESLint + Prettier

  • ESLint:检查代码语法错误、React 最佳实践(如react-hooks/rules-of-hooks);
  • Prettier:统一代码格式(缩进、换行、引号),避免格式争论。
// .eslintrc.js(React项目配置)
module.exports = {
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:react-hooks/recommended", // Hooks规则
    "prettier" // 与Prettier兼容
  ],
  rules: {
    "react/prop-types": "error", // 强制PropTypes校验
    "react-hooks/rules-of-hooks": "error", // Hooks调用规则
    "react-hooks/exhaustive-deps": "warn" // useEffect依赖检查
  }
};

25. 编写测试:Jest + React Testing Library

测试是保证代码质量的关键,推荐用Jest(测试运行器)+React Testing Library(组件测试库),聚焦 “用户行为” 而非实现细节。

// Counter.jsx(待测试组件)
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <span data-testid="count">{count}</span>
      <button onClick={() => setCount(prev => prev + 1)}>加1</button>
    </div>
  );
}

// Counter.test.jsx(测试文件)
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test("点击按钮计数增加", () => {
  // 1. 渲染组件
  render(<Counter />);

  // 2. 验证初始状态
  expect(screen.getByTestId("count")).toHaveTextContent("0");

  // 3. 模拟用户行为(点击按钮)
  const button = screen.getByText("加1");
  fireEvent.click(button);

  // 4. 验证结果
  expect(screen.getByTestId("count")).toHaveTextContent("1");
});

总结

React 最佳实践的核心是 “简洁、可维护、高性能”:

  • 组件设计遵循单一职责,拆分合理;
  • Hooks 使用严格遵守规则,抽取复用逻辑;
  • 状态管理区分局部 / 全局,避免过度复杂;
  • 性能优化聚焦 “减少不必要重渲染” 和 “降低首屏体积”;
  • 错误处理和测试保障代码稳定性。

根据项目规模(小型用 Context+useReducer,大型用 Redux Toolkit)灵活选择方案,同时保持代码规范统一,可大幅提升开发效率和项目可维护性。

相关推荐

vue:生命周期钩子函数及顺序_列举出5个vue中常用的生命周期钩子函数

一、vue的钩子相关顺序Vue实例有一个完整的生命周期,在newVue()后,会初始化数据,如下://初始化的入口,各种初始化工作initMixin(Vue);//数据绑定的核心方法,包括常用...

最长递增子序列:从经典算法到 Vue3 运行时核心优化

最长递增子序列(LongestIncreasingSubsequence,LIS)正悄然成为性能分水岭。它不仅是面试的高频考点,更是Vue3快速Diff算法赖以实现O(nlogn)...

十分钟掌握Vue 3性能优化:实战技巧与避坑指南

「为什么我的Vue应用越做越卡?」这是最近团队新人最常问的问题。本文将从真实电商项目出发,手把手教你用Vue3的现代特性实现性能飞跃,文末还准备了可复用的优化检查清单!一、先看疗效:优化前后对比优...

JavaScript学习 -- 文本节点_html 文本节点

什么是文本节点在HTML文档中,文本节点是一种特殊的dom节点,它包含文本内容,没有任何标记或属性。<p>这是一段文本节点</p>在上面的代码中,<p>元素包含了...

JavaScript中this指向各种场景_javascript的this指向

在JavaScript中,this的指向是一个核心概念,其值取决于函数的调用方式,而非定义位置(箭头函数除外)。以下是this指向的常见场景及具体说明:1.全局作用域中的this在全局作用域(非...

v-if和v-for的优先级是什么?_v-if和v-for的区别,什么时候用

#一、作用v-if指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true值的时候被渲染v-for指令基于一个数组来渲染一个列表。v-for指令需要使用iteminitems...

Vue插槽(Slot)深度解析:从匿名到作用域的组件复用革命

在Vue组件化开发中,内容分发始终是核心挑战之一。当我们需要让组件既能保持结构复用,又能灵活定制局部内容时,插槽(Slot)机制应运而生。从基础的匿名插槽到复杂的作用域插槽,Vue的插槽系统逐步解决了...

手摸手带你解决AI应用开发中Markdown渲染问题

使用Markdown-It+VueRender实现安全可控的Markdown渲染在前端项目中,Markdown的渲染经常使用markdown-it。它功能丰富、插件多,但默认的渲染方...

Vue3 新趋势:10 个最强 X 操作!_vue.3

Vue3为前端开发带来了诸多革新,它不仅提升了性能,还提供了更简洁、更强大的API。以下是十个最值得学习和使用的Vue3API,它们将助力你的开发工作迈向新高度。浅层响应式API:shall...

25个React最佳实践小技巧_reactor设计模式

以下是25个React开发中实用的最佳实践与小技巧,覆盖组件设计、状态管理、性能优化、代码规范、错误处理等核心场景,每个技巧均附示例和核心原因,帮助你写出更高效、可维护的React代码。一...

javascript函数的call、apply和bind的原理及作用详解

javascript函数的call、apply和bind本质是用来实现继承的,专业点说法就是改变函数体内部this的指向,当一个对象没有某个功能时,就可以用这3个来从有相关功能的对象里借用过来...

简单介绍一下前端各框架中的模板标签

在各大前端框架、小程序中,此类标签的作用主要是用来帮助我们包裹多个元素。在浏览器实际渲染中会将其移除只渲染其包裹的DOM元素,所以说不会增加额外的DOM节点在小程序中使用小程序中的模板标签是<...

面试官问我,后端一次性返回十万条数据,前端应该怎么处理 ?

问题描述面试官:后端一次性返回10万条数据给你,你如何处理?我:歪嘴一笑,马上给后端发送一百万次请求,干蹦他的服务器,让他给爷哭!问题考察点性能优化意识(能否识别出“10万条数据”会导致性能问题?是...

React系列十 - 高阶组件以及组件补充

源自:coderwhy一.高阶组件1.1.认识高阶组件什么是高阶组件呢?相信很多同学都听说过,也用过高阶函数,它们非常相似,所以我们可以先来回顾一下什么是高阶函数。高阶函数的维基百科定义:至少...

从0开始写一个虚拟滚动组件_虚拟滚动原理

如果一个页面有1W+条数据,该怎么渲染比较好。不管是在我们的实际项目开发中还是在面试的过程中都会遇到类似的问题。相信很多同学会想到分页。当然这也是最传统也是最保底的解决方案了。如果有开发过electr...