react(基础二)_组件化开发页面的步骤
一、前言
组件化开发界面最好按如下步骤操作:
第一步:分析页面拆分组件
第二步:用react实现静态组件(没有动态的数据)
第三步:实现动态组件
3.1先用初始化数据显示动态页面
3.2添加实现交互功能
二、基础知识
1、假设我们需实现以下功能:
2、具体实现
第一步:将上面的简单页面拆分
第二步:用react实现静态组件(没有动态的数据)
<script type="text/babel"> //App 父组件 class App extends React.Component{ constructor (props) { super(props) } render(){ ////这里分别是App父组件中包含的两个子组件 return ( <div> <TodoAdd /> <TodoList /> </div> ) } } //TodoAdd 添加的组件 class TodoAdd extends React.Component{ constructor(props){ super(props) } //{//每个组件只有一个根,所以要用一个div包裹起来} render(){ return ( <div> <h1>动态添加</h1> <input type="text" /> <button>添加 #length</button> </div> ) } } //TodoAdd 显示列表的组件 class TodoList extends React.Component{ render(){ return ( <ul> <li>11</li> <li>22</li> <li>33</li> </ul> ) } } // 渲染应用组件标签 ReactDOM.render(<App />, document.getElementById('app')) </script>
第三步:实现初始化数据的页面(这一步是关键,我们需要考虑以下几个问题)
问题一:我们需要在那个组件里面设置初始化数据
分析:(1)先看看哪些组件里面需要用到数据(TodoAdd组件是操作数据的所以需要用到, TodoList是显示数据的所以也需要用到)
(2)这两个组件都用,那么我们将初始化数据在他们共同的父组件中App中
(3)父组件的数据传给子组件
(4)子组件使用之前必须用props约定
代码:
<script type="text/babel"> //App 父组件 class App extends React.Component{ constructor (props) { super(props) this.state={ todos:['吃饭','睡觉','打豆豆'] } } render(){ ////这里分别是App父组件中包含的两个子组件 const {todos} = this.state //拿到state, 分别给下面组件添加两个属性,通过该属性传进去(em可以说是和vue很像了) return ( <div> <TodoAdd count={todos.length}/> <TodoList todos={todos}/> </div> ) } } //TodoAdd 添加的组件 class TodoAdd extends React.Component{ constructor(props){ super(props) } //{//每个组件只有一个根,所以要用一个div包裹起来} render(){ return ( <div> <h1>动态添加</h1> <input type="text" /> <button>添加 #{this.props.count}</button> </div> ) } } //TodoAdd 添加的组件使用父组件传来的数之前必须先用props限定 TodoAdd.propTypes = { count: PropTypes.number.isRequired } //TodoAdd 显示列表的组件 class TodoList extends React.Component{ render(){ //拿到props中的数据后将数据转化为标签 //需要用{}包裹住js代码 const {todos} = this.props return ( <ul> { todos.map((todo,index)=> <li key={index}>{todo}</li>) } </ul> ) } } //TodoAdd 显示列表的组件使用父组件传来的数据时也要props限制 TodoList.propTypes = { todos: PropTypes.array.isRequired } // 渲染应用组件标签 ReactDOM.render(<App />, document.getElementById('app')) </script>
第四步:交互实现
注意的问题:
(1)在子组件中不能直接改变父组件的状态,因为我们需要点击子组件,来改变数组
(2)原则:状态在哪个组件,更新状态组件的行为就在哪个组件里
代码:
<script type="text/babel"> //App 父组件 class App extends React.Component{ constructor (props) { super(props) this.state={ todos:['吃饭','睡觉','打豆豆'] } this.add = this.add.bind(this) } //App组件里面定义方法,然后传给子组件 add(todo){ const {todos} = this.state todos.unshift(todo) this.setState({todos})//必须要通过setState才能更新state里面的数据 } render(){ ////这里分别是App父组件中包含的两个子组件 const {todos} = this.state //拿到state, 分别给下面组件添加两个属性,通过该属性传进去(em可以说是和vue很像了) return ( <div> <TodoAdd add={this.add} count={todos.length}/> <TodoList todos={todos}/> </div> ) } } //TodoAdd 添加的组件 class TodoAdd extends React.Component{ constructor(props){ super(props) this.addTodo = this.addTodo.bind(this) } addTodo () { // 读取输入数据 const text = this.input.value.trim() // 查检 if(!text) { return } // 保存到todos this.props.add(text)//将改变的数据传到父组件父add方法 // 清除输入 this.input.value = '' } //{//每个组件只有一个根,所以要用一个div包裹起来} render(){ return ( <div> <h1>动态添加</h1> <input type="text" ref={input=>this.input=input}/> <button onClick={this.addTodo}>添加 #{this.props.count}</button> </div> ) } } //TodoAdd 添加的组件使用父组件传来的数之前必须先用props限定 TodoAdd.propTypes = { add: PropTypes.func.isRequired, count: PropTypes.number.isRequired } //TodoAdd 显示列表的组件 class TodoList extends React.Component{ render(){ //拿到props中的数据后将数据转化为标签 //需要用{}包裹住js代码 const {todos} = this.props return ( <ul> { todos.map((todo,index)=> <li key={index}>{todo}</li>) } </ul> ) } } //TodoAdd 显示列表的组件使用父组件传来的数据时也要props限制 TodoList.propTypes = { todos: PropTypes.array.isRequired } // 渲染应用组件标签 ReactDOM.render(<App />, document.getElementById('app')) </script>