函数组件
# 函数组件
- 什么叫函数组件
- 声明函数的时候,用箭头函数去写
- 基础知识
1.首字母大写的函数就是函数组件,函数组件会返回一个jsx元素,把函数名当作标签渲染
2.函数组件可以传参:props传值,属性传参
3.props是个对象,里面集合了所有传递的参数
4.当我们传递的属性为多个时,使用拓展运算符{...对象名}
5.props传值从上到下
6.子组件是不可以修改 props 属性值的,但是,子组件可以调用父组件传过来的修改属性的方法,从而间接性的达到我们的需求。
- 函数上下文对象(在项目中没有特殊情况不建议使用上下文)
注意:
* 函数组件使用上下文:使用hooks 钩子函数
* 函数不能使用静态属性static 和 this
函数中的this是undefined
# 常用的 event 对象属性
- target:被触发的元素[不固定]
- currentTarget:事件被绑定元素[固定]
- preventDefault:组织默认事件
- stopPropagation:禁止冒泡
- persist:强制保留属性值
异步函数中属性值会丢失,就需要用到 persist 方法来强制保留属性值
react事件是合成的,事件对象也是合成的,合成的事件对象在异步中会丢失属性的值
- 解决了什么问题
解决了多层嵌套数据共享的问题,实际上就是解决了 props 显示的层层传递的不可控制问题
Portals
Portal 将子节点渲染到存在于父组件以外的 DOM 节点
渲染出一个和DOM同级的组件
1.先创建一个与root统计的元素 <div id="root"></div> <div id="modal-root"></div> 2. const appRoot = document.getElementById("root"); const modalRoot = document.getElementById("modal-root"); 3. constructor(props) { super(props); this.el = document.createElement('div'); } 4.render() { return ReactDOM.createPortal( this.props.children, this.el ); }
react优化
react优化 (浅比较):减少不必要的渲染
1.类组件优化可以使用PureComponent
```js class Child2 extends React.PureComponent ```;
2.函数组件 类组件 React.memo(组件) 是一个高阶组件
``` js let MemoChild = React.memo(Child); ```;
3.函数组件 如果子组件依赖父组件的数据可以使用useMemo
```js let data = useMemo(()=>{ return {count} },[count]) ```
4.函数组件 如果子组件依赖父组件的事件 使用useCallback
```js let add = useCallback(()=>{
setCount(count=>count+1)
},[count])
```
Hooks(函数组件使用)
只在顶层调⽤ Hooks,函数组件调用hooks
1. Hooks 的调⽤尽量只在顶层作⽤域进⾏调⽤ 不要在循环,条件或者是嵌套函数中调⽤ Hook,否则可能会⽆法确保每次组件渲染时都以相同的顺序调⽤ Hook
2. 只在函数组件调⽤ Hooks
React Hooks ⽬前只⽀持函数组件,所以⼤家别在 class 组件或 者普通的函数⾥⾯调⽤ Hook 钩⼦函数 React Hooks 的应⽤场景如下
1. 函数组件
2. ⾃定义 hooks
1.useState
1.基本使用 const [state, setState] = useState(2); state = 0 function setState(state){} state:第一个参数是要设置的状态的值 setState:第二个参数是用来更新状态的方法 useState的参数表示第一个参数的初始值 const [state,setState] = useState(()=>{return {name:"lili"}}) 2.函数式更新 保证每次拿到的状态都是上一次的状态 function add(){ settimeout(()=>{ state=>state+1 },1000) }
2.useContext:使用上下文多层传值
let 自定义 = useContext(上下文对象);
useContext 用来放置上下文 相当于class的 static contextType = 上下文对象 上下文的默认值只有在没有provider包裹的情况下才会生效
createContext的第一个参数代表上下文的默认值
React DevTools 使用该字符串来确定
context 要显示的内容。
3.useEffect
useEffect(() => {
document.title = `我点击了${number}次`;
}); 副作用,dom操作 定时器
* 1.useEffect 里的函数会在组件挂载完成后或组件更新后进行调用
* 2.useEffect 返回一个清理函数 当组件卸载时,进行清理
第一个参数是回调函数
第二个参数是数组
空数组:挂载
非空数组:监听数组中的数据
不加依赖 :useEffect 每次渲染都会执行
4.useRef
返回一个不可变的对象
createRef 和 useRef的区别 ref是个字符串, 通过refs拿到dom
1.createRef:写在class组件上
useRef:写在函数组件上
2.createRef:每次返回新对象
useRef:每次返回老对象
5.useReducer:useState的替代方案
* state:就是我们要操作的数据, * dispatch派发事件的方法,useReducer要通过dispatch派发事件
* reducer:是一个函数,负责修改state * initialstate:是一个初始化的数据
* action:dispatch派发过来的动作(事件) dispatch里传过来的对象 可以根据type属性判断传递过来的动作是什么
* useReducer有三个参数,reducer函数(操作state),initialstate初始化数据, 如果需要第三个参数会把第三个参数的返回值作为reducer里面state的初始值
const [state, dispatch] = useReducer(reducer, initialArg, init); function reducer(state, action) { switch (action.type) {
case "add":
return { ...state, num: state.num + action.payload };
case "reduce":
return { ...state, num: state.num - 1 };
default:
return state;
} }
function App() {
const [state, dispatch] = useReducer(reducer, initialstate);
return (
<>
<span>{state.number}</span>
{/* 派发了一个Add事件到reducer,type表示事件类型
dispatch里面派发的东西我们叫做action动作,动作会派发到reducer
通过事件类型不同对state进行修改
payload:载荷
*/}
<button onClick={() => dispatch({ type: "Add", payload: 5 })}>
点击加1
</button>
<button onClick={() => dispatch({ type: "Acc" })}>点击加1</button>
</>
); }
6.useMemo
useMemo(callback,[deps])
第一个参数时回调函数,用来返回定义的状态
第二个参数 是一个数组,表示依赖项
空:挂载
值:监听数组的值
不给值:每次渲染都会执行
7.useCallback
第一个参数是回调函数,放置子组件依赖的函数减少更新
第二个参数是一个数组,表示依赖项,用法和useEffect的依赖项完全相同
useCallback(callback,[deps]) 空:只在渲染的时候执行一次 值:会在数组每次改变时执行 不给值:每次渲染都会执行
8.useImperativeHandle:使用命令时代码
* 第一个参数是传进来的ref Pref
* 第二个参数是 回调函数
useImperativeHandle(Pref,()=>{ return{} })
* 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。
useImperativeHandle 应当与 forwardRef 一起使用
9.useLayoutEffect
布局结束,useLayoutEffect同步进行dom操作
useLayoutEffect(() => { document.getElementById("mydiv").style.backgroundColor = "pink"; });
10.自定义Hooks
use开头的函数,并且使用其他hooks
## 使用 hooks 实现异步请求
import React, { Fragment, useState, useEffect } from "react";
import axios from "axios";
function App1() {
const [data, setData] = useState({ hits: [] });
const [query, setQuery] = useState("redux");
const [url, setUrl] = useState(
"https://hn.algolia.com/api/v1/search?query=redux"
);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
const result = await axios(url);
setData(result.data);
setIsLoading(false);
};
fetchData();
}, [url]);
return (
<Fragment>
<input
type="text"
value={query}
onChange={event => setQuery(event.target.value)}
/>
<button
type="button"
onClick={() =>
setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`)
}
>
Search
</button>
{isLoading ? (
<div>Loading ...</div>
) : (
<ul>
{data.hits.map(item => (
<li key={item.objectID}>
<a href={item.url}>{item.title}</a>
</li>
))}
</ul>
)}
</Fragment>
);
}滞留
export default App1;
浙公网安备 33010602011771号