React进阶

React中的事件

这里的事件:React内置的DOM组件中的事件

  1. 几乎所有的元素的事件处理,均在document的事件中处理,React会根据虚拟DOM树的完成事件函数的调用
    1. 一些不冒泡的事件,是直接在元素上监听
    2. 一些document上面没有的事件,直接在元素上监听
    3. 如果给真实的DOM注册事件,阻止了事件冒泡,则会导致react的相应事件无法触发(和第三方dom插件混用是需要特别注意)
    4. 如果给真实的DOM注册事件,事件会先于React事件运行
  2. React的事件参数,并非真实的DOM事件参数,是React合成的一个对象,该对象类似于真实DOM的事件参数
    1. e.stopPropagation,通过React的事件中阻止事件冒泡,无法阻止真实的DOM事件冒泡,阻止事件在虚拟DOM树中冒泡(demo1)
    2. nativeEvent,可以得到真实的DOM事件对象
    3. 可以通过e.nativeEvent.stopImmediatePropagation(),阻止document上剩余事件的执行
    4. 为了提高执行效率,React使用事件对象池来处理事件,事件事件中e是同一个
    5. 在事件处理程序中,不要异步的使用事件对象。如果一定要使用,需要调用persist函数
for (const handler of eventHandlers) {
  handler(e);
  if (e.isStopped) {
    break;
  }
}
虚拟dom和真实dom

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2etkQ81K-1600487421956)(./react-learn/public/1.png)]

深入认识setState

setState,它对状态的改变,可能是异步的

如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步(比如在定时器中改变state中的值,改变后立刻就可以获取的改变后的值)

如果遇到某个事件中,需要同步调用多次,需要使用函数的方式得到最新状态

最佳实践:

  1. 把所有的setState当作是异步的
  2. 永远不要信任setState调用之后的状态
  3. 如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)
  4. 如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)

React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对state进行改变,然后触发render)

### React 进阶教程:高级用法与深入理解 #### 一、React 插槽(Portals) React 的插槽(Portals)是一种特殊的渲染机制,允许开发者将子节点渲染到 DOM 层次结构之外的位置。通过 `ReactDOM.createPortal` 方法,可以在不破坏现有组件层次的情况下,将某些 UI 元素放置在特定位置,比如模态框或工具提示。这种方法特别适用于需要脱离父容器样式影响的场景[^2]。 ```javascript const Modal = (props) => { return ReactDOM.createPortal( <div className="modal"> {props.children} </div>, document.getElementById('portal-root') // 渲染目标DOM节点 ); }; ``` --- #### 二、复杂的组件通信模式——Context API 随着应用程序规模的增长,传统的 props drilling 方式会变得繁琐且难以维护。React 提供了 Context API 来解决跨层级通信的需求。通过创建上下文对象并将其提供给后代组件,可以轻松实现全局状态共享[^3]。 以下是基于 Context 和 Hooks 实现的一个简单例子: ```javascript // 创建上下文 const ThemeContext = React.createContext(); // Provider 组件 function App() { const [theme, setTheme] = React.useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}> <Toolbar /> </ThemeContext.Provider> ); } // Consumer 组件 function Toolbar() { return ( <ThemeContext.Consumer> {({ theme, setTheme }) => ( <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle {theme} Mode </button> )} </ThemeContext.Consumer> ); } ``` 如果使用函数组件,则可以通过 `useContext` Hook 替代 Consumer[^4]: ```javascript function Toolbar() { const { theme, setTheme } = React.useContext(ThemeContext); return ( <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}> Toggle {theme} Mode </button> ); } ``` --- #### 三、React 高级优化技术 为了提升性能和用户体验,React 推出了许多高级功能和技术,例如 Memoization 和 Refs。 ##### 1. **Memoization** 对于纯展示型组件,可以利用 `React.memo` 或 `shouldComponentUpdate` 减少不必要的重新渲染。这有助于提高大型列表或频繁更新区域的效率[^1]。 ```javascript const ExpensiveChild = React.memo((props) => { console.log('ExpensiveChild rendered'); return <div>{props.value}</div>; }); ``` ##### 2. **Refs** 当需要操作原生 DOM 节点或者访问子组件实例时,可以借助 `useRef` 或类组件中的 `ref` 属性来完成任务。 ```javascript const inputEl = useRef(null); const focusInput = () => { inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> <button onClick={focusInput}>Focus Input</button> </> ); ``` --- #### 四、Redux 状态管理集成 在复杂应用中,推荐结合 Redux 进行集中化状态管理。通过 `react-redux` 库提供的 `Provider` 和 `connect`/`useSelector`,能够方便地连接 React 组件与 Redux Store。 ```javascript import { useSelector, useDispatch } from 'react-redux'; function Counter() { const count = useSelector(state => state.counter); // 订阅state变化 const dispatch = useDispatch(); // 获取dispatch方法 return ( <div> Count: {count} <button onClick={() => dispatch({ type: 'INCREMENT' })}> Increment </button> </div> ); } ``` --- #### 五、总结 上述内容涵盖了 React 中的一些重要进阶知识点,包括 Portals、Context API、Memoization、Refs 及 Redux 集成等。掌握这些技能可以帮助开发人员更高效地构建现代化前端应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值