干巴爹兔的博客 干巴爹兔的博客
首页
  • 前端文章

    • JavaScript
    • HTML
    • Vue
  • 学习笔记

    • JavaScript教程
    • React学习笔记
    • Electron学习笔记
  • 开源项目

    • cloud-app-admin
    • 下班了吗Vscode插件
    • Subversion变更单插件
  • Server

    • Django
  • 学习笔记

    • MySQL学习笔记
  • 运维

    • 服务器部署
    • Linux
  • 日常学习

    • 学习方法
关于
收藏
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

干巴爹兔

卑微的前端打工人
首页
  • 前端文章

    • JavaScript
    • HTML
    • Vue
  • 学习笔记

    • JavaScript教程
    • React学习笔记
    • Electron学习笔记
  • 开源项目

    • cloud-app-admin
    • 下班了吗Vscode插件
    • Subversion变更单插件
  • Server

    • Django
  • 学习笔记

    • MySQL学习笔记
  • 运维

    • 服务器部署
    • Linux
  • 日常学习

    • 学习方法
关于
收藏
友链
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React学习

    • React入门笔记(一)
    • React入门笔记(二):JSX样式、组件初识
    • React入门笔记(三):React状态、事件绑定
      • React入门笔记(四):React生命周期、插槽、路由
      • React入门笔记(五):Redux、react-redux
    • Redux学习

    • 《React学习笔记》
    • React学习
    干巴爹兔
    2020-06-17
    目录

    React入门笔记(三):React状态、事件绑定

    # 四、React状态

    # 4.1、React的state

    react的state相较于props它可以对状态进行更改,这也是react中很重要的一个部分。在类组件中它在construor函数中定义:

    constructor(props) {
        super(props);
        //状态(数据) -- view
        //构造函数初始化数据,将需要改变的数据初始化到state中
        this.state = {
          time: new Date().toLocaleTimeString(),
        };
      }
    
    1
    2
    3
    4
    5
    6
    7
    8

    要调用state中的状态,只需要this.state.你的变量:

    render() {
        // this.state.time = new Date().toLocaleTimeString();
        return (
          <div>
            <h1>当前时间:{this.state.time}</h1>
          </div>
        );
      }
    
    1
    2
    3
    4
    5
    6
    7
    8

    想要给state赋值请勿直接赋值state,通过setState函数来进行状态的更改,直接赋值并不会出发react的dom更新。通过setState函数来进行状态的更改并不会立即修改DOM里的内容,他会在所有设置状态改变之后统一对比虚拟dom。

    这里是一个时钟的demo,通过setInterval来不断进行状态更新:

    import React from "react";
    import ReactDOM from "react-dom";
    
    class Clock extends React.Component {
      constructor(props) {
        super(props);
        //状态(数据) -- view
        //构造函数初始化数据,将需要改变的数据初始化到state中
        this.state = {
          time: new Date().toLocaleTimeString(),
        };
      }
    
      render() {
        // this.state.time = new Date().toLocaleTimeString();
        return (
          <div>
            <h1>当前时间:{this.state.time}</h1>
          </div>
        );
      }
    
      //生命周期函数,组件渲染完成时的函数
      componentDidMount(){
        //请勿直接赋值state,通过setState函数来进行状态的更改
        //通过setState函数来进行状态的更改并不会立即修改DOM里的内容,他会在所有设置状态改变之后统一对比虚拟dom
        setInterval(()=>{
          this.setState({
            time:new Date().toLocaleTimeString()
          })
        },1000)
      }
    }
    
    ReactDOM.render(<Clock/>,document.getElementById('root'));
    
    // setInterval(() => {
    //   ReactDOM.render(<Clock />, document.getElementById("root"));
    // }, 1000);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    # 4.2、事件的绑定

    除了状态,我们还需要一些事件,react中的事件和原生的函数写法没有不同,但是在jsx中调用事件需要做好事件this绑定,this的绑定可以在construor中实现,this.function = this.function.bind(this);或者在调用的时候使用箭头函数,这样你就不用担心this的指向问题,统一指向class:

    render() {
        return (
          <div>
            <button data-index="1" onClick={(e)=>this.clickEvent(e)}>
              内容1
            </button>
            <button data-index="2" onClick={(e)=>this.clickEvent(e)}>
              内容2
            </button>
            <div className={this.state.c1}>
              <h1>内容1</h1>
            </div>
            <div className={this.state.c2}>
              <h1>内容2</h1>
            </div>
          </div>
        );
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    这里我们做一个demo,利用之前学过的state来做一个点击按钮切换页面的事件,在这个例子中我们还在标签中使用的data-index的属性,它可以通过e.target.dataset.index获得具体的值,从而实现判断由那个按钮获得的元素,从而实现切换的效果:

    import React from "react";
    import ReactDOM from "react-dom";
    import "./Tab.css";
    
    class Tab extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          c1: "content active",
          c2: "content",
        };
    
        //this.clickEvent = this.clickEvent.bind(this);
      }
      clickEvent(e) {
        console.log(e.target.dataset.index);
        let index = e.target.dataset.index;
        if (index === "1") {
          this.setState({
            c1: "content active",
            c2: "content",
          });
        } else {
          this.setState({
            c1: "content",
            c2: "content active",
          });
        }
      }
    
      render() {
        return (
          <div>
            <button data-index="1" onClick={(e)=>this.clickEvent(e)}>
              内容1
            </button>
            <button data-index="2" onClick={(e)=>this.clickEvent(e)}>
              内容2
            </button>
            <div className={this.state.c1}>
              <h1>内容1</h1>
            </div>
            <div className={this.state.c2}>
              <h1>内容2</h1>
            </div>
          </div>
        );
      }
    }
    
    ReactDOM.render(<Tab />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52

    # 4.3、Props传值

    父传递给子组件数据,子不能传给父,props传值可以是任意的类型,props可以设置默认值

    注意:props可以传递函数,props可以传递父元素的函数,就可以修改父元素的状态state,从而达到传递数据给父元素

    这个例子通过父传子实现控制效果:

    import React from "react";
    import ReactDOM from "react-dom";
    import './01props.css'
    
    //即在父元素使用state去控制子元素的props从而达到父元素传递数据给子元素
    
    class ParentCom extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          isActive:true
        }
      }
    
      changeShow(){
        this.setState({
          isActive:!this.state.isActive
        })
      }
    
      render(){
        return(
          <div>
            <button onClick={(e)=>this.changeShow(e)}>控制子元素显示</button>
            <ChildCom isActive={this.state.isActive}/>
          </div>
        )
      }
    }
    
    class ChildCom extends React.Component{
      constructor(props){
        super(props)
      }
      render(){
        let strClass = null;
        if(this.props.isActive){
          strClass = ' active'
        }else{
          strClass = ''
        }
    
        return (
          <div className={"content"+strClass}>
            <h1>子元素</h1>
          </div>
        )
      }
    }
    
    ReactDOM.render(<ParentCom/>,document.getElementById('root'))
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    .content{
        width: 400px;
        height: 400px;
        background-color: skyblue;
        display: none;
    }
    
    .content.active{
        display: block;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    子传递父的数据:调用父元素的函数从而操作父元素的数据,从而实现数据从子元素传递至父元素,下列代码实现了点击子类的按钮,将子类的state数据通过父类传递给子类的props函数来实现修改父类的数据:

    import React from "react";
    import ReactDOM from "react-dom";
    
    
    //实现子传父
    
    class Parent extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          parentData:null
        }
      }
    
      setParentData = (data) =>{
        this.setState({
          parentData:data
        })
      }
    
      render(){
        return(
          <div>
            <h1>子元素传递给父元素的数据:{this.state.parentData}</h1>
            <ChildCom setParentData={this.setParentData}/>
          </div>
        )
      }
    }
    
    class ChildCom extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          msg:'helloworld'
        }
      }
    
      sendData(){
        console.log(this.state.msg)
        //将子元素传递给到父元素,实际就是调用父元素传递进来的函数
        this.props.setParentData(this.state.msg)
      }
    
      render(){
        return(
          <div>
            <button onClick={(e)=>this.sendData(e)}>传递helloworld给父元素</button>
    		<button onClick={()=>this.props.setParentData('直接传递')}>直接传递helloworld给父元素</button>
          </div>
        )
      }
    }
    
    ReactDOM.render(<Parent/>,document.getElementById('root'))
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55

    # 4.4、react事件

    特点:

    1. 事件绑定采用驼峰命名
    2. 使用{}传入一个函数

    事件对象:react返回的事件对象是代理的原生事件对象,如果想要查看事件对象的具体值,必须直接输出事件对象的属性。原生,组织默认行为时,可以直接返回return false,但是react不行,可以使用preventDefault来阻止:

    import React from "react";
    import ReactDOM from "react-dom";
    
    class ParentCom extends React.Component {
      constructor(props) {
        super(props);
      }
    
      parentEvent = (e) => {
        console.log(e);
        e.preventDefault()
      };
    
      render() {
        return (
          <div>
            <form action="http://baidu.com">
              <div className="child">
                <h1>你好</h1>
                <button onClick={this.parentEvent}>提交</button>
              </div>
            </form>
          </div>
        );
      }
    }
    
    ReactDOM.render(<ParentCom />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    React中阻止默认事件必须使用e.preventDefault()

    但是react的事件调用如果带参数传递,需要使用匿名(箭头)函数的方式,否则他会在渲染的时候不需要点击直接调用函数,实现的方法如下:

             <button onClick={(e)=>{this.parentEvent1('123',e)}}>提交</button>
    		...
    		parentEvent1 = (msg,e) => {
        console.log(msg);
        console.log(e);
      };
    
    1
    2
    3
    4
    5
    6

    # 4.5、条件渲染

    react中条件渲染即和JavaScript中的条件运算,如if...else,三元运算符等相同。

    1.直接通过条件运算返回要渲染的js对象

    import React from "react";
    import ReactDOM from "react-dom";
    
    function UserGreet(props){
      return (
        <h1>欢迎登录</h1>
      )
    }
    
    function UserLogin(props){
      return(
        <h1>请先登录</h1>
      )
    }
    
    class ParentCom extends React.Component{
      constructor(props){
        super(props)
        this.state = {
          isLogin:true
        }
      }
    
      render(){
        let element = null
        this.state.isLogin ? element = <UserGreet/> : element = <UserLogin/>
        return element
      }
    }
    
    ReactDOM.render(<ParentCom />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    2.通过条件运算得出jsx对象,再将jsx对象渲染到模板中

    import React from "react";
    import ReactDOM from "react-dom";
    
    function UserGreet(props) {
      return <h1>欢迎登录</h1>;
    }
    
    function UserLogin(props) {
      return <h1>请先登录</h1>;
    }
    
    class ParentCom extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          isLogin: true,
        };
      }
    
      render() {
        let element = null;
        this.state.isLogin ? (element = <UserGreet />) : (element = <UserLogin />);
        return (
          <div>
            <header>
              <h1>这是头部</h1>
            </header>
            <section>{element}</section>
          {this.state.isLogin?<UserGreet></UserGreet>:<UserLogin></UserLogin>}
            <footer>
              <h1>这是尾部</h1>
            </footer>
          </div>
        );
      }
    }
    
    ReactDOM.render(<ParentCom />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39

    # 4.6、列表渲染

    不能通过循环直接输出模板,需要通过数组的形式将数组的内容放置到模板中,将数据拼装成jsx数组对象

    import React from "react";
    import ReactDOM from "react-dom";
    
    let arr = ["陈昀昊","方胖胖","班长"]
    
    function Welcome(props){
      return(
        <div>
          <ul>
            {arr.map((list,i)=>{
              return <li key={i}>{list}</li>
            })}
          </ul>
        </div>
      )
    }
    
    ReactDOM.render(<Welcome />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import React from "react";
    import ReactDOM from "react-dom";
    
    class Welcome extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          list: [
            {
              title: "第一节 React事件",
              content: "实践内容",
            },
            {
              title: "第二节 React数据传递",
              content: "实践内容",
            },
            {
              title: "第三节 条件渲染",
              content: "实践内容",
            },
          ],
        };
      }
    
      render() {
        return (
          <div>
            <h1>今天的课程内容</h1>
            <ul>
              {this.state.list.map((list, i) => {
                return (
                  <li key={i}>
                    <h3>{list.title}</h3>
                    <p>{list.content}</p>
                  </li>
                );
              })}
            </ul>
          </div>
        );
      }
    }
    
    ReactDOM.render(<Welcome />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

    在使用数组的map方法对每一项数据按照jsx的形式对数据进行加工,最后得到一个每一项都是jsx形式的数组,再将数组渲染到模板中,key值需要放置到每一项中,封装成组件,key的是在组件上的:

    import React from "react";
    import ReactDOM from "react-dom";
    
    function ListItem(props) {
      return (
        <li key={props.index}>
          <h3>{props.data.title}</h3>
          <p>{props.data.content}</p>
        </li>
      );
    }
    
    class Welcome extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          list: [
            {
              title: "第一节 React事件",
              content: "实践内容",
            },
            {
              title: "第二节 React数据传递",
              content: "实践内容",
            },
            {
              title: "第三节 条件渲染",
              content: "实践内容",
            },
          ],
        };
      }
    
      render() {
        let listAtr = this.state.list.map((list, i) => {
          return <ListItem key={i} data={list} index={i}></ListItem>;
        });
        return (
          <div>
            <h1>今天的课程内容</h1>
            <ul>{listAtr}</ul>
          </div>
        );
      }
    }
    
    ReactDOM.render(<Welcome />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48

    再与事件绑定案例结合一下:

    import React from "react";
    import ReactDOM from "react-dom";
    
    class ListItem2 extends React.Component {
      constructor(props) {
        super(props);
      }
    
      clickEvent = (index, title, event) => {
        alert(index + "-" + title);
      };
    
      render() {
        return (
          <li
            onClick={(e) => this.clickEvent(
              this.props.index, 
              this.props.data.title,
              e)}
            key={this.props.index}
          >
            <h3>{this.props.data.title}</h3>
            <p>{this.props.data.content}</p>
          </li>
        );
      }
    }
    
    class Welcome extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          list: [
            {
              title: "第一节 React事件",
              content: "实践内容",
            },
            {
              title: "第二节 React数据传递",
              content: "实践内容",
            },
            {
              title: "第三节 条件渲染",
              content: "实践内容",
            },
          ],
        };
      }
    
      render() {
        let listAtr = this.state.list.map((list, i) => {
          return <ListItem2 key={i} data={list} index={i}></ListItem2>;
        });
        return (
          <div>
            <h1>今天的课程内容</h1>
            <ul>{listAtr}</ul>
          </div>
        );
      }
    }
    
    ReactDOM.render(<Welcome />, document.getElementById("root"));
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    编辑 (opens new window)
    #React
    上次更新: 2022/08/26, 15:52:02
    React入门笔记(二):JSX样式、组件初识
    React入门笔记(四):React生命周期、插槽、路由

    ← React入门笔记(二):JSX样式、组件初识 React入门笔记(四):React生命周期、插槽、路由→

    最近更新
    01
    使用Vscode开发一个小插件
    10-21
    02
    Vscode插件配置项监听
    10-18
    03
    使用has属性构造必填效果
    10-14
    更多文章>
    Theme by Vdoing | Copyright © 2020-2023 互联网ICP备案: 闽ICP备18027236号
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式