react【一】 传参

一、认识React

1、第一个react程序

在这里插入图片描述

<body>
  <div id="root"></div>
  
  <!-- 引入依赖 -->
  <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> 
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <!-- 编写React代码 -->
  <script type="text/babel">
    const root = ReactDOM.createRoot(document.querySelector("#root"))

    // 1.将文本定义成变量
    let message = "Hello World"

    // 2.监听按钮的点击
    function btnClick() {
      // 1.1.修改数据
      message = "Hello React"

      // 2.重新渲染界面
      rootRender()
    }

    // 3.封装一个渲染函数
    function rootRender() {
      root.render((
        <div>
          <h2>{message}</h2>
          <button onClick={btnClick}>修改文本</button>
        </div>
      ))
    }
    rootRender()
  </script>

</body>

2、使用组件重构代码

在这里插入图片描述

<body>

  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">

    // 使用组件进行重构代码
    // 类组件和函数式组件
    class App extends React.Component {
      // 组件数据
      constructor() {
        super()
        this.state = {
          message: "Hello World",

          name: "why",
          age: 18
        }

        // 对需要绑定的方法, 提前绑定好this
        this.btnClick = this.btnClick.bind(this)
      }

      // 组件方法(实例方法)
      btnClick() {
        // 内部完成了两件事情: 
        // 1.将state中message值修改掉 2.自动重新执行render函数函数
        this.setState({
          message: "Hello React"
        })
      }

      // 渲染内容 render方法
      render() {
        return (
          <div>
            <h2>{this.state.message}</h2>
            <button onClick={this.btnClick}>修改文本</button>
          </div>
        )
      }
    }

    // this绑定的问题
    // const app = new App()
    // const foo = app.btnClick
    // foo(); // 默认绑定 => window => 严格模式下 => undefined

    // function bar() {
    //   console.log("bar:", this);
    // }
    // bar()


    // 将组件渲染到界面上
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    // App根组件
    root.render(<App/>)


  </script>

</body>

3、遍历列表案例

<body>
  
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">
    // 1.创建root
    const root = ReactDOM.createRoot(document.querySelector("#root"))

    // 封装App组件
    class App extends React.Component {
      constructor() {
        super()

        this.state = {
          movies: ["星际穿越", "流浪地球", "独行月球", "大话西游", "火星救援"]
        }
      }


      render() {
        // 1.对movies进行for循环
        // const liEls = []
        // for (let i = 0; i < this.state.movies.length; i++) {
        //   const movie = this.state.movies[i]
        //   const liEl = <li>{movie}</li>
        //   liEls.push(liEl)
        // }

        // 2.movies数组 => liEls数组
        // const liEls = this.state.movies.map(movie => <li>{movie}</li>)

        return (
          <div>
            <h2>电影列表</h2>
            <ul>
              {this.state.movies.map(movie => <li>{movie}</li>)}
            </ul>
          </div>
        )
      }
    }


    // 2.渲染组件
    root.render(<App/>)
  </script>

</body>

4、计数器案例

<body>
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">
    const root = ReactDOM.createRoot(document.querySelector("#root"))

    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          message: "Hello World",
          counter: 100
        }

        this.increment = this.increment.bind(this)
        this.decrement = this.decrement.bind(this)
      }

      render() {
        const { counter } = this.state

        return (
          <div>
            <h2>当前计数: {counter}</h2>
            <button onClick={this.increment}>+1</button>
            <button onClick={this.decrement}>-1</button>
          </div>
        )
      }

      // 组件的方法
      increment() {
        this.setState({
          counter: this.state.counter + 1
        })
      }

      decrement() {
        this.setState({
          counter: this.state.counter - 1
        })
      }
    }

    root.render(<App/>)
  </script>

</body>

5、为什么React选择了JSX

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

<body>
  
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">
    // 1.定义App根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          counter: 100,
          message: "Hello World",
          names: ["abc", "cba", "nba"],

          aaa: undefined,
          bbb: null,
          ccc: true,

          friend: { name: "kobe" },

          firstName: "kobe",
          lastName: "bryant",

          age: 20,

          movies: ["流浪地球", "星际穿越", "独行月球"]
        }
      }

      render() {
        // 1.插入标识符
        const { message, names, counter } = this.state
        const { aaa, bbb, ccc } = this.state
        const { friend } = this.state

        // 2.对内容进行运算后显示(插入表示)
        const { firstName, lastName } = this.state
        const fullName = firstName + " " + lastName
        const { age } = this.state
        const ageText = age >= 18 ? "成年人": "未成年人"
        const liEls = this.state.movies.map(movie => <li>{movie}</li>)

        // 3.返回jsx的内容
        return (
          <div>
            {/* 1.Number/String/Array直接显示出来 */}
            <h2>{counter}</h2>
            <h2>{message}</h2>
            <h2>{names}</h2>

            {/* 2.undefined/null/Boolean */}
            <h2>{String(aaa)}</h2>
            <h2>{bbb + ""}</h2>
            <h2>{ccc.toString()}</h2>

            {/* 3.Object类型不能作为子元素进行显示*/}
            <h2>{friend.name}</h2>
            <h2>{Object.keys(friend)[0]}</h2>

            {/* 4.可以插入对应的表达式*/}
            <h2>{10 + 20}</h2>
            <h2>{firstName + " " + lastName}</h2>
            <h2>{fullName}</h2>

            {/* 5.可以插入三元运算符*/}
            <h2>{ageText}</h2>
            <h2>{age >= 18 ? "成年人": "未成年人"}</h2>

            {/* 6.可以调用方法获取结果*/}
            <ul>{liEls}</ul>
            <ul>{this.state.movies.map(movie => <li>{movie}</li>)}</ul>
            <ul>{this.getMovieEls()}</ul>
          </div>
        )
      }

      getMovieEls() {
        const liEls = this.state.movies.map(movie => <li>{movie}</li>)
        return liEls
      }
    }

    // 2.创建root并且渲染App组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

</body>
<body>
  
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">
    // 1.定义App根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          title: "哈哈哈",
          imgURL: "https://ts1.cn.mm.bing.net/th/id/R-C.95bc299c3f1f0e69b9eb1d0772b14a98?rik=W5QLhXiERW4nLQ&riu=http%3a%2f%2f20178405.s21i.faiusr.com%2f2%2fABUIABACGAAgoeLO-wUo4I3o2gEw8Qs4uAg.jpg&ehk=N7Bxe9nqM08w4evC2kK6yyC%2bxIWTjdd6HgXsQYPbMj0%3d&risl=&pid=ImgRaw&r=0",
          href: "https://www.baidu.com",
          isActive: true,
          objStyle: {color: "red", fontSize: "30px"}
        }
      }

      render() {
        const { title, imgURL, href, isActive, objStyle } = this.state

        // 需求: isActive: true -> active
        // 1.class绑定的写法一: 字符串的拼接
        const className = `abc cba ${isActive ? 'active': ''}`
        // 2.class绑定的写法二: 将所有的class放到数组中
        const classList = ["abc", "cba"]
        if (isActive) classList.push("active")
        // 3.class绑定的写法三: 第三方库classnames -> npm install classnames

        return (
          <div>
            { /* 1.基本属性绑定 */ }
            <h2 title={title}>我是h2元素</h2>
            {/*<img src={imgURL} alt=""/>*/}
            <a href={href}>百度一下</a>

            
            { /* 2.绑定class属性: 最好使用className */ }
            <h2 className={className}>哈哈哈哈</h2>
            <h2 className={classList.join(" ")}>哈哈哈哈</h2>

            
            { /* 3.绑定style属性: 绑定对象类型 */ }
            <h2 style={{color: "red", fontSize: "30px"}}>呵呵呵呵</h2>
            <h2 style={objStyle}>呵呵呵呵</h2>
          </div>
        )
      }
    }

    // 2.创建root并且渲染App组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

</body>

6、this的绑定问题

在这里插入图片描述

<body>
  
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">
    // const obj = {
    //   name: "obj",
    //   foo: function() {
    //     console.log("foo:", this)
    //   }
    // }

    // // obj.foo()

    // const config = {
    //   onClick: obj.foo.bind(obj)
    // }

    // const click = config.onClick
    // click()

    /*
      this的四种绑定规则:
        1.默认绑定 独立执行 foo()
        2.隐式绑定 被一个对象执行 obj.foo() -> obj
        3.显式绑定: call/apply/bind foo.call("aaa") -> String("aaa")
        4.new绑定: new Foo() -> 创建一个新对象, 并且赋值给this
    */

    // 1.定义App根组件
    class App extends React.Component {
      // class fields
      name = "App"

      constructor() {
        super()
        this.state = {
          message: "Hello World",
          counter: 100
        }

        this.btn1Click = this.btn1Click.bind(this)
      }

      btn1Click() {
        console.log("btn1Click", this);
        this.setState({ counter: this.state.counter + 1 })
      }

      btn2Click = () => {
        console.log("btn2Click", this)
        this.setState({ counter: 1000 })
      }

      btn3Click() {
        console.log("btn3Click", this);
        this.setState({ counter: 9999 })
      }

      render() {
        const { message } = this.state

        return (
          <div>
            {/* 1.this绑定方式一: bind绑定 */}
            <button onClick={this.btn1Click}>按钮1</button>

            
            {/* 2.this绑定方式二: ES6 class fields */}
            <button onClick={this.btn2Click}>按钮2</button>


            {/* 3.this绑定方式三: 直接传入一个箭头函数(重要) */}
            <button onClick={() => console.log("btn3Click")}>按钮3</button>

            <button onClick={() => this.btn3Click()}>按钮3</button>


            <h2>当前计数: {this.state.counter}</h2>
          </div>
        )
      }
    }

    // 2.创建root并且渲染App组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

</body>

二、传参

2.1 事件参数传递

在这里插入图片描述

<body>
  
  <div id="root"></div>

  <script src="../lib/react.js"></script>
  <script src="../lib/react-dom.js"></script>
  <script src="../lib/babel.js"></script>

  <script type="text/babel">

    // function foo(name, age, height) {}
    // const bar = foo.bind("aaa", "kobe", 30)
    // bar("event")

    // 1.定义App根组件
    class App extends React.Component {
      constructor() {
        super()
        this.state = {
          message: "Hello World"
        }
      }

      btnClick(event, name, age) {
        console.log("btnClick:", event, this)
        console.log("name, age:", name, age)
      }

      render() {
        const { message } = this.state

        return (
          <div>
            {/* 1.event参数的传递 */}
            <button onClick={this.btnClick.bind(this)}>按钮1</button>
            <button onClick={(event) => this.btnClick(event)}>按钮2</button>

            
            {/* 2.额外的参数传递 */}
            <button onClick={this.btnClick.bind(this, "kobe", 30)}>按钮3(不推荐)</button>

            <button onClick={(event) => this.btnClick(event, "why", 18)}>按钮4</button>
          </div>
        )
      }
    }

    // 2.创建root并且渲染App组件
    const root = ReactDOM.createRoot(document.querySelector("#root"))
    root.render(<App/>)
  </script>

</body>

2.2 传参的案例

<body>
    <div id="root"></div>
    <script src="../lib/react.js"></script>
    <script src="../lib/react-dom.js"></script>
    <script src="../lib/babel.js"></script>

    <script type="text/babel">
        class App extends React.Component {
        constructor() {
          super();
          this.state = {
            movies: ["星际穿越", "盗梦空间", "大话西游", "流浪地球"],
            currentIndex: 0,
          };
        }
        handleClick(index) {
          this.setState({
            currentIndex: index,
          });
        }

        // render() {
        //   const { movies, currentIndex } = this.state;
        //     const lis = movies.map((item,index)=>{
        //         return (
        //             <li className={index==currentIndex?'active':""}
        //                 key={index}
        //                 onClick={()=>this.handleClick(index)}
        //             >
        //              {item}
        //             </li>
        //         )
        //     })
        //     return (
        //         <div>
        //             <ul>
        //                 {lis}
        //             </ul>
        //         </div>
        //     )
        // }
        render(){
            const {movies,currentIndex} = this.state

            const mapLis = (item,index) =>{
                return (
                    <li
                        className = {currentIndex ==index?'active':''}
                        key={index}
                        onClick={()=>this.handleClick(index)}
                    >
                    {item}
                    </li>)
            }

            return (
                <div>
                    <ul>{movies.map(mapLis)}</ul>    
                </div>
            )
        }
      }
      const root = ReactDOM.createRoot(document.querySelector("#root"));
      root.render(<App/>)
    </script>
</body>

三、生命周期

在这里插入图片描述

在这里插入图片描述

import React from "react";
import HelloWord from "./HelloWord";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      isShow: true,
    };
  }
  handleRemove() {
    const { isShow } = this.state;
    this.setState({ isShow: !isShow });
  }
  render() {
    const { isShow } = this.state;
    return (
      <div>
        <button onClick={() => this.handleRemove()}>点击卸载组件</button>
        {isShow && <HelloWord />}
      </div>
    );
  }
}

export default App;

import React from "react";

class HelloWord extends React.Component {
  // 1.先执行构造方法
  constructor() {
    super();
    this.state = {
      number: 1,
      isShow: true,
    };
  }
  handleClick() {
    const { number } = this.state;
    this.setState({ number: number + 1 });
  }

  // 2.执行render函数
  render() {
    const { number } = this.state;
    return (
      <div>
        <button onClick={() => this.handleClick()}>点击更新</button>
        <h1>{number}</h1>
      </div>
    );
  }

  // 3.组件被渲染到DOM:被挂载到DOM
  componentDidMount() {
    console.log("组件被挂载");
  }

  // 4.Dom发生更新
  // 第一个参数 更新前的props 更新前的state 获取dom更新前的信息
  componentDidUpdate(preProps, preState, snapShot) {
    console.log("Dom元素发生了更新");
    console.log(preProps, preState, snapShot);
  }

  // 5.组件被卸载掉
  componentWillUnmount() {
    console.log("组件发生了卸载");
  }

  // 不常用的生命周期 用来保存dom更新前的信息
  getSnapshotBeforeUpdate() {
    console.log("获取dom更新前的信息");
    return {
      scrollTop: 100,
    };
  }
}

export default HelloWord;

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、组件之间传递参数

1、父传子

  • APP.jsx
import React, { Component } from "react";
import Son from "./components/Son";

export class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      <div>
        <Son title={["我是标题"]}></Son>
      </div>
    );
  }
}

export default App;
  • son.jsx
import React, { Component } from "react";
import PropTypes from "prop-types";

export class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const { title } = this.props;
    return <div>{title}</div>;
  }
}

// 对传入的props设置默认值
Son.defaultProps = {
  title: "默认标题",
};

// 对传入的props类型进行验证
Son.propTypes = {
  title: PropTypes.string,
};

export default Son;

2、子传父

在这里插入图片描述

  • App.jsx
import React, { Component } from "react";
import Son from "./Son";

class App extends Component {
  constructor() {
    super();
    this.state = {
      counter: 20,
    };
  }

  changeCounter(value) {
    this.setState({ counter: this.state.counter + value });
  }

  render() {
    const { counter } = this.state;
    return (
      <div>
        <h1>当前计数为{counter}</h1>
        <Son changeCounterFun={(counter) => this.changeCounter(counter)}>
          +1
        </Son>
      </div>
    );
  }
}

export default App;

  • Son.jsx
import React, { Component } from "react";

class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  changeCounter(value) {
    const { changeCounterFun } = this.props;
    changeCounterFun(value);
  }

  render() {
    return (
      <div>
        <button onClick={() => this.changeCounter(+1)}>+1</button>
        <button onClick={() => this.changeCounter(-1)}>+1</button>
      </div>
    );
  }
}

export default Son;

3、案例

在这里插入图片描述

在这里插入图片描述

  • son.jsx
import React, { Component } from "react";
import "./Son.css";

export class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {
      currentIndex: 0,
    };
  }

  changeTab(index) {
    const { currentIndex } = this.state;
    console.log("发射", currentIndex);
    this.setState({ currentIndex: index });
    this.props.changeTabFun(currentIndex);
  }
  render() {
    const { currentIndex } = this.state;
    const activeClass = (index) => {
      if (index === currentIndex) return true;
      else return false;
    };

    const tabs = this.props.tabs;
    const tabsDom = tabs.map((item, index) => (
      <div
        className={`tab ${activeClass(index) ? "active" : ""}`}
        key={index}
        onClick={() => this.changeTab(index)}
      >
        {item},{index}
      </div>
    ));

    return <div className="tabs">{tabsDom}</div>;
  }
}

export default Son;


4、剧名插槽

在这里插入图片描述

import React, { Component } from "react";
import "./Son.css";

export class Son extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    const { children } = this.props;
    const { slotLeft, slotRight, slotCenter } = this.props;
    return (
      <div>
        {children}
        <div className="tabs">
          <div className="tab">{slotLeft}</div>
          <div className="tab">{slotCenter}</div>
          <div className="tab">{slotRight}</div>
        </div>
      </div>
    );
  }
}

export default Son;

在这里插入图片描述

5、作用域插槽

在这里插入图片描述
在这里插入图片描述

6、context

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.

import React from "react";

// 1、创建一个Context
const userContext = React.createContext();

export default userContext;

App.jsx

import React, { Component } from "react";
import User from "./components/User";

import userContext from "./context/user-context";

class App extends Component {
  constructor() {
    super();
    this.state = {
      info: {
        name: "APP.JSX",
        age: 18,
      },
    };
  }
  render() {
    const { info } = this.state;
    return (
      <div>
        {/* 第2步骤 通过value为后代提供组件 */}
        <userContext.Provider value={{ nickName: "kiki", age: 18 }}>
          <User {...info}></User>
        </userContext.Provider>
      </div>
    );
  }
}

export default App;

  • user.jsx
import React, { Component } from "react";

import userContext from "../context/user-context";

export class User extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    const { name, age } = this.props;
    return (
      <div>
        <h1>
          props传进来的值:{name},{age}
        </h1>
        {/* 4、使用上下文的数值 */}
        <h1>通过context传进来的值:{this.context.nickName}</h1>

        {/* 也可以通过消费者来获取值 */}
        <userContext.Consumer>
          {(value) => {
            return value.nickName;
          }}
        </userContext.Consumer>
      </div>
    );
  }
}

// 3、引入上下文
User.contextType = userContext;

export default User;

``
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值