带状态的组件
除了可以通过this.props访问输入数据之外,组件还可以通过this.state来维持他的内部状态数据。当一个组件的状态数据改变时,组件将重新调用render()方法来重绘。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
// JSX code
var
Timer = React.createClass({
getInitialState:
function
() {
return
{secondsElapsed: 0};
},
tick:
function
() {
this
.setState({secondsElapsed:
this
.state.secondsElapsed + 1});
},
componentDidMount:
function
() {
this
.interval = setInterval(
this
.tick, 1000);
},
componentWillUnmount:
function
() {
clearInterval(
this
.interval);
},
render:
function
() {
return
(
<div>Seconds Elapsed: {
this
.state.secondsElapsed}</div>
);
}
});
React.render(<Timer />, mountNode);
// compiled javascript code
var
Timer = React.createClass({displayName:
"Timer"
,
getInitialState:
function
() {
return
{secondsElapsed: 0};
},
tick:
function
() {
this
.setState({secondsElapsed:
this
.state.secondsElapsed + 1});
},
componentDidMount:
function
() {
this
.interval = setInterval(
this
.tick, 1000);
},
componentWillUnmount:
function
() {
clearInterval(
this
.interval);
},
render:
function
() {
return
(
React.createElement(
"div"
,
null
,
"Seconds Elapsed: "
,
this
.state.secondsElapsed)
);
}
});
React.render(React.createElement(Timer,
null
), mountNode);
|
React应用
结合使用属性(props)和状态(state),可以构建一个基础的代办事项应用。这个例子中使用状态来跟踪事项列表和用户输入的新事项名称,即使事件处理程序看起来是内联的,他们仍将会通过代理被收集和实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// JSX code
var
TodoList = React.createClass({
render:
function
() {
var
createItem =
function
(itemText, index) {
return
<li key={index + itemText}>{itemText}</li>;
};
return
<ul>{
this
.props.items.map(createItem)}</ul>;
}
});
var
TodoApp = React.createClass({
getInitialState:
function
() {
return
{items: [], text:
''
};
},
onChange:
function
(e) {
this
.setState({text: e.target.value});
},
handleSubmit:
function
(e) {
e.preventDefault();
var
nextItems =
this
.state.items.concat([
this
.state.text]);
var
nextText =
''
;
this
.setState({items: nextItems, text: nextText});
},
render:
function
() {
return
(
<div>
<h3>TODO</h3>
<TodoList items={
this
.state.items} />
<form onSubmit={
this
.handleSubmit}>
<input onChange={
this
.onChange} value={
this
.state.text} />
<button>{
'Add #'
+ (
this
.state.items.length + 1)}</button>
</form>
</div>
);
}
});
React.render(<TodoApp />, mountNode);
// compiled javascript code
var
TodoList = React.createClass({displayName:
"TodoList"
,
render:
function
() {
var
createItem =
function
(itemText, index) {
return
React.createElement(
"li"
, {key: index + itemText}, itemText);
};
return
React.createElement(
"ul"
,
null
,
this
.props.items.map(createItem));
}
});
var
TodoApp = React.createClass({displayName:
"TodoApp"
,
getInitialState:
function
() {
return
{items: [], text:
''
};
},
onChange:
function
(e) {
this
.setState({text: e.target.value});
},
handleSubmit:
function
(e) {
e.preventDefault();
var
nextItems =
this
.state.items.concat([
this
.state.text]);
var
nextText =
''
;
this
.setState({items: nextItems, text: nextText});
},
render:
function
() {
return
(
React.createElement(
"div"
,
null
,
React.createElement(
"h3"
,
null
,
"TODO"
),
React.createElement(TodoList, {items:
this
.state.items}),
React.createElement(
"form"
, {onSubmit:
this
.handleSubmit},
React.createElement(
"input"
, {onChange:
this
.onChange, value:
this
.state.text}),
React.createElement(
"button"
,
null
,
'Add #'
+ (
this
.state.items.length + 1))
)
)
);
}
});
React.render(React.createElement(TodoApp,
null
), mountNode);
|
组件可以使用第三方插件
React非常灵活,通过钩子允许与其他的库和框架对接。这个例子使用外部的Markdown库来实时转化文本域中的内容。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
// JSX code
var
MarkdownEditor = React.createClass({
getInitialState:
function
() {
return
{value:
'Type some *markdown* here!'
};
},
handleChange:
function
() {
this
.setState({value: React.findDOMNode(
this
.refs.textarea).value});
},
render:
function
() {
return
(
<div className=
"MarkdownEditor"
>
<h3>Input</h3>
<textarea onChange={
this
.handleChange} ref=
"textarea"
defaultValue={
this
.state.value} />
<h3>Output</h3>
<div className=
"content"
dangerouslySetInnerHTML={{
__html: marked(
this
.state.value, {sanitize:
true
})
}}/>
</div>
);
}
});
React.render(<MarkdownEditor />, mountNode);
// compiled javascript code
var
MarkdownEditor = React.createClass({displayName:
"MarkdownEditor"
,
getInitialState:
function
() {
return
{value:
'Type some *markdown* here!'
};
},
handleChange:
function
() {
this
.setState({value: React.findDOMNode(
this
.refs.textarea).value});
},
render:
function
() {
return
(
React.createElement(
"div"
, {className:
"MarkdownEditor"
},
React.createElement(
"h3"
,
null
,
"Input"
),
React.createElement(
"textarea"
, {
onChange:
this
.handleChange,
ref:
"textarea"
,
defaultValue:
this
.state.value
}),
React.createElement(
"h3"
,
null
,
"Output"
),
React.createElement(
"div"
, {
className:
"content"
,
dangerouslySetInnerHTML: {
__html: marked(
this
.state.value, {sanitize:
true
})
}
})
)
);
}
});
React.render(React.createElement(MarkdownEditor,
null
), mountNode);
|