虚拟DOM
本质是Object类型的对象
虚拟DOM是React内部在用,最终会被react转化为真实DOM,呈现在页面上
jsx语法规则
定义时不用写引号
标签中混入JS表达式时用{}
样式名用className,其他属性例如onclick 用onClick
内联样式写法:style={{key:value}}。
只有一个根标签
标签必须闭合
标签首字母:a)小写字母开头,转换为HTML中同名元素。 b)大写字母开头,react渲染对应的组件。
函数式组件和类式组件
函数式组:
function MyComponent() {
return <h2>函数式组件</h2>
}
函数式组件中的this是undefined,因为babel编译后开起来严格模式
执行过程:React解析组件标签,找到MyComponent组件。调用该函数式组件,将虚拟DOM转为真实DOM,呈现在页面中。
类式组件:
class MyComponent extends React.Component {
render() {
return <h2>类式组件</h2>
}
}
render()是放在MyComponent的原型上,供实例使用。
render()中的this是MyComponent的实例对象 MyComponent 组件实例对象。也就是MyComponent组件实例对象
执行过程:React解析组件标签,找到MyComponent组件。发现是类式组件,随后new出该类的实例,通过该实例调用原型上的render方法,将render返回的虚拟DOM转为真实DOM,呈现在页面中。
组件实例三大属性(一) state
组件实例,也就是在类式组件中
- state是重要的组件属性,值为对象(可以包含多组key-value组合)
- 组件被称为“状态机”,通过更新组件的state,来更新对应页面的显示(重新渲染组件)
- 组件的状态里面存着数据,通过改变数据更新组件的状态来更新着页面的展示。
状态更新必须通过setState进行更新,且更新是一种合并,不是替换。
类式组件中自定义方法用:赋值语句+箭头函数的形式
name = () => {
}
这样使方法的this指向组件实例中的this。
组件实例三大属性(二) props
props可以接收传递给组件的数据(任何类型)
props是只读的
- 每个组件对象都有props属性
- 组件标签的属性保存在props中
从render中传入属性值后,打印Person实例对象,可以看见传入的值再props属性中
使用prop-type对组件标签属性进行限制,此时全局多了一个PropTypes对象
安装一个叫prop-types的第三方包
npm install prop-types
通过propTypes来对标签属性进行类型,必要性的限制,通过defaultProps对这个默认值进行设置。
通过标签属性从组件外向组件内传递变化的数据。使用静态属性,通过static把限制条件从类的外侧移动到类的里面。
//对标签属性进行类型、必要性的限制
static Person.propTypes = {
name:PropTypes.string.isRequired, //限制name必传,且为字符串
sex:PropTypes.string,//限制sex为字符串
age:PropTypes.number,//限制age为数值
speak:PropTypes.func,//限制speak为函数
}
//指定默认标签属性值
static Person.defaultProps = {
sex:'男',//sex默认值为男
age:18 //age默认值为18
}
类式组件中的构造器中,如果没有传props,直接打印this.props的值为undefined。因此需要在构造器中接收props并传递给supe,使能够通过this拿到props。
constructor(props){
//构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
// console.log(props);
super(props)
console.log('constructor',this.props);
}
函数式组件使用props
function Person (props){
const {name,age,sex} = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
组件实例三大属性(三) refs
组件类的标签可以定义refs 属性来标识,可以用来获取这个节点,以及这个节点中的所有属性和值
1.字符串形式的ref
<input ref="input1" type="text" />
用this.ref.input1可以获取这个标签(官网不推荐)
2.回调函数形式的ref
<input ref={c => this.input1 = c } type="text" />
通过ref的回调函数定义成class的绑定函数,实际开发中内联函数的形式写的比较多。
3.createRef的使用
myRef = React.createRef()
<input ref={this.myRef} type="text" />
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的
react中的事件处理
通过onXxx属性指定事件处理函数(注意大小写)
- React使用的是自定义(合成)事件, 而不是使用的原生DOM事件 ,为了更好的兼容性
- React中的事件是通过事件委托方式处理的(委托给组件最外层的元素),为了的高效
通过event.target得到发生事件的DOM元素对象 ,不要过度使用ref
myRef = React.createRef()
showData = (event)=>{
console.log(event.target); //整个节点“<input ... />”
alert(this.myRef.current.value);
}
render(){
return(
<div>
<input ref={this.myRef} onBlur={this.showDate} type="text" />
</div>
)
}
受控组件和非受控组件
https://blog.csdn.net/qq_41846861/article/details/86598797
在react中状态改变受setState控制的为受控组件,不受setState控制的非受控组件
组件生命周期
旧版生命周期
新版生命周期
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
- constructor()
- getDerivedStateFromProps
- render()
- componentDidMount()
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
- getDerivedStateFromProps
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate
- componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
DOM的Diffing算法
因此要设置唯一的key,一般可以用id