2022/6/16
定义React组件或者书写React相关代码为什么要导入React
- 前情: 我们在开发项目的时候,创建每一组件,组件的第一行都会引入React,然而发现并没有使用过它, 不引入React的时候会报React没有定义的错误
import React from 'react';
-
React的运行机制能够解释一切,react的运行大概分成了三个阶段:
- jsx(也就是javascript xml)对象转变成javascript对象
- javascript对象转变成虚拟DOM对象
- 虚拟DOM对象变成实际的DOM对象
-
在第一阶段其实主要用到了Babel。Babel主要的功能就是转码功能,将ES6转换成ES5。组件经过Babel转码之后可以看到React.createElement(....), 所以说明React是在转码之后使用的,我们在写代码的时候从表面上是看不出来React被使用了。
-
我们在React项目使用Babel的时候,主要用到了这三个:
-
babel-core
-
babel-preset-env
-
babel-plugin-transform-react-jsx
-
//并且通常都会创建一个.babelrc的文件,文件中内容基本都如下:
{
"presets": ["env"],
"plugins": [
["transform-react-jsx",
{
"prama": "React.createElement"
}
]
]
}
- 可以看到在使用babel-plugin-transform-react-jsx插件的时候,会需要调用React.createElement,这也就解释了为什么每个React组件页面都需要引入React的原因。
vue中keep-alive的作用
-
理解: keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 transition 相似,keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。
-
作用: 可以实现组件缓存,当组件切换时,主要用于保留组件状态或避免重新渲染
-
属性:
- include:字符串或正则表达式。只有匹配的组件会被缓存。
- exclude:字符串或正则表达式。任何匹配的组件都不会被缓存。
-
举例子: 有一个列表页面和一个详情页面,那么用户就会经常执行打开详情->返回列表->打开详情,这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用进行缓存,这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染。
调用setState之后发生了什么
- 首先setState的出现是因为,React并不会绑定视图和state,需要手动去更新视图,所以setState就出现了,它帮助我们更改数据的同时并且通知视图进行渲染。
- 第二个能力是性能优化,可以认为setState是异步的,React在setState之后,会经对state进行diff,判断是否有改变,然后去diff dom决定是否要更新UI。如果这一系列过程立刻发生在每一个setState之后,就可能会有性能问题。在短时间内频繁setState。React会将state的改变压入栈中,在合适的时机,批量更新state和视图,达到提高性能的效果。(简单理解为批量处理,或者延迟处理)
- 在代码中调用setState函数之后,React 会将传入的参数对象与组件当前的状态合并,然后触发所谓的调和过程(Reconciliation)。经过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个UI界面。在 React 得到元素树之后,React 会自动计算出新的树与老树的节点差异,然后根据差异对界面进行最小化重渲染。在差异计算算法中,React 能够相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是全部重新渲染。
react的受控组件和非受控组件
非受控组件
- 定义: 页面中所有输入类DOM的值,都是现用现取的
- 表单数据由DOM本身处理。即
不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用时通过ref从DOM获取表单值)
// 一个非受控组件的案例(表单元素中的值是当点击了按钮的时候才取到的)
// 创建组件
class Login extends React.Component {
handleSubmit = (event) => {
event.preventDefault() // 阻止表单提交
const {username, password} = this
alert(`您输入的用户名是 ${username.value},您输入的密码是:${password.value}`)
}
render() {
return (
<form action="https://www.baidu.com/" onSubmit={this.handleSubmit}>
用户名:<input ref={c => this.username = c} type="text" name="username" />
密码:<input ref={c => this.password = c} type="password" name="password" />
<button>登录</button>
</form>
)
}
}
// 渲染组件
ReactDOM.render(<Login />, document.getElementById('test'))
//原生知识点回顾:
form中的action是表单的提交地址
name是接收数据的字段名(来收集存储对应的数据)
受控组件
- 页面中输入类的DOM,随着输入的过程,通过
setState()更新state中的数据,需要用的时候在从状态state中取(有点类似Vue中的双向数据绑定),而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。
标签 input、textarea、select的值的改变通常是根据用户输入进行更新,所以受控组件是必须要有value的,value用来传入一个参数,结合onchang来控制这个参数输出。
每当value变化的时候,都会调用onchange的方法,事件处理器拿到新的值之后就会重新渲染视图,更新表单
备注:其中,文本框、下拉框都用的是event.target.value,而多选框用的是event.target.checked。 value和onchange两者在受控组件中缺一不可,一旦缺少其中一个就会报错
// 受控组件的案例
// 创建组件
class Login extends React.Component {
// 初始化状态
state = {
username: '',
password: ''
}
// 保存用户名到状态中
saveUsername = (event) => {
this.setState({username: event.target.value})
}
// 保存密码到状态中
savePassword = (event) => {
this.setState({password: event.target.value})
}
// 表单提交的回调
handleSubmit = (event) => {
event.preventDefault()
//一个数据怎么获取主要取决于这个数据存储的形态
const {username, password} = this.state
alert(`您输入的用户名是 ${username},您输入的密码是:${password}`)
}
render() {
return (
<form action="https://www.baidu.com/" onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveUsername} type="text" name="username" />
密码:<input onChange={this.savePassword} type="password" name="password" />
<button>登录</button>
</form>
)
}
}
// 渲染组件
ReactDOM.render(<Login />, document.getElementById('test'))
//注意
<input onChange={this.saveUsername} type="text" name="username" />
//这里是将saveUsername给onChange作为回调函数
<input onChange={this.saveUsername('username')} type="text" name="username" />
//而这里是将'username'作为一个参数传递给saveUsername()函数之后将函数执行结果作为回调函数给onChange,而这个函数如果没有返回值,传入的就是一个undefined

浙公网安备 33010602011771号