Reactjs入门
阮一峰网络日志:http://www.ruanyifeng.com/blog/2015/03/react.html
React学习文档:http://reactjs.cn/react/docs/getting-started.html
1、jsx
-- 在javascript代码里写着xml格式的代码叫做jsx
-- javascript语法扩展,react用来做简单的句法转换
-- jsx能定义简介且包含属性的树状结构语法
-- react jsx代码文件可以写在单独的文件里
2、props与state
props属性
-- 组件的属性可以通过this.props对象上获取, 且是一一对应关系
-- 由于class 和for是js的保留字,故添加组件属性时需要注意,属性名分别为写className、htmlFor
-- this.props.children表示组件上的所有子节点,其值有三种情况:
没有子节点,为undefined;
一个子节点,数据类型为object类型;
多个子节点,数据类型为array类型
-- React.Children方法来处理this.props.children,使用React.Children.map()遍历子节点,而不用担心子节点是undefined还是object类型
-- PropsType用于验证组件实例的属性是否符合要求
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired,
},
render: function() {
return <h1> {this.props.title} </h1>;
}
});
state
组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI. 查看demo8: https://github.com/ruanyf/react-demos/blob/master/demo08/index.html
varLikeButton
=React
.createClass({
getInitialState
:function()
{
return
{
liked
:false};
},
handleClick
:function(
event
){
this
.setState({liked
:!
this
.state
.liked
});
},
render
:function()
{
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')
);
上面代码是一个 LikeButton
组件,它的 getInitialState
方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state
属性读取。当用户点击组件,导致状态变化,this.setState
方法就修改状态值,每次修改以后,自动调用 this.render
方法,再次渲染组件
props与state
由于 this.props
和 this.state
都用于描述组件的特性,可能会产生混淆。一个简单的区分方法是,this.props
表示那些一旦定义,就不再改变的特性,而 this.state
是会随着用户互动而产生变化的特性.
--getDefaultProps用于定义属性,不可变化
--getInitialState用于定义初始状态,可变化
--用户在表单填写信息,属于用户跟组件的互动,不能用this.props获取
3、组件定义使用规则
组件并不是真实的dom节点,而是存在于内存之中的一种真实的数据结构,只有插入文档之后才会变成真实的dom。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff.(值à状态à页面):可以极大的提高网页性能
-- React.createClass()方法用于生成组件类
-- 所有组件类必须有自己的render()方法,用于输出组件
-- 所有组件类首字母必须大写,否则会报错
-- 组件类只能包含一个顶层标签,否则也会报错
-- React组件支持的事件有onClick、onKeyDown、onCopy、onCut、onPaste、onScroll、onChange等,更多事件官方文档:https://facebook.github.io/react/docs/events.html#supported-events
4、ref属性
组件上获取真实的DOM节点,通过ref获取:
varMyComponent
=React
.createClass({
handleClick
:function()
{
this
.refs
.myTextInput
.focus();
},
render
:function()
{
return
(
<
div
>
<
input type
="text"ref
="myTextInput"/>
<
input type
="button"value
="Focus the text input"onClick
={this
.handleClick
}/>
</
div
>
);
}
});
ReactDOM
.render(
<
MyComponent
/>,
document
.getElementById('example')
);
必须等到虚拟DOM插入到文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click
事件的回调函数,确保了只有等到真实 DOM 发生 Click
事件之后,才会读取 this.refs.[refName]
属性。
5、表单
varInput
=React
.createClass({
getInitialState
:function()
{
return
{
value
:'Hello!'};
},
handleChange
:function(
event
){
this
.setState({value
:event
.target
.value
});
},
render
:function
()
{
var
value
=this
.state
.value
;
return
(
<
div
>
<
input type
="text"value
={value
}onChange
={this
.handleChange
}/>
<
p
>{value
}</p
>
</
div
>
);
}
});
ReactDOM
.render(<Input
/>,document
.body
);
上面代码中,文本输入框的值,不能用 this.props.value
读取,而要定义一个 onChange
事件的回调函数,通过 event.target.value
读取用户输入的值。textarea
元素、select
元素、radio
元素都属于这种情况,更多参与官方文档:
6、组件的生命周期
组件的生命周期分为三种状态:
Mounting:已插入真实 DOM -- componentDidMount
Updating:正在被重新渲染 -- componentWillUpdate
Unmounting:已移出真实 DOM
React 为每个状态都提供了两种处理函数,will
函数在进入状态之前调用,did
函数在进入状态之后调用,三种状态共计五种处理函数
- componentWillMount()
- componentDidMount()
- componentWillUpdate(object nextProps, object nextState)
- componentDidUpdate(object prevProps, object prevState)
- componentWillUnmount()
此外,React 还提供两种特殊状态的处理函数。
componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用
7、ajax
组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount
方法设置 Ajax 请求,等到请求成功,再用 this.setState
方法重新渲染 UI
varUserGist
=React
.createClass({
getInitialState
:function()
{
return
{
username
:'',
lastGistUrl
:''
};
},
componentDidMount
:function()
{
$
.get(this
.props
.source
,function(
result
){
var
lastGist
=result
[0];
if
(
this
.isMounted()){
this
.setState({
username
:lastGist
.owner
.login
,
lastGistUrl
:lastGist
.html_url
});
}
}.bind(
this
));
},
render
:function()
{
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/octocat/gists"/>,
document
.body
);
上面代码使用 jQuery 完成 Ajax 请求,这是为了便于说明。React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。我们甚至可以把一个Promise对象传入组件
ReactDOM
.render(
<
RepoList
promise
={$
.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')}
/>,
document
.body
);
上面代码从Github的API抓取数据,然后将Promise对象作为属性,传给RepoList
组件.
如果Promise对象正在抓取数据(pending状态),组件显示"正在加载";如果Promise对象报错(rejected状态),组件显示报错信息;如果Promise对象抓取数据成功(fulfilled状态),组件显示获取的数据。
varRepoList
=React
.createClass({
getInitialState
:function()
{
return
{
loading
:true,
error
:null,
data
:null};
},
componentDidMount()
{
this
.props
.promise
.then(
value
=>this
.setState({loading
:false,
data
:value
}),
error
=>this
.setState({loading
:false,
error
:error
}));
},
render
:function()
{
if
(
this
.state
.loading
){
return
<
span
>Loading
...</span
>;
}
else
if
(
this
.state
.error
!==null)
{
return
<
span
>Error
:{
this
.state
.error
.message
}</span
>;
}
else
{
var
repos
=this
.state
.data
.items
;
var
repoList
=repos
.map(function(
repo
){
return
(
<
li
>
<
a href
={repo
.html_url
}>{repo
.name
}</a
>({
repo
.stargazers_count
}stars
)<
br
/>{
repo
.description
}
</
li
>
);
});
return
(
<
main
>
<
h1
>Most Popular JavaScript Projects
inGithub
</h1
>
<
ol
>{repoList
}</ol
>
</
main
>
);
}
}
});
8、采用react+node实现同构及组件化
-- React.js相当于MVC框架的视图层
-- isomorphic (同构) : 同时在客户端和服务器端渲染页面
-- 同构js通常是同构node.js和io.js实现
-- react.js就是一种支持同构的框架