React

react.js

react.js引入后可以使用

  • 创建虚拟dom
    React.createElement(type,props,children)
    • type 虚拟dom类型,可写入'h1'等标签类型
    • props 属性,当前标签可用属性接可
    • children 子元素,也就是需要写入的内容
      创建多个子元素,用jsx实现更好,但顶层元素只能有一个
js 复制代码
    React.createElement("header",{id: "title"},
          React.createElement("h1", null, "hello"),
          React.createElement("p", null, "nihao")
     )

虚拟dom

对象类型,console.log如下

优点:按需渲染性能好

reactDom

react-dom.js引入后可以使用

  • dom渲染
    ReactDOM.render(element, container, callback)
    element: 要渲染的内容
    container: 渲染内容的容器
    callback: 渲染后的回调函数,非必传

jsx

=js+xml,在js中使用xml语法

需要引入babel,引入后在script标签上用type='text/babel'指定

js 复制代码
    ReactDOM.render(
        <header id='title' style="{{color: 'red',...}}">
          <h1>...<h1>
          ...
        </header>
     )

class->className

style接收一个对象(第一个{}是插值的,第二个才是对象的)

插值表达式

注意不要加''会被识别为字符串

可以叠加js表达式(会返回一个值的,正则等),但不能用if,while,for等语句

js 复制代码
let text = document.querySelector('#text')
ReactDOM.render(
<div> { text.value }</div>
)

在函数里用jsx最好在return时用()包裹一下

注释需要写在插值{/* .注释内容... */}里再注释

布尔值、空和未定义都会直接被忽略,不能输出对象(直接报错),数组可以(会用空白替换,分割)

  • 列表渲染
    jsx不能写循环语句,但可以把页面元素放到数组里,再让jsx渲染数组
    在项目中需要给重复的元素增加key属性

react工程

createReactApp命令

npm i create-react-app

create-react-app my-app // my-app是自定义的工程文件夹名

如果报错可以尝试npx create-react-app my-app,npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装。

  • eject 不可逆的抛出配置

项目目录

index.js入口文件,会引入App.vue

App.vue全局根组件

大写组件小写标签

函数式组件

函数名称=组件名

函数返回值=组件渲染内容,需要返回一个reactElement

js 复制代码
function App(props) {
   return (<h1>HELLO</h1>)
}

第0个参数是父组件传来的props

没有string ref,this和生命周期(无状态组件),除了hooks之外所以的变量都会在更新时重新创建(无法在外部定义变量)

尽量避免子函数 每次更新会创建新函数

类式组件

必须继承自React.Component

组件必须定义render方法,写明渲染内容

js 复制代码
import React from 'react'
class App extends React.Component { // 继承自React的组件类
  render() {
    return <h1>HELLO</h1>
  },
  constructor(props) {
    super(props) //继承父组件
  }
}
  • this里有:
    props:父组件传来的数据
    • state: 用于定义和保存数据变量
      可以直接定义,变成类的一个属性
js 复制代码
import React from "react";
// import {Component} from "react"也可以extends Component 
class App extends React.Component {
  state = {
    name: 'ssss',
    num: 1
  }
  render() {
    return <button onClick={}>HELLO</button>
  }
}

修改state:

js 复制代码
setState(
{
// 要修改的state部分
}, 
() => { 
// 状态更新完之后需要执行的回调函数,非必填
}
}

修改state并会重新渲染组件,直接修改this.state 组件不会重新渲染

react会对多次修改合并,只render一次

js 复制代码
setNum= () => { // 事件名称需要驼峰
    let {name,num} = this.state
    this.setState({num: ++num})
  }
  • constructor构造函数
    需要super继承父级
    要定义变量只能在constructor或原型上
    -事件
    没有this,需要用箭头函数

路由和store的包裹关系

index.js

js 复制代码
import store from './redux/index'
import {Provider} from 'react-redux'
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter><App /></BrowserRouter>
    </Provider>
  </React.StrictMode>
);

store包裹router

react API

组件间通信

  • 子组件-父组件
    把数据和数据更新的回调方法放在props里
js 复制代码
// 父组件
state = {
  openChlid: '1'
}
setOpen=(chlidName) => {
  // 需要绑定this,所以要用箭头函数定义成属性
  this.setSate({
    openChild: chlidName
  })
}
render() {
  return(<List isOpen={openChild === item.name}  date={datas[item]} />)
}
// 子组件
render() {
  let {setOpen} = this.props
  setOpen('1')
}

跨组件
context 不推荐直接在项目中使用

js 复制代码
// --------父组件
import {createContext} from "react";
let {Provider,Consumer} = createContext(defaultVaule) // 可以传默认值 
return (<Provider vaule={{data}}>
  <div><List Consumer={Consumer}/></div>
</Provider>)
// ---------子组件
let {Provider,Consumer} = this.props
return(<Consumer>
  { (props) => {return (<Son {...props} />)} }
</Consumer>)

createContext提供两个组件Provider和Consumer,提供参数的组件用Provider包裹要用到数据的子组件,用vaule属性传参
不结合第三方插件的话,Consumer需要自己做Props传下去
需要使用数据的组件要用Consumer标签包裹,并在箭头函数里返回,回调函数里会有props参数,就是传递的数据

生命周期

react16.3之前

  • 挂载
    constructor() → componentWillMount() → render() → componentDidMount()-
  • 更新阶段:组件因props或state变化而重新渲染
    componentWillReceiveProps(nextProps) (且只有父组件更新引起组件更新会触发)→ shouldComponentUpdate(nextProps, nextState) → componentWillUpdate(nextProps, nextState) → render() → getSnapshotBeforeUpdate() *(16.3之前没有)*→ componentDidUpdate(prepProps, prevState, prevHtml)
    shouldComponentUpdate() { 需要return一个boolean值表示是否更新,return false打断不更新视图}
    16.3之后提供静态方法替代componentWillReceiveProps,但不建议使用,但可以用于state和prop中的数值绑定
js 复制代码
    static getDerivedStateFromProps(props,state) {
        console.log('父组件引起当前组件更新的参数',props, state)
        state.val = props.data.val // 可以用于state和prop中的数值绑定
        return true; // 返回false也没用
    }
  • 卸载阶段:组件从DOM中移除
    componentWillUnmount()
  • 错误处理 16.3之后才有
    在父组件中写,捕获子组件生命周期的错误,不捕获事件中的错误
    static getDerivedStateFromError(error): 静态方法,error是true,方法里返回一个对象可以直接更新组件的state
    componentDidCatch(err, info):API,能拿到this, info能拿到具体的出错信息

受控组件

非受控组件:不需要同步value值的表单控件 用defaultVaule或defaultCheck属性

受控组件:通过onChange事件更新state里的数据的表单控件

PureComponent

和Component比在加载性能上更好,setState提供的是浅比较的shouldComponentUpdate,浅比较相同的不会触发render

state中的引用对象修改记得引用新地址,即使用新对象

children

js 复制代码
// 父组件
render() {
  return(
    <Alert>
      <p>children1</p>
      <p>children2</p>
    </Alert>
   )
}
// Alert子组件
render() {
let {children} = this.props
  return(
    <div>
      <p>...</p>
      {children}
    </div>
   )
}

需要自定义传参的用prop传组件或返回组件的回调函数

js 复制代码
// 父组件
class Btn extends PureComponent {
    render() {
        return(<button onClick={() => {this.props.hide();}}>CLOSE</button>)
    }
}
render() {
  return(
     <Child Child={Btn}}></Child>
     // 或
     <Child renderCb={() => {return <Btn {...this.props}/>}}></Child>
   )
}
// Alert子组件
hide=() => {
        ...
}
render() {
let {Child} = this.props
  return(
    <div>
      <p>...</p>
      <Child hide={() => {this.hide}}></Child>
      // 或
      { renderCb({hide: this.hide}) }
    </div>
   )
}

dangerouslySetInnerHTML

转字符串到html

js 复制代码
import { PureComponent } from "react";
const innerHtmlStr = `<section><h1>11111</h1><section/>`
export default class danger extends PureComponent {
    render() {
        return(<div
          dangerouslySetInnerHTML={{
            __html: innerHtmlStr
          }}
        >
        </div>)
    }
}

refs

在组件挂载、更新完成之后使用
String ref:老版本,不向下兼容

js 复制代码
import { PureComponent } from "react";
export default class danger extends PureComponent {
    render() {
        return(<div>
          <input
             ref="txt" 
          /> 
        </div>)
    }
    componentDidUpdate() {
      this.refs.txt // 对应的dom元素
    }
}

方二 createRef

js 复制代码
import { PureComponent, createRef } from "react";
export default class danger extends PureComponent {
    state = {
        txtRef:createRef()
    }
    render() {
        return(<div>
          <input
            ref={this.state.txtRef} 
          /> 
        </div>)
    }
    componentDidUpdate() {
      this.state.txtRef.current // 对应的dom元素
    }
}

hooks

只能在函数式组件或其他hook里用

只能在顶层使用=不能在if或for里用

use开头的都是钩子函数

react提供的:

useState

sate, setState\] = useState(initSate) useState返回的是一个数组,sate当前对应的状态,setState修改对应state的方法 返回的setState也是浅对比 对一个对象useState之后返回的setState是直接替换,而不是合并赋值 ```js // -------子组件 function Child(props) { // const {name, setName} = props; const {state, setState} = props; let {name, count} = state return(

name: {name}

{ // setName(e.target.value) setState({ ...state, // 对对象使用时是直接替换,需要把原有的加进来 name: e.target.value }) }} >

count: {count}

{ // setName(e.target.value) setState({ ...state, count: e.target.value }) }} >
) } // -------父组件 import { useState } from "react" function HookExp() { // const [name, setName] = useState('') const [state, setState] = useState({ name: '', count: 1 }) return(
) } ``` #### 自定义hook 用use开头,可以提炼重复的单一逻辑 ```js // 自定义hook function useToggle(init) { const [off, setOff] = useState(init); return [off, () => { setOff(!off) // 直接取反 }] } // 用的时候 const {show, changeShow} = useToggle(true); ``` #### effect 组件加载/更新之后需要的回调 useEffect(cb,\[监听对象1,监听对象2\]) // 第二个参数非必传 相当于类组件componentDidMount,componentDidUpdate,componentWillUnmount的时候会执行 ```js useEffect(() => { return () => { // 只在组件卸载前执行=componentWillUnmount } }, []) const mountVal = useRef(true) useEffect(() => { if(!mountVal.current) { // 只在组件更新之后执行=componentDidUpdate console.log('更新') } else { // 只在组件挂载时执行=componentDidMount console.log('挂载') mountVal.current = false } // 在组件挂载和更新都执行 }) ``` 第二个参数可以指定回调触发的监听对象,但必须是数组形式 ```js // 监听某个值的更新 useEffect(() => { // age改变之后要执行的动作 }, [name]) ``` #### useRef useRef(initRef) 可以获取到真实DOM 并记录组件更新前的值 ```js // 获取真实dom const divRef = useRef(null) useEffect(() => { console.log(divRef.current) }, []) // 获取组件更新前的变量值 const {name, setName} = props; const [count, setCount] = useState(1) const prevVal = useRef({ name, count }) useEffect(() => { console.log(prevVal.current) // 获取之前的值 prevVal.current = {name, count} // 不赋新值的话会一直是初始值 }, [prevVal]) return(
) ``` 函数式组件定义在hooks外的变量更新会重新创建,也就是回到初始值,变量需要定义在hooks里面,并且在获取之前的值的时候用useRef() #### useMemo 组件更新前定义值 useMemo→函数渲染→useEffect ```js const val = useMemo(()=> { return `${name}+${count}` },[name, count]) const mountVal = useRef(true) useEffect(() => { if(mountVal.current) { // 只在组件挂载时执行 console.log('挂载',val) // 已经可以获取到useMemo定义的值 mountVal.current = false } // 在组件挂载和更新都执行 }) ```

相关推荐
程序员笨鸟2 小时前
[特殊字符] React 高频 useEffect 导致页面崩溃的真实案例:从根因排查到彻底优化
前端·javascript·学习·react.js·面试·前端框架
普通网友2 小时前
框架适配:React/Vue 项目中如何高效使用 debugger 断点
javascript·vue.js·react.js
写代码的【黑咖啡】2 小时前
Python 中的控制流程:掌握程序的逻辑跳转
服务器·javascript·python
Highcharts.js2 小时前
从旧版到新版:Highcharts for React 迁移全攻略 + 开发者必知的 5 大坑
前端·react.js·前端框架·编辑器·highcharts
独角鲸网络安全实验室2 小时前
高危预警!React核心组件曝CVSS 9.8漏洞,数百万开发者面临远程代码执行风险
运维·前端·react.js·网络安全·企业安全·漏洞·cve-2025-11953
西瓜凉了半个夏~2 小时前
React专题:react,redux以及react-redux常见一些面试题
前端·javascript·react.js
独角鲸网络安全实验室2 小时前
高危预警!React CVE-2025-55182 突破 RSC 防护,未授权 RCE 威胁 39% 云应用
前端·react.js·网络安全·前端框架·漏洞·rce·cve-2025-55182
GISer_Jing2 小时前
前端开发:提示词驱动的全链路
前端·javascript·aigc
多看书少吃饭2 小时前
Electron 桌面应用打开录音功能导致页面蓝屏问题解决方案
javascript·electron·策略模式