• 08 组件组合使用


    需求:组件化实现此功能

      1. 显示所有todo列表

      2. 输入文本, 点击按钮显示到列表的首位, 并清除输入的文本

    第一步,定义组件并渲染静态组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script src="../js/prop-types.js"></script>
        <script src="../js/babel.min.js"></script>
    </head>
    <body>
        <div id="test"></div>
    </body>
    </html>
    <script type="text/babel">
       
         //App根组件
        class AppComponent extends React.Component{
            render(){
                return(
                    <div>
                        <h1>Simplet TODO List</h1>
                        <AddComponent/>
                        <ListComponent/>
                    </div>
                )
            }
        }
    
        //上方添加组件
        class AddComponent extends React.Component {
               render() {
                   return (
                       <div>
                            <input type="text"/>
                            <button>Add#1</button>
                       </div>
                   )
               }
        }
    
        //下方列表组件
        class ListComponent extends React.Component {
                render() {
                    return (
                        <ul>
                            <li>1111</li>
                            <li>2222</li>
                            <li>3333</li>
                        </ul>
                    )
                }
        }
        ReactDOM.render(<AppComponent/>,document.getElementById("test"));
    </script>
    
    <!-- 此页面
    1,拆分为三个组件
    2,使用组件实现静态页面效果 -->

    第二步,动态显示初始化数据

    注意考虑:数据保存在哪个组件中?

           看数据是某个组件需要它(给它),还是某些组件需要它(给包含它们的父组件)
    这里,AddComponent要提供数据并且Add按钮后面的数字是数据的长度加1,ListComponent 要显示数据,都需要用到数据,所以数据应该保存在 AppComponent 中
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="../js/react.development.js"></script>
        <script src="../js/react-dom.development.js"></script>
        <script src="../js/prop-types.js"></script>
        <script src="../js/babel.min.js"></script>
    </head>
    <body>
        <div id="test"></div>
    </body>
    </html>
    <script type="text/babel">
    
        //根组件
        class AppComponent extends React.Component{
            constructor(props){
                super(props);
                //初始化状态
                this.state={
                    todos:['吃饭','睡觉','敲代码'],
                }
            }
            render(){
                const {todos} =this.state;//ES6解构赋值的写法,相当于this.state.todos,这里需要接收的是状态
                return(
                    <div>
                        <h1>Simplet TODO List</h1>
                        <AddComponent dataNum={todos.length}/> 给添加组件传一个dataNum属性,属性值是数组长度
                        <ListComponent todos={todos}/> 给列表组件传入todos属性,属性值是组件对象中的数组
                    </div>
                )
            }
        }
        //添加组件
        class AddComponent extends React.Component {
               render() {
                   return (
                       <div>
                            <input type="text"/>
                            <button>Add#{this.props.dataNum+1}</button>
                       </div>
                   )
               }
        }
        //添加组件接收dataNum属性并给予类型限制和必要性限制
        AddComponent.propTypes = {
            dataNum:PropTypes.number.isRequired,
        }
    
        //列表组件
        class ListComponent extends React.Component {
                render() {
                    const { todos } = this.props; //ES6解构赋值的写法,这里接收到的是属性
                    return (
                        <ul>
                            {todos.map((todo,index)=><li key={index}>{todo}</li>)}
                        </ul>
                    )
                }
                
        }
        //列表组件接收todos属性,并给予类型限制和必要性限制
        ListComponent.propTypes={
            todos:PropTypes.array.isRequired,
        }
        
        ReactDOM.render(<AppComponent/>,document.getElementById("test"));
    </script>

     第三步,做交互,输入一个 todo ,点击Add按钮,这个 todo 要添加到 state 中的 todos 数据中,并更新 todos 状态

    考虑:

    我们是点击按钮时要改变父组件中的状态,是在子组件中改变父组件的状态,但这是不允许的,因为状态在哪个组件,更新状态的行为就应该在哪个组件,这里的行为就是指 添加todo 这个事件。

    方案:

    父组件定义函数,通过标签传递给子组件,子组件调用
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     6     <title>Document</title>
     7     <script src="../js/react.development.js"></script>
     8     <script src="../js/react-dom.development.js"></script>
     9     <script src="../js/prop-types.js"></script>
    10     <script src="../js/babel.min.js"></script>
    11 </head>
    12 <body>
    13     <div id="test"></div>
    14 </body>
    15 </html>
    16 <script type="text/babel">
    17    
    18     //根组件
    19     class AppComponent extends React.Component{
    20         constructor(props){
    21             super(props);
    22             //初始化状态
    23             this.state={
    24                 todos:['吃饭','睡觉','敲代码'],
    25             }
    26             this.addData=this.addData.bind(this); //addData()方法是自己定义的,帮它的this绑定到组件对象上
    27         }
    28         addData(todo){
    29             const {todos}=this.state;
    30             todos.unshift(todo);//unshift()向数组的头部添加元素,push()向数组的尾部添加元素
    31             //更新状态
    32             this.setState({todos});
    33         }
    34         render(){
    35             const {todos}=this.state;
    36             return(
    37                 <div>
    38                     <h1>Simplet TODO List</h1>
    39                     <AddComponent dataNum={todos.length} addData={this.addData} todos={todos}/> 
    40                     <ListComponent todos={this.state.todos}/>
    41                 </div>
    42             )
    43         }
    44     }
    45     //添加组件
    46     class AddComponent extends React.Component {
    47            constructor(props){
    48                super(props);
    49                this.addLi=this.addLi.bind(this); //addLi()自己定义的方法,注意绑定this
    50            }
    51            addLi(){
    52              alert(this.input.value);//获取的输入框中的值
    53              const text=this.input.value.trim() //读取输入数据
    54              if(!text){ //考虑输入不合法的情况,比如输入的是一个空字符串,就不添加
    55                  return;
    56              }
    57              this.props.addData(text);//调用接收到的addData()这个方法,并传入参数(输入框中的值)
    58              this.input.value=''; //清除输入框
    59            }
    60            render() {
    61                return (
    62                    <div>
    63                         <input type="text" ref={input=>this.input=input}/>
    64                         <button onClick={this.addLi}>Add#{this.props.dataNum+1}</button>
    65                    </div>
    66                )
    67            }
    68     }
    69     AddComponent.propTypes={
    70         dataNum:PropTypes.number.isRequired,
    71         addData:PropTypes.func.isRequired,//函数也是一个属性,可以以同样的方式接收
    72         todos:PropTypes.array.isRequired,
    73     }
    74 
    75     //列表组件
    76     class ListComponent extends React.Component {
    77             render() {
    78                 const { todos } = this.props;
    79                 return (
    80                     <ul>
    81                         {todos.map((todo,index)=><li key={index}>{todo}</li>)}
    82                     </ul>
    83                 )
    84             }
    85             
    86     }
    87     ListComponent.propTypes={
    88         todos:PropTypes.array.isRequired,
    89     }
    90     
    91     ReactDOM.render(<AppComponent/>,document.getElementById("test"));
    92 </script>
    补充,考虑用户输入的 todo 列表中已经存在就不添加,只有当用户输入的内容在 todos 中没有出现过才添加
    在 addLi() 中添加一个判断
     
     
  • 相关阅读:
    快速得到栈、队列的最大值
    原型与原型链
    人家跟你谈生意,你连份明码标价的菜单都拿不出来,有什么资格好撒气的?
    一个坑:java.sql.ResultSet.getInt==》the column value; if the value is SQL NULL, the value returned is 0
    static在实例Extends、Overload中理解
    JVM-ClassLoader(转)
    关于eclipse和javac编译结果不一致的问题的分析与解决 (转)
    蜗牛—JSP学习之JavaBean初识
    ibatis 开发中的经验 (一)ibatis 和hibernate 在开发中的理解
    关于64位Linux配置android开发环境出现 No such file or directory
  • 原文地址:https://www.cnblogs.com/shanlu0000/p/12487009.html
Copyright © 2020-2023  润新知