state
state 顾名思义就是状态, 它只是用来控制这个组件本身自己的状态, 我们可以用 state 来完成对行为的控制, 数据的更新, 界面的渲染, 由于组件不能修改传入的 props, 所以需要记录自身的数据变化.
那么, 我们要如何修改 state 中的值呢?
setState 时 react 用来修改 state 状态中的值的方法
如何使用
- this.setState({
- key:value
- })
这样就行了.
props
react 中说的单向数据流值说的就是 props, 根据这一特点它还有一个作用: 组件之间的通信. props 本身是不可变的, 但是有一种情形它貌似可变, 即是将父组件的 state 作为子组件的 props, 当父组件的 state 改变, 子组件的 props 也跟着改变, 其实它仍旧遵循了这一定律: props 是不可更改的.
props 一定来源于默认属性或者通过父组件传递而来, 以下是这个写法:
- static propProps = {
- val:PropTypes.string.isRequired
- }
- static defaultProps = {
- val:0
- }
如果你觉得还是搞不清 state 和 props 的使用场景, 那么请记住一个简单的规则: 尽量少地用 state, 尽量多地用 props.
没有 state 的组件叫无状态组件 (stateless component), 设置了 state 的叫做有状态组件 (stateful component). 因为状态会带来管理的复杂性, 我们尽量多地写无状态组件, 尽量少地写有状态的组件. 这样会降低代码维护的难度, 也会在一定程度上增强组件的可复用性. 函数式组件就只有 props 没有 state, 而 react 也非常鼓励我们编写函数式组件.
以下给 props 和 state 做一个总结:
props 用于定义外部接口, state 用于记录内部状态
props 的赋值在于外部世界使用组件, state 的赋值在于组件内部
组件不应该改变 props 的值, 而 state 存在的目的就是让组件来修改的
组件的 state 相当于组件的记忆, 其存在的意义就是被修改, 每一次通过 setState 函数修改 state 就改变了组件的状态, 然后通过把渲染过程体现出来. 但是组件的 props 绝不应该被修改, 我们可以想象一个场景, 一个父组件将同一个 props 传给几个子组件, 若有一个子组件将 props 修改, 那么其他的组件就不一定能得到自己想到的值, 此时的情况将混乱不堪.
refs
某些情况下需要直接修改元素, 要修改的子代可以是 React 组件实例, 也可以是 DOM 元素. 这时就要用到 refs 来操作 DOM.
[注意] 如果可以通过声明式实现, 则尽量避免使用 refs.
ref
React 支持给任意组件添加特殊属性 ref ,ref 可以是一个字符串, 也可以是一个属性接受一个回调函数, 它在组件被加载或卸载时会立即执行.
[注意] 在组件 mount 之后再去获取 ref.componentWillMount 和第一次 render 时都获取不到, 在 componentDidMount 才能获取到.
新 ref
版本 16.3 之前, React 有两种提供 ref 的方式: 字符串和回调, 因为字符串的方式有些问题, 所以官方建议使用回调来使用 ref. 而现在引入的 createRef API, 据官方说是一种零缺点的使用 ref 的方式, 回调方式也可以让让路了.
- class MyComponent extends React.Component {
- constructor(props) {
- super(props);
- this.myRef = React.createRef();
- }
- render() {
- return <div ref={this.myRef} />;
- }
- }
然后使用 current 属性, 即可获得当前元素
this.myRef.current
[注意] 使用 styledComponents 样式化的元素暴露的接口是 innerRef, 而不是 ref
<Wrap innerRef={this.itemRef}>
ref 传递原理
当给 html 元素添加 ref 属性时, ref 回调接收了底层的 DOM 元素作为参数.
React 组件在加载时将 DOM 元素传入 ref 的回调函数, 在卸载时则会传入 null.ref 回调会在 componentDidMount 或 componentDidUpdate 这些生命周期回调之前执行.
- class CustomTextInput extends React.Component {
- constructor(props) {
- super(props);
- this.focus = this.focus.bind(this);
- }
- focus() {
- this.textInput.focus();
- }
- render() {
- return (
- <div>
- <input
- type="text"
- ref={(input) => { this.textInput = input; }} />
- <input
- type="button"
- value="Focus the text input"
- onClick={this.focus}
- />
- </div>
- );
- }
- }
更简短的写法如下:
ref={input => this.textInput = input}
类组件
当. ref 属性用于使用 class 声明的自定义组件时, ref 的回调接收的是已经加载的 React 实例.
- class AutoFocusTextInput extends React.Component {
- componentDidMount() {
- this.textInput.focusTextInput();
- }
- render() {
- return (
- <CustomTextInput
- ref={(input) => { this.textInput = input; }} />
- );
- }
- }
[注意] 这种方法仅对 class 声明的 CustomTextInput 有效
函数式组件
不能在函数式组件上使用 ref 属性, 因为它们没有实例.
对父组件暴露 DOM 节点
在子节点上暴露一个特殊的属性. 子节点将会获得一个函数属性, 并将其作为 ref 属性附加到 DOM 节点. 这允许父代通过中间件将 ref 回调给子代的 DOM 节点.
该方法适用于类组件和函数式组件:
- function CustomTextInput(props) {
- return (
- <div>
- <input ref={props.inputRef} />
- </div>
- );
- }
- class Parent extends React.Component {
- render() {
- return (
- <CustomTextInput
- inputRef={el => this.inputElement = el}
- />
- );
- }
- }
- 在上面的例子中, Parent 将它的 ref 回调作为一个特殊的 inputRef 传递给 CustomTextInput, 然后 CustomTextInput 通过 ref 属性将其传递给 <input>. 最终, Parent 中的 this.inputElement 将被设置为与 CustomTextInput 中的 < input > 元素相对应的 DOM 节点.
参考链接 : https://www.jianshu.com/p/2f6d81a15d81
https://www.jianshu.com/p/628d5514b145
来源: http://www.bubuko.com/infodetail-3184876.html