7.获取DOM代码
根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff 。
组件 MyComponent 的子节点有一个文本输入框,用于用户输入,这时就必须获取真实的DOM节点,虚拟DOM是拿不到用户输入的数据的为了做到这一点,文本输入框必须有一个ref属性,然后this.ref.[refName]就会返回这个真实的DOM节点。
由于 this.refs.[refName]
属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
代码中,通过为组件指定 Click
事件的回调函数,确保了只有等到真实 DOM 发生 Click
事件之后,才会读取 this.refs.[refName]
属性。
1 | <div id="example"></div> |
关于constructor()函数可以看我的另一篇文章
关于为什么要用this可以看我的另一篇文章
React 组件支持很多事件,除了 Click
事件以外,还有 KeyDown
、Copy
、Scroll
等,完整的事件清单请查看官方文档。
8.this.state
状态改变渲染页面
上面代码是一个
LikeButton
组件,构造器函数定义 state 状态,这是一个对象,可以通过this.state属性读取,当用户点击组件时,状态改变,this.setState() 方法就修改状态值,每次修改以后,自动调用this.render方法,再次渲染组件。
由于 this.props
和 this.state
都用于描述组件的特性,可能会产生混淆。
一个简单的区分方法是,this.props
表示那些一旦定义,就不再改变的特性,而 this.state
是会随着用户互动而产生变化的特性。
class LikeButton extends React.Component {
// 构造器创建 state
constructor(props) {
super(props)
this.state = {liked: false} // p标签上的 方法
this.handleClick = this.handleClick.bind(this)
}
handleClick(event) {
// state 下的 liked 状态改变
this.setState({ liked: !this.state.liked });
}
render() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
}
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
9.表格
this.state
描述组件的状态,并通过用户交互进行变异,以及this.props
描述组件的属性,并且是稳定的和不可变的。
除此之外,value
表单组件的属性(如、
class Input extends React.Component {
constructor(props) {
super(props)
this.state = {value: 'Hello!'}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div>
);
}
}
ReactDOM.render(
<Input/>,
document.getElementById('example')
);
10.组件的生命周期
组件的生命周期分为三个状态:
Mounting: 一插入真实的DOM
Updating: 正在被重新渲染
Unmounting: 以移除真实 DOM
React为每一个状态都提供了两种处理函数,will
函数在进入状态之前调用,did
函数在进入状态之后调用,三种状态共计五种处理函数。
- componentWillMount() 组件挂载之前调用,render()之前调用
- componentDidMount() DOM渲染完成后调用,可以用于加载后台数据
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState) 组件更新时触发该方法,初始渲染不调用
- componentWillUnmount() 组件被销毁之前一般用于清理工作(定时器timer、网络请求、订阅事件)
此外,React 还提供两种特殊状态的处理函数。
1. componentWillReceiveProps(object nextProps) :已加载组件收到新的参数时调用
2. shouldComponentUpdate(object nextProps, object nextState) :组件判断是否重新渲染时调用
1 | class Hello extends React.Component { |
如果不使用bind()
而直接调用 setInterval 中定义的匿名函数,函数内部的 this 是指向 window 对象的。匿名函数内部显然需要 this 指向当前组件,才能读取state
属性/调用setState()
方法,所以使用bind()
为匿名函数绑定当前执行环境的 this,即当前组件。
为组件添加外部css样式时,类名应该写成className而不是class;添加内部样式时,应该是 style={{opacity: this.state.opacity}}{% end%} 而不是{% raw %} style="opacity:{this.state.opacity};"{% endraw %} 。
11.Ajax
如何从服务器或API提供程序获取组件的数据?的事件处理程序中使用ajax获取数据。componentDidMount
…当服务器响应到达时,使用this.setState()
以触发UI的重新呈现。
class UserGist extends React.Component {
constructor(props) {
super(props)
this.state = {
username: '',
lastGistUrl: ''
};
}
componentDidMount() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
}
render() {
return (
<div>
{this.state.username}'s last gist is
<a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
}
ReactDOM.render(
<UserGist source="https://api.github.com/users/lifei-2019/starred" />, //看最后看的代码段
document.getElementById('example')
);
- 本文作者: Raphael_Li
- 本文链接: https://lifei-2019.github.io/react-02/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!