react1-基本介绍

React

官网

用于构建用户界面(UI)的 JavaScript 库

创建 React 项目

  • create-react-app
  • 官方定义的脚手架,用于快速搭建项目结构
  • 目前 create-react-app 升级到 5.x 版本,要求 node.js 的版本至少为 14.x 以后的版本

创建项目

  • $ npx create-react-app
  • $ yarn create react-app

安装依赖包

  • react:核心包
  • react-dom:浏览器渲染 (react-native:原生渲染,了解)
  • react-scripts:封装了 webpack 各项任务的脚本

npm scripts

可以在命令行中使用 npm run 的任务:

  • start:开发任务
  • build:生产任务,打包构建生成打包后的代码
  • test:测试
  • eject:弹出(将封装好的 webpack 任务还原到项目本地,以便于在项目目录下找到 webpack 的配置文件并进行修改扩展)
    注意:执行 eject 弹出任务后,是不能撤销的

入口文件(Hello World)

  • src/index.js 文件(16.x、17.x的写法):
import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <h1>Hello React</h1>,
  document.getElementById('root')
)
  • 18.x 的写法:
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>Hello, world!</h1>);

JSX

  1. JavaScript 的语法扩展
  2. 建议在 React 中配合使用 JSX,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。
  3. 在 JSX 中嵌入 JS 表达式:
<div>Hello {
    
     'world' }</div>

注:使用 { expression } 来嵌入 JS 表达式内容,注意:在 {} 内的 HTML 表达式内容会被转义处理,以避免出现 XSS 攻击。

<div dangerouslySetInnerHTML={
    
    {
    
    __html: this.state.html}}></div>

组件

  1. 函数组件
function MyComponent(props) {
    
    
  return (
    <div>JSX 表示的 React 元素</div>
  )
}
  1. class 组件
class MyComponent extends React.Component {
    
    
  // constructor() {} // 可以省略
  render() {
    
    
    // this.props 获取组件接收到的属性
    return (
      <div>JSX 表示的 React 元素</div>
    )
  }
}

注意:

  • 组件名称使用帕斯卡命名规范(每个单词首字母都大写,JSX 中通过标签首字母是否大写来区分是 html 标签还是自定义的组件)
  • 使用单个根节点包裹布局结构
  • 在 class 组件中,必须实现 render() 方法

State 与 Props

  1. state 是组件内私有使用到的数据,state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容
  2. props 是组件接收到的属性数据,应该是只读的,绝不能修改组件中的 属性 数据
  3. 正确使用 state
  • 不能直接修改 state 的值,而是调用 setState() 方法更新状态数据。直接修改 state 数据,视图不会响应式渲染
  • state 的更新可能是异步的
  • state 的更新会被合并

prop-types:运行时类型检查

  1. 下载包
  • $ npm i prop-types
  • $ yarn add prop-types
import PropTypes from 'prop-types'

class MyComponent extends React.Component {
    
    
  static propTypes = {
    
    
    prop1: PropTypes.number, // prop1式数字
    prop2: PropTypes.array.isRequired, // prop2式数组并且是必填的
  }
}
  1. TypeScript 或 Flow:静态类型检查
  2. 属性默认值
class MyComponent extends React.Component {
    
    
  static defaultProps = {
    
    
    prop1: 1,
    prop2: 'abc',
    prop3: [],
  }
}

Ref

绑定DOM元素,能够在方法中调用到

import React, {
    
    Component} from 'react';
import Children1 from './ components/Children1'
class App extends Component {
    
    
    myRef=React.createRef()
    methods=()=>{
    
    
        console.log(this.myRef.current)
        // 指向div本身    
    }
    render() {
    
    
        return (
            <>
                <div ref={
    
    this.myRef} onClick={
    
    this.methods}>
                    hello react
                </div>
                <Children1/>
            </>
        );
    }
}

export default App;

注:调用 Ref 对象的 current 属性获取关联的数据

组件通信

  1. 父子组件
  • 父传子:利用 props 传递
  • 子传父:利用 props 来传递函数的引用。父组件中渲染子组件实例时,传递一个函数的引用作为属性值到子组件中,当子组件需要传递数据时,调用在属性中接收到的函数并传递参数即可。要注意函数中 this 指向的问题(可以调用 bind 修改 this 指向,或使用箭头函数定义)
  • 父组件
import React, {
    
    Component} from 'react';
import Children1 from './ components/Children1'
class App extends Component {
    
    
    state={
    
    
        person:{
    
    
            name:'jack',
            age: '20',
        }
    }
    render() {
    
    
        return (
            <>
                <div>
                    hello react
                </div>
                <Children1 info={
    
    this.state.person}/> // 在这里通过属性的方式传值给子组件
            </>
        );
    }
}

export default App;
  • 子组件
import React, {
    
    Component} from 'react';
import PropTypes from 'prop-types'
class Children1 extends Component {
    
    
    static propTypes={
    
    
        info:PropTypes.object.isRequired
    }
    show=()=>{
    
    
        console.log(this.props)
        // 控制台打印{info: {…}}
    }
    render() {
    
    
        return (
            <div>
                <div onClick={
    
    this.show()}>hello children</div>
                <div>{
    
    this.props.info.name}</div>
            </div>
        );
    }
}

export default Children1;
  1. 跨组件层级Context
  • Context 提供了一种在组件之间共享此类值的方式,不必再逐层级传播props
  • 封装context文件utils/with-context文件中写入
  • 利用 Context 可在全局范围内实现组件树中各组件间数据的共享,通常可以 Context 中共享的数据有如:用户登录的状态、地区偏好设置、UI主题设置、语言设置等
import {
    
    createContext} from 'react';
// 创建createContext对象
const TestContext=createContext()
// 解构要用到的组件
const {
    
    
    Provider, // 生产组件
    Consumer, // 消费组件
} = TestContext
export {
    
    
    Provider,
    Consumer,
    TestContext,
}
  • 父级组件引入Provider
import React, {
    
    Component} from 'react';
import Children1 from './ components/Children1'
import {
    
    Provider} from "./utils/with-context";

class App extends Component {
    
    
    state={
    
    
        person:{
    
    
            name:'jack',
            age: '20',
        }
    }
    myRef=React.createRef()
    methods=()=>{
    
    
        console.log(this.myRef.current)
    }
    render() {
    
    
        return (
            <Provider value={
    
    {
    
    
                person:this.state.person
            }}>
                <>
                    <div ref={
    
    this.myRef} onClick={
    
    this.methods}>
                        hello react
                    </div>
                    <Children1/>
                </>
            </Provider>
        );
    }
}

export default App;
  • 子级组件引入Consumer
import React, {
    
    Component} from 'react';
import {
    
    Consumer} from "../utils/with-context";

class Children1 extends Component {
    
    

    render() {
    
    
        return (
            <Consumer>
                {
    
    
                    value=>{
    
    
                        const {
    
    person} = value
                        return (
                            <div>
                                <div>hello children</div>
                                <div>{
    
    person.name}</div>
                            </div>
                        );
                    }
                }
            </Consumer>
        )
    }

}

export default Children1;

context API

  • React.createContext(defaultValue)会从最近的Prvider中读取当前的context值,如果没有匹配到,将调用默认defaultValue
  • Provider每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化
  • Consumer传递给该函数的 value 值等价于组件树上方离这个 context 最近的 Provider 提供的 value 值
  • class.contextType 这是类的静态属性,设置后,可以成员方法中使用 this.context 获取到最近保存在 Provider 组件 value 属性中的值
  • Context.displayName使用该字符串来确定 context 要显示的内容
import React, {
    
    Component} from 'react';
import {
    
    Consumer, TestContext} from "../utils/with-context";
class Children1 extends Component {
    
    
    handelContext=()=>{
    
    
        console.log(this.context) //{person: {…}}
    }
    render() {
    
    
        TestContext.displayName='rose'
        return (
            <Consumer>
                {
    
    
                    value=>{
    
    
                        const {
    
    person} = value
                        return (
                            <div>
                                <div onClick={
    
    this.handelContext}>hello children</div>
                                <div>{
    
    person.name}</div> // jack
                                <div>{
    
    TestContext.displayName}</div> // rose
                            </div>
                        );
                    }
                }
            </Consumer>
        )
    }

}
Children1.contextType=TestContext // 定义类的静态属性,这样类中就能访问context

export default Children1;

生命周期

  1. 组件从创建开始,到销毁结束,所经历的整个过程,就是生命周期
  2. 生命周期钩子:在正常的生命周期过程中,有机会执行到用户额外的代码逻辑
  3. 只在 class 组件中有生命周期钩子函数,函数组件中不存在这些生命周期钩子(函数组件中 this 为 undefined)

主要阶段

  1. 挂载阶段
    当组件实例被创建并插入 DOM 中时
  • constructor() 构造器,初始化,如:state初始化,方法中 this 指向的绑定
  • static getDerivedStateFromProps():生命周期的功能是将传入的props映射到state上面
  • render() 渲染
  • componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方
  1. 更新阶段
    当组件的 props 或 state 发生变化时会触发更新
  • static getDerivedStateFromProps():
  • shouldComponentUpdate():通常作为性能优化的方式存在。这个方法会返回 boolean 值,当返回 true 时,会继续向后执行流程,返回 false 时,中断当前阶段渲染。默认行为是 state 每次发生变化组件都会重新渲染
  • render():
  • componentDidUpdate() 会在更新后会被立即调用
  1. 卸载阶段(销毁)
  • componentWillUnmount() 销毁阶段常销毁的资源:打开的连接、启动的定时器、未完成的网络请求、订阅的监听等

猜你喜欢

转载自blog.csdn.net/weixin_64925940/article/details/125089172