网站建设南京公司,网站建设与管理复习知识点,仿站网,淘宝联盟的网站管理怎么做文章目录 函数组件的特点props组件间的传值父传子看上例子传父兄弟组件传值祖先组件传值 插槽基础插槽具名插槽作用域插槽 样式操作**CSS Modules** 生命周期useRef常用hookuseStateuseEffectuseContextuseReduceruseMemouseCallback 高阶组件什么时候使用 react性能问题和优化… 文章目录 函数组件的特点props组件间的传值父传子看上例子传父兄弟组件传值祖先组件传值 插槽基础插槽具名插槽作用域插槽 样式操作**CSS Modules** 生命周期useRef常用hookuseStateuseEffectuseContextuseReduceruseMemouseCallback 高阶组件什么时候使用 react性能问题和优化React的时间切片fiber避免父组件数据导致子组件更新 函数组件的特点
函数组件没有生命周期函数组件没有this函数组件通过hook来完成各种操作函数组件本身的函数体相当于render函数props在函数的第一个参数接受
props
props是react中的核心 在react中一切写在组件上的属性和子节点都被规划为了props。 所以props是react很多功能的根本。父子传值插槽全都是基于props不像Vue有事件监听emit专门的插槽这一类东西
//也可以给默认值
function Avatar({ person, size 100 }) {return (imgclassNameavatarsrc{getImageUrl(person)}alt{person.name}width{size}height{size}/);
}export default function Profile() {return (divAvatarsize{100}person{{ name: Katsuko Saruhashi, imageId: YfeOqp2}}//div);
}
组件间的传值
父传子看上例
子传父
子组件可以通过回调函数将数据传递回父组件。没有Vue中的emit和expose方法
// 子组件const ChildComponent ({ onSendData }) {return button onClick{() onSendData(Hello from Child!)}Send Data/button;};// 父组件const ParentComponent () {const handleData (data) {console.log(data);};return ChildComponent onSendData{handleData} /;};兄弟组件传值
与Vue相同 都是通过父组件作为中介来传递数据。
// 第一个兄弟组件const BrotherOne ({ onSendData }) {return button onClick{() onSendData(Data from Brother One)}Send Data/button;};// 第二个兄弟组件const BrotherTwo ({ data }) {return h1{data}/h1;};// 父组件const ParentComponent () {const [data, setData] React.useState();const handleDataChange (newData) {setData(newData);};return (divBrotherOne onSendData{handleDataChange} /BrotherTwo data{data} //div);};祖先组件传值
import React, { createContext, useContext, useState } from react;JJ// 创建 Contextconst MyContext createContext();// 提供者组件const MyProvider ({ children }) {const [value, setValue] useState(Hello from Context!);return (MyContext.Provider value{{ value, setValue }}J{children}/MyContext.Provider);};// 使用 Context 的子组件const ChildComponent () {const { value } useContext(MyContext);return h1{value}/h1;};// 父组件const ParentComponent () {return (MyProviderChildComponent //MyProvider);};插槽
在 React 中虽然没有 Vue 的插槽(slot)具名插槽 作用域插槽,但是可以实现 插槽本质上讲就是子组件的html内容需要父组件传入在jsx的加持下我可以把html像普通的字符串数字一样传递所以插槽只需要直接作为props传入就行
基础插槽
在基础插槽中我们可以使用 children prop 来接收父组件传递的内容
import React from react;// 容器组件支持基础插槽const Container ({ children }) {return (div classNamecontainerh2Container Header/h2div classNamecontent{children}/div/div);};// 使用容器组件const App () {return (ContainerpThis is the content inside the container./p/Container);};
export default App;具名插槽
可以通过将不同的 props 传递给子组件来实现。我们可以使用标准的 JSX 语法来实现具名插槽
import React from react;
// 容器组件支持具名插槽const Container ({ header, footer, children }) {return (div classNamecontainerdiv classNameheader{header}/divdiv classNamecontent{children}/divdiv classNamefooter{footer}/div/div);};// 使用容器组件const App () {return (Containerheader{h1This is the Header/h1}footer{h2This is the Footer/h2}pThis is the main content area./p/Container
);
};
export default App;作用域插槽
允许我们将数据传递到子组件使得父组件可以控制子组件的渲染。我们可以通过传递一个函数作为 prop 来实现
import React from react;
// 容器组件支持作用域插槽const ListContainer ({ items, renderItem }) {return (ul{items.map(item (li key{item.id}{renderItem(item)}/li))}/ul);};
// 使用容器组件const App () {const items [{ id: 1, text: Item 1 },{ id: 2, text: Item 2 },{ id: 3, text: Item 3 }];const renderItem (item) span{item.text}/span;return (ListContainer items{items} renderItem{renderItem} /);};export default App;样式操作
class类名设值:必须写为className 类名和样式写在css文件里 必须接受一个字符串 style内联:不能像原生一样写成字符串必须写成对象
import React from react;import ./styles.css; // 这里引入你的 CSS 文件const MyComponent ({ className, style }) {return (div className{className} style{style}Hello, World!/div);};// 使用组件const App () {const customStyle {color: blue,fontSize: 20px,backgroundColor: lightgray,};return (MyComponentclassNamemy-custom-class // 在 CSS 文件中定义的类名style{customStyle} // 使用对象形式的内联样式/);};export default App;CSS Modules
CSS Modules 提供了局部作用域的 CSS避免类名冲突。
//styles.module.css
.myCustomClass { color: blue; font-size: 20px; padding: 10px; background-color: lightgray; }import styles from ./styles.module.css;
const MyComponent () { return div className{
styles.myCustomClass}
Hello, World!
/div;};生命周期
在 React 函数组件中没有传统的生命周期方法 ,React 通过 Hooks 提供了类似的功能允许你在不同的阶段执行副作用。
import React, { useEffect } from react;const MyComponent () {useEffect(() {// 组件挂载时执行return () {// 组件卸载时执行};}, []); // 空数组表示只在挂载和卸载时执行return divHello, World!/div;};useRef
用于获取真实dom和vue中ref一个道理 只不过变成了.current
import React, { useRef } from react;const MyComponent () {const inputRef useRef(null);const focusInput () {if (inputRef.current) {inputRef.current.focus();}};return (divinput ref{inputRef} typetext /button onClick{focusInput}Focus Input/button/div);};常用hook
useState
语法: const [state, setState] useState(initialState) initialState 是初始状态可以是任何类型数字、字符串、对象等。setState 是更新状态的函数。 这个不做举例了
useEffect
语法:useEffect(() { … },[dependencies]) dependencies 是一个数组包含 effect 依赖的值。当这些值发生变化时effect 会重新执行。如果传入空数组 []effect 只会在组件挂载和卸载时执行一次。 不做举例了
useContext
语法:const value useContext(MyContext) useContext 不接受第二个参数。它从最近的 MyContext.Provider 中获取当前上下文值
useReducer
用法: const [state, dispatch] useReducer(reducer, initialState); 第二个参数: initialState 是 reducer 的初始状态通常是一个对象或基本数据类型。
import React, { useReducer } from react;const initialState { count: 0 };function reducer(state, action) {switch (action.type) {case increment:return { count: state.count 1 };case decrement:return { count: state.count - 1 };default:throw new Error();}}const Counter () {const [state, dispatch] useReducer(reducer, initialState);return (divCount: {state.count}button onClick{() dispatch({ type: increment })}/buttonbutton onClick{() dispatch({ type: decrement })}-/button/div);};useMemo
用法:const memoizedValue useMemo(() computeExpensiveValue(a, b), [a, b]); dependencies 是一个数组当数组中的任意一个值改变时computeExpensiveValue 才会重新计算并返回新值 可以提高性能 记忆函数 也就是保存结果组件多次渲染直接取缓存结果就行
import React, { useMemo } from react;const ExpensiveCalculation ({ num }) {const result useMemo(() {// 进行复杂计算return num * 2; // 示例计算}, [num]); // 依赖于 numreturn divResult: {result}/div;};useCallback
用法: const memoizedCallback useCallback(() { }, [dependencies]); 第二个参数: dependencies 是一个数组当数组中的任意一个值改变时返回新的回调函数。 更上面一样 就是保存函数
import React, { useState, useCallback } from react;const Button React.memo(({ onClick }) {console.log(Button Rendered);return button onClick{onClick}Click Me/button;});const App () {const [count, setCount] useState(0);const handleClick useCallback(() {setCount(count 1);}, [count]); // 依赖于 countreturn (divButton onClick{handleClick} /pCount: {count}/p/div);};
高阶组件
高阶组件Higher-Order Component简称 HOC是 React 中一种用于复用组件逻辑的模式。它本质上是一个函数接受一个组件作为参数并返回一个新的组件。高阶组件可以用于许多场景例如状态管理、数据获取、权限控制等。
import React from react;// 原始组件const MyComponent ({ extraInfo }) (divp这是我的组件。/pp{extraInfo}/p/div);// 高阶组件const withExtraInfo (WrappedComponent) {return (props) {const extraInfo 附加信息这是来自高阶组件的内容;return WrappedComponent {...props} extraInfo{extraInfo} /;};};// 使用高阶组件const EnhancedComponent withExtraInfo(MyComponent);const App () (divEnhancedComponent //div);export default App;什么时候使用
组件是既包含了ui界面的复用也包含了逻辑的复用高阶组件只是复用操作逻辑运算类似于vue中mixin的用途当我们发现某个操作逻辑或者某个运算经常出现的时候我们可以提取为高阶组件
react性能问题和优化
Vue的因为是在get和set里触发更新 Vue在get部分有一个重要的操作-依赖收集 这样我们在更改了数据后只会更新用到了这个数据的地方做到最小的更新范围 React的更新是调用方法时触发的并没有依赖收集的过程所以他会更新整个组件树也就是会把子组件一起更新即使更新的数据和子组件没有任何关系 所以React最大的一个性能问题就是-React的某个组件的更新会连带着他的子组件一起更新。所以我们需要解决这个问题让子组件只做合理的更新
React的时间切片
Vue有依赖收集做到了最小的更新范围而React没有做这个事情。所以React要更新就会有很大的diff算法比对和计算工作 这大的更新量虚拟dom比对和计算会花很大时间这样可能会阻塞住浏览器的工作导致页面长时间白屏 React为了解决这个问题选择另一种策略-时间切片也就是先计算一部分更新然后让渡给渲染进程 然后再进行下一步更新我从使用者的角度 就不会出现长时间白屏了。
fiber
为了支持这种切片我们需要把更新化成一个个单元然后我们也必须有回复上一次计算进度的能力 所以react设计一种数据结构-fiber 每一个组件会被转化为一个fiber结构的对象组成一个个单元。Fiber让我们有了回复上次中断的计算进度的能力 类似于vue中的虚拟节点vnode, Both Fiber 和 vnode 都是对真实 DOM 的抽象旨在提高性能和效率。它们允许框架在内存中处理组件树而不是直接操作 DOM。
避免父组件数据导致子组件更新
React.memo子组件 让它缓存 我们特别注意父组件传入的方法对象数组这样的引用类型 用useCallback包裹传递给子组件的方法 state对象数组数据要用useMemo包裹起来
import React, { useState, useCallback, useMemo } from react;// 子组件const ChildComponent React.memo(({ handleClick, data }) {console.log(ChildComponent rendered);return (divbutton onClick{handleClick}Click Me/buttonul{data.map((item, index) (li key{index}{item}/li))}/ul/div);});// 父组件const ParentComponent () {const [count, setCount] useState(0);const [items, setItems] useState([Item 1, Item 2]);// 使用 useCallback 包裹传递给子组件的方法const handleClick useCallback(() {setCount(count 1);}, [count]);// 使用 useMemo 包裹传递给子组件的数组数据const memoizedItems useMemo(() {return items;}, [items]);return (divh1Count: {count}/h1ChildComponent handleClick{handleClick} data{memoizedItems} //div);};export default ParentComponent;如果对你有所帮助的话就点个关注吧会持续更新技术文章