例子来自尚硅谷react视频,相当于笔记整理

link: https://www.bilibili.com/video/av51174155?from=search&seid=11218837597275325699

要做的功能: 在输入框内输入内容,点击add按钮自动添加到下面的列表去,并且清空input

重点是通过这个例子,把如何进行解决react多组件的创建和交互的思路理清了。

 

react 封装axios 加载中组件_App

功能界面组件化编码流程:
1 拆分组件:拆分页面,抽取组件
2 实现静态组件: 使用组件实现静态页面效果
3 实现动态组件:
  1)动态显示初始化数据
  2)交互功能(从绑定事件监听开始)
  
问题:数据保存在哪个组件内?
解答:看数据是某个组件需要还是某些组件需要。
    如果是后者,要将数据给共同的父组件。
    
问题:如何做交互?
解答:先绑定监听

问题:如何在子组件中改变父组件状态?
解答:子组件中不能直接改变父组件状态。状态在哪个组件,更新状态的行为就应该定义在哪个组件。
在本例中,父组件中定义更新状态的方法,子组件使用该方法,因此需要将该方法从父组件传递到子组件中。方式是通过props来传递。
精简地说:父组件定义函数,传递给子组件,子组件调用

/*
功能界面组件化编码流程:
1 拆分组件:拆分页面,抽取组件
2 实现静态组件: 使用组件实现静态页面效果
3 实现动态组件:
  1)动态显示初始化数据
  2)交互功能(从绑定事件监听开始)
  
问题:数据保存在哪个组件内?
解答:看数据是某个组件需要还是某些组件需要。
    如果是后者,要将数据给共同的父组件。
    
问题:如何做交互?
解答:先绑定监听

问题:如何在子组件中改变父组件状态?
解答:子组件中不能直接改变父组件状态。状态在哪个组件,更新状态的行为就应该定义在哪个组件。
在本例中,父组件中定义更新状态的方法,子组件使用该方法,因此需要将该方法从父组件传递到子组件中。方式是通过props来传递。
精简地说:父组件定义函数,传递给子组件,子组件调用

*/

class App extends React.Component{
  constructor(props){
    super(props);
    
    this.state = {
      todos: ['Read', 'Write']

    }
    
    this.addTodo = this.addTodo.bind(this);
  }
  
  addTodo (todo){
    console.log('addTodo - App')
    const {todos} = this.state
    todos.unshift(todo)
    this.setState({todos}) //必须调用setState才会更新页面
    console.log(todos)
  }
  
  render (){
    // return 有且仅有一个根标签!
    const {todos} = this.state
    return (
      <div>
       <h1> Simple TODO List </h1>
        <Add count={todos.length} addTodo={this.addTodo}/>
        <List todos={todos}/>
      </div>
    ); 
  }
  
}

class Add extends React.Component{
  constructor(props){
    super(props);
  
    this.add = this.add.bind(this);
  }
  
  add (){
    /*
     在子组件中不能直接改变父组件的状态。因此要使用父组件传递过来的函数。
     相当于父组件(App)暴露了一个接口来修改状态,修改的逻辑在接口中已经订好了
    (具体为在Todos前面插入一个新Todo)
     那么如何触发这个接口的使用呢?向接口中传入怎样的参数呢?都是在子组件(Add)中进行的
    具体:
      1 读取输入的数据
      2 检查合法性
      3 合法则添加
    */
  
    console.log('add - Add')
    const todo = this.todoInput.value.trim();  //通过refs获取input标签
    if(!todo){
      return 
    }
    console.log(todo)
    this.props.addTodo(todo);
    //清除input的输入
    this.todoInput.value = '';
    
    
  }
  
  render (){
    
    return (
      <div>
        <input type='text' ref={input=>this.todoInput=input}/>  
        <button onClick={this.add}> add #{this.props.count+1}</button>
      </div>
    )
  }
  
}
Add.propTypes = {
  count: PropTypes.number.isRequired,
  addTodo: PropTypes.func.isRequired
}

class List extends React.Component{
  constructor(props){
    super(props);
  }
  
  render (){
    const {todos} = this.props
    
    return (
      <ul>
        {todos.map((todo, index)=><li key={index}>{todo}</li>)}
      </ul>
    )
  }
  
}

//指定 list的参数的类型
List.propTypes = {
  todos : PropTypes.array.isRequired
  
}

ReactDOM.render(<App />, document.getElementById('root'));