组件化编写功能的流程
拆分组件
实现静态组件,只有静态界面,没有动态数据,也没有动态交互
实现动态组件(实现动态数据初始化显示;实现交互功能)
初始化显示
拆分组件: 拆分界面,抽取组件,实现静态组件: 使用组件实现静态页面效果
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>05_components_composing</title>
</head>
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class App extends React.Component {
render () {
return (
<div>
<h1>Simple TODO List</h1>
<Add />
<List />
</div>
)
}
}
class Add extends React.Component {
render () {
return (
<div>
<input type="text" />
<button>add #4</button>
</div>
)
}
}
class List extends React.Component {
render () {
return (
<ul>
<li>AAAA</li>
<li>BBBB</li>
<li>CCCC</li>
</ul>
)
}
}
ReactDOM.render(<App/>, document.getElementById('example'))
</script>
</body>
</html>
实现动态组件:动态显示初始化数据
数据保存在哪个组件,如果是这个数据只是某个组件需要用到,那么就放在该组件,如果有两个组件需要用到,那么放在他们共同的父组件里
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>05_components_composing</title>
</head>
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 这种情况下将数据放在App组件里面,这样两个子组件Add和List都可以使用到这个数据
class App extends React.Component {
constructor (props) {
super (props)
this.state = {
todos: ['吃饭', '睡觉', '写代码']
}
}
render () {
return (
<div>
<h1>Simple TODO List</h1>
<Add />
<List todos={this.state.todos}/>
</div>
)
}
}
class Add extends React.Component {
render () {
return (
<div>
<input type="text" />
<button>add #4</button>
</div>
)
}
}
class List extends React.Component {
render () {
return (
<ul>{this.props.todos.map((todo, index) => <li key={index}>{todo}</li>)}</ul>
)
}
}
List.protoType = {
todos: PropTypes.array.isRequired
}
ReactDOM.render(<App/>, document.getElementById('example'))
</script>
</body>
</html>
交互功能
子组件改变父组件的状态(状态在哪个组件,更新状态的行为就应该定义在哪个组件,父组件定义函数,传给子组件调用)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>05_components_composing</title>
</head>
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
// 这种情况下将数据放在App组件里面,这样两个子组件Add和List都可以使用到这个数据
class App extends React.Component {
constructor (props) {
super (props)
this.state = {
todos: ['吃饭', '睡觉', '写代码']
}
this.addTodo = this.addTodo.bind(this)
}
render () {
const {todos} = this.state
return (
<div>
<h1>Simple TODO List</h1>
<Add count={todos.length} addTodo={this.addTodo}/>
<List todos={todos}/>
</div>
)
}
addTodo (todo) {
const {todos} = this.state // 先取出状态
todos.unshift(todo)
this.setState({todos})// 更新状态
}
}
class Add extends React.Component {
constructor (props) {
super (props)
this.add = this.add.bind(this)
}
render () {
return (
<div>
<input type="text" ref={input => this.todoInput = input}/>
<button onClick={this.add}>add #{this.props.count + 1}</button>
</div>
)
}
add () {
// 1.读取输入的数据
const todo = this.todoInput.value.trim()
// 2.检查合法性
if (!todo) {
return
}
// 3.添加
this.props.addTodo(todo)
// 4.清除输入
this.todoInput.value = ''
}
}
Add.propTypes = {
count: PropTypes.number.isRequired,
addTodo: PropTypes.func.isRequired
}
class List extends React.Component {
render () {
return (
<ul>
{
this.props.todos.map((todo, index) => {return <li key={index}>{todo}</li>})
}
</ul>
)
}
}
List.propTypes = {
todos: PropTypes.array.isRequired
}
ReactDOM.render(<App/>, document.getElementById('example'))
</script>
</body>
</html>