React基础详解(一)

Hello World--在原生JS里面引入React

javascript 复制代码
<div id="root"></div>
//React 的核心库,与宿主环境无关
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
//依赖核心库,将核心的功能与页面相结合
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
//如果使用的JSX语法,还需要引入babel转义
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script>
    //创建一个p元素
    var span = React.createElement("span", {}, "一个p元素");
    //创建一个H1元素
    var h1 = React.createElement("h1", {
        title: "第一个React元素"
    }, "Hello", "World", span)
    ReactDOM.render(h1, document.getElementById("root"))
</script>
1、React.createElement

创建一个React元素,称作虚拟DOM,本质上是一个对象

1)参数1:元素类型,如果是字符串,本质上是一个对象

2)参数2:元素的属性,一个对象

3)后续参数:元素的子节点

2、JSX

JS的扩展语法,需要使用babel进行转义

2.1 什么是JSX

Facebook起草的JS扩展语法

本质是一个JS对象,会被babel编译,最终会被转换成React.createElement

每个JSX表达式,有且仅有一个根节点:React.Fragment

每个JSX元素必须结束(XML规范)

2.2 在JSX中嵌入表达式

将表达式作为内容的一部分:null和undefined不会显示;

将表达式作为元素属性,属性使用小驼峰命名法;

防止注入攻击:自动编码;使用dangerouslyInnerHTML进行插入文本节点

javascript 复制代码
import React from 'react'
import ReactDOM from 'react-dom'

const content = "<h1>测试测试</h1>"
const div = (
            <div dangerouslySetInnerHTML={{
                __html: content
            }}>
            </div>)

ReactDOM.render(div, document.getElementById("root"))
2.3 元素的不可变性

虽然JSX元素是一个对象,但是该对象中的所有属性不可更改

如果确实需要更改元素的属性,需要重新创建JSX元素

3、组件

组件:包含内容、样式和功能的UI单元

3.1创建一个组件

特别注意:组件的名称首字母必须是大写

3.1.1函数组件

返回一个React元素

3.1.2类组件

必须继承React.Component

必须提供render函数,用于渲染组件

javascript 复制代码
import React from 'react'

export default class MyClassComp extends React.Component{
    constructor(props){
        super(props) //this.props = props
    }



    //该方法必须返回React元素
    render() {
        return <h1>类组件的内容,数字:{this.props.number}</h1>    
    }
}
3.2组件的属性

对于函数组件,属性会作为一个对象的属性,传递给函数的参数

对于类组件,属性会作为一个对象的属性,传递给构造函数的参数

注意:组件的属性,应该使用小驼峰命名法

3.3组件无法改变自身的属性

之前学习的React元素,本质上,就是一个组件(内置组件)

React中的哲学,数据属于谁,谁才有权利改动

React中的数据,自顶而下流动

4、组件状态

组件状态:组件可以自行维护的数据

组件状态仅在类组件中有效

状态(state),本质上是类组件的一个属性,是一个对象

4.1状态初始化
4.2状态的变化

不能直接改变状态:因为React无法监控到状态发生了变化

必须使用this.setState({})改变状态

一旦调用了this.setState,会导致当前组件重新渲染

javascript 复制代码
handleClick = () => {
    this.setState({
        //参数prev表示当前的状态
        //该函数的返回结果,会混合(覆盖)掉之前的状态
        //该函数是异步执行
        n: this.state.n + 1
    }, () => {
        //状态完成改变之后触发,该回调运行在render之后
        //所有状态全部更新完成,并且重新渲染后执行
        console.log("state更新完成", this.state.n)
    })

    this.setState({
        n: this.state.n + 1
    })

    this.setState(cur => ({
        n: cur.n + 1
    }))
}
4.3组件中的数据

1、props:该数据是由组件的使用者传递的数据,所有权不属于组件自身,因此组件无法改变该数组(如果给自定义组件传递元素内容,则React会将元素内容作为children属性传递过去)

javascript 复制代码
import React from 'react'

export default function Comp(props) {
    console.log(props)
    return (
        <div className="comp">
            {props.children || <h1>默认值</h1>}
        </div>
    )
}

2、state:该数组是由组件自身创建的,所有权属于组件自身,因此组件有权改变该数据

5、事件

在React中,组件的事件,本质上就是一个属性;按照之前React对组件的约定,由于事件本质上是一个属性,因此也需要使用小驼峰命名法

注意:如果没有特殊处理,在事件处理函数中,this指向undefined

1、使用bind函数,绑定this

2、使用箭头函数

javascript 复制代码
handleClick = () => {
    this.setState({
        n: this.state.n + 1
    }, () => {
        //状态完成改变之后触发,该回调运行在render之后
        console.log(this.state.n)
    })
}

render() {
    console.log("render")
    return (
        <div>
            <h1>
                {this.state.n}
            </h1>
            <p>
                <button onClick={this.handleClick}>+</button>
            </p>
        </div>
    )
}
6、深入认识setState

setState ,它对状态的改变,可能是异步的

(异步:与同步相区别,由于JS是单线程的,执行顺序是从上到下的,同步就是没有阻塞的情况下从上到下执行,异步就是有阻塞的情况下,将阻塞的事件放进执行队列的微队列里面,等待宏队列执行完成后,再执行微队列里面的事件)

如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步

如果遇到某个事件中,需要同步调用多次,需要使用函数的方式得到最新状态

最佳实践:

1、把所有的setState当做是异步的

2、永远不要信任setState调用之后的状态

3、如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)

4、如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)

React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对setState进行改变,然后触发render)

相关推荐
腾讯TNTWeb前端团队6 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰3 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy4 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom5 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom5 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom5 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom5 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试