什么是受控组件与非受控组件?
在了解这两个概念之前,你需要知道 JSX 是什么。
JSX
JSX 是 JavaScript 的语法扩展,它可以让我们在 JS 中编写类似 HTML 的代码。
看起来像这样:
const element = <div>hello, world</div>我们可以给 element 赋一个 div,看起来很奇怪,但这就是 JSX 语法。可以将 JS 和 HTML 写在一起。
不过,需要注意的是这里的 div 并不是原生 DOM。
写在 HTML 文档中的 HTML 标签是原生 DOM,而写在 JSX 中的 HTML 标签是 JSX 元素。
JSX 元素在项目构建的时候会被 babel 转换。
上面定义的 element 在转换之前是这样的:
<div>hello, world</div>经过 babel 转换后是这样的:
import { jsx as _jsx } from 'react/jsx-runtime'
/*#__PURE__*/ _jsx('div', {
children: 'hello, world'
})babel 将 JSX 元素转换成了一个 React 元素的创建操作,函数 _jsx 创建了一个与真实 DOM 结构对应的 React 元素,
这个根据真实 DOM 结构抽象出来的对象,即我们常说的虚拟 DOM。结构是这样的:
{
$$typeof: Symbol(react.element),
key: null,
props: {
children: 'hello, world'
},
ref: null,
type: 'div'
}element 虚拟 DOM 的标签类型是 div,子元素是文本元素 'hello, world',其描述了真实 DOM 的结构。
虚拟
DOM转为真实DOM是通过react-dom库实现的。
受控与非受控
在 React 中,组件的状态可分为:受控和非受控。
受控和非受控的区别在于组件的状态是由谁来控制的。
简单来说:
组件状态由外部控制的就是受控组件,由内部控制的就是非受控组件。
在 React 里,如果一个组件的状态是由 props 控制的,那么这个组件就是受控组件。
如果这个组件的状态是由内部 state 控制的,那么这个组件就是非受控组件。
在 React 中,组件分为:
- 内置浏览器组件:比如
div、input、form等。 - 自定义组件:开发者自己实现的函数组件或类组件。
注意 React 的内置浏览器组件并不是原生 DOM,它们实际上是 React 元素。在 JSX 部分我们已经讲过了。
下面我们看一个受控浏览器组件的例子:
组件 <input> 的状态 value 完全由 onChange 事件控制。
function ControlledInput() {
const [inputValue, setInputValue] = useState('')
const handleInputChange = event => {
setInputValue(event.target.value)
}
return <input type="text" value={inputValue} onChange={handleInputChange} />
}再来看一个非受控浏览器组件的例子:
组件 <input> 的状态由组件自身管理,组件的数据更新不需要外部控制,我们通过 ref 获取它的值。
function UncontrolledInput() {
const inputRef = useRef(null)
const handleButtonClick = () => {
console.log(inputRef.current.value)
}
return (
<div>
<input type="text" ref={inputRef} />
<button onClick={handleButtonClick}>打印 input 值</button>
</div>
)
}