Hello World--在原生JS里面引入React
//React 的核心库,与宿主环境无关
//依赖核心库,将核心的功能与页面相结合
//如果使用的JSX语法,还需要引入babel转义
创建一个React元素,称作虚拟DOM,本质上是一个对象
1)参数1:元素类型,如果是字符串,本质上是一个对象
2)参数2:元素的属性,一个对象
3)后续参数:元素的子节点
JS的扩展语法,需要使用babel进行转义
Facebook起草的JS扩展语法
本质是一个JS对象,会被babel编译,最终会被转换成React.createElement
每个JSX表达式,有且仅有一个根节点:React.Fragment
每个JSX元素必须结束(XML规范)
将表达式作为内容的一部分:null和undefined不会显示;
将表达式作为元素属性,属性使用小驼峰命名法;
防止注入攻击:自动编码;使用dangerouslyInnerHTML进行插入文本节点
import React from 'react'
import ReactDOM from 'react-dom'
const content = "测试测试
"
const div = (
)
ReactDOM.render(div, document.getElementById("root"))
虽然JSX元素是一个对象,但是该对象中的所有属性不可更改
如果确实需要更改元素的属性,需要重新创建JSX元素
组件:包含内容、样式和功能的UI单元
特别注意:组件的名称首字母必须是大写
返回一个React元素
必须继承React.Component
必须提供render函数,用于渲染组件
import React from 'react'
export default class MyClassComp extends React.Component{
constructor(props){
super(props) //this.props = props
}
//该方法必须返回React元素
render() {
return 类组件的内容,数字:{this.props.number}
}
}
对于函数组件,属性会作为一个对象的属性,传递给函数的参数
对于类组件,属性会作为一个对象的属性,传递给构造函数的参数
注意:组件的属性,应该使用小驼峰命名法
之前学习的React元素,本质上,就是一个组件(内置组件)
React中的哲学,数据属于谁,谁才有权利改动
React中的数据,自顶而下流动
组件状态:组件可以自行维护的数据
组件状态仅在类组件中有效
状态(state),本质上是类组件的一个属性,是一个对象
不能直接改变状态:因为React无法监控到状态发生了变化
必须使用this.setState({})改变状态
一旦调用了this.setState,会导致当前组件重新渲染
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
}))
}
1、props:该数据是由组件的使用者传递的数据,所有权不属于组件自身,因此组件无法改变该数组(如果给自定义组件传递元素内容,则React会将元素内容作为children属性传递过去)
import React from 'react'
export default function Comp(props) {
console.log(props)
return (
{props.children || 默认值
}
)
}
2、state:该数组是由组件自身创建的,所有权属于组件自身,因此组件有权改变该数据
在React中,组件的事件,本质上就是一个属性;按照之前React对组件的约定,由于事件本质上是一个属性,因此也需要使用小驼峰命名法
注意:如果没有特殊处理,在事件处理函数中,this指向undefined
1、使用bind函数,绑定this
2、使用箭头函数
handleClick = () => {
this.setState({
n: this.state.n + 1
}, () => {
//状态完成改变之后触发,该回调运行在render之后
console.log(this.state.n)
})
}
render() {
console.log("render")
return (
{this.state.n}
)
}
setState ,它对状态的改变,可能是异步的
(异步:与同步相区别,由于JS是单线程的,执行顺序是从上到下的,同步就是没有阻塞的情况下从上到下执行,异步就是有阻塞的情况下,将阻塞的事件放进执行队列的微队列里面,等待宏队列执行完成后,再执行微队列里面的事件)
如果改变状态的代码处于某个HTML元素的事件中,则其是异步的,否则是同步
如果遇到某个事件中,需要同步调用多次,需要使用函数的方式得到最新状态
最佳实践:
1、把所有的setState当做是异步的
2、永远不要信任setState调用之后的状态
3、如果要使用改变之后的状态,需要使用回调函数(setState的第二个参数)
4、如果新的状态要根据之前的状态进行运算,使用函数的方式改变状态(setState的第一个函数)
React会对异步的setState进行优化,将多次setState进行合并(将多次状态改变完成后,再统一对setState进行改变,然后触发render)