React(二)——dom、组件间通信、useEffect 目录一、表单受控绑定二、React中获取DOM三、组件间通信1.父传子特殊的prop——children2.子传父3.兄弟间组件通信1儿子A给父通信然后父再把拿到的数据传给儿子B2Context机制跨层级组件通信从上到下四、useEffect1.基础2.不同依赖项3.useEffect清除副作用五、自定义Hook实现一、表单受控绑定使用React组件的状态useState控制表单的状态就是你往input里输入内容然后state用onChange事件监听到输入框内容变化于是用setName更改name属性也就是这个变量值变了然后数值驱动试图input框里的内容跟着显示出来。虽然输入框显示键盘输入的内容是浏览器的默认行为但是这个默认行为下js并不知道你写了什么除非document.xx去获取。但是这种表单受控绑定的情况下react就知道你写了什么并且由他给你展示在页面上展示动作是浏览器完成的展示什么内容是react决定的import { useState } from react; function Son() { const [name,setName]useState() const setName1(value){ setName(value) } const nameChange(e){ console.log(e.target.value) setName1(e.target.value) } return ( div input onChange{ nameChange } value{name}/input /div ); } export default Son;二、React中获取DOM目前基本都是要数据驱动视图不建议直接去操作dom但是某些情况需要我们操作dom需要使用useRef钩子函数使用useRef创建Ref对象并与JSX绑定ref.current获取dom值import { useState } from react; import { useRef } from react; function Son1() { //获取ref对象初始值为null并把这个对象绑定到dom身上去 const inputRefuseRef(null) //然后这个对象.current获取dom console.log(inputRef.current) return ( div input ref{inputRef} value{11}/input /div ); } export default Son1;不过需要注意第二步在dom渲染完毕的时候才能用三、组件间通信1.父传子依旧是标签给子传子用props接收父import { useState } from react; import Son1 from ./components/Son1 function App() { return ( div Son1 name{hh} / /div ); } export default App;子props接收来的数据只读import { useState } from react; function Son1(props) { console.log(props,99) return ( div11/div ); } export default Son1;props是个对象可以传递数字、字符串、布尔、数组、对象、函数、JSX特殊的prop——children把内容直接嵌套在子组件标签里然后在子组件的pros.children里去找Son1 span111 /span /Son12.子传父依旧是子调用父的方法父import { useState } from react; import Son1 from ./components/Son1 const fn_f(x){ console.log(x,888) } function App() { return ( div Son1 fn_f{fn_f}/Son1 /div ); } export default App;子import { useState } from react; import { useRef } from react; function Son1(props) { console.log(props,99) props.fn_f(hhh) return ( div 111 /div ); } export default Son1;注意useState必须写在function 组件名() {}的函数体内部。3.兄弟间组件通信1儿子A给父通信然后父再把拿到的数据传给儿子B比较简单就不再放代码了2Context机制跨层级组件通信从上到下使用createContext方法创建一个上下文对象Ctx在顶层组件用Ctx.provider组件提供数据底层组件通过useContext钩子函数获取数据顶级组件import { useState } from react; import Son1 from ./components/Son1 import Son2 from ./components/Son2 import { createContext } from react; const msgHello React!; export const CtxcreateContext() function App() { return ( div Son1 fn_f{fn_f}/Son1 Ctx.Provider value{msg} Son2/Son2 /Ctx.Provider /div ); } export default App;底层组件import { useContext, useState } from react; import { useRef } from react; import { Ctx } from ../App; function Son2(props) { const btn(){ // console.log(props,99) } const msg useContext(Ctx); console.log(msg,99) return ( div input onClick{btn}/input /div ); } export default Son2;我是在两个文件里写的所以Ctx还需要导出导入一下不过我感觉特别不好我都导出了还要你Context干嘛不过export导出的变量组件不能监听变化以及自动更新而context可以四、useEffect1.基础useEffect是一个React的React Hook函数用于在组件中创建不是由事件引起而是由渲染本身引起的操作比如发送AJAX请求、更改DOM就像mounted干的事一样用户没有任何操作但是渲染完了就自动去发请求userEffect((){},[])第一个参数是一个箭头函数也叫副作用函数放要执行的操作第二个参数是数组可选参在数组里放依赖项不同的依赖项会影响第一个函数参数的执行空数组的时候副作用函数只在渲染完毕之后执行一次。2.不同依赖项第一种是这个参数压根不传组件更新指的是组件函数重新渲染了一次比如state变化、props变化、父组件重新渲染了第三种比如下面这种只有count和name变化之后才会有hh输出userEffect((){ console.log(hh) },[conut,name])3.useEffect清除副作用就像定时器在vue里要在组件卸载的时机去清理一样语法userEffect((){ //副作用代码订阅、定时器、事件监听等 return(){ //清除副作用逻辑 } },[])所以这个userEffect类似mounted但又不仅仅是mounted还有点监听器的作用里面的return类似unmounted五、自定义Hook实现自定义Hook是以use打头的函数通过自定义Hook函数可以用来实现逻辑的封装和复用就是用use打头命名的一个function最后把需要的东西return出去供组件或其他Hook函数使用。ReactHooks使用规则这里不只自定义的还有useState、useEffect、useContext、useRef、useReducer、useCallback、useMemo等等只能在组件或其他Hook函数使用只能在组件的顶层调用不能嵌套在if、for、其他函数中React靠调用次序来记住Hooks而不是靠名字如果放if/for/其他函数里的话就会搞混顺序