• React小记(一)_基础部分


    1、项目搭建与结构

    2、类组件和函数组件

        主要区别:
          1、函数组件没有生命周期
          2、函数组件没有this指向
          3、函数组件没有状态
          4、函数组件通过hooks实现各种操作
          5、props在函数的第一个参数接收
          6、函数体相当于类组件的render函数
    
    
    import React from 'react'
    
    function App() {
      // 1、函数组件
      function Fn() {
        return <div>fn hello</div>
      }
    
      // 2、类组件
      class ClassHello extends React.Component{
        // 构造器可有可无
        constructor(props) {
          super(props)
        }
        // render必须有
        render() {
          return <div>class hello</div>
        }
      }
      return (
        <div className="App">
          <Fn></Fn>
          <ClassHello></ClassHello>
        </div>
      );
    }
    
    export default App;
    

    3、js与jsx语法

        1、jsx和react是相互独立的
        2、写法相似,更加简便
        3、可以和js混用
        4、最终会转化为和一个【React-element对象】
        5、不借助jsx,可以通过React.createElement创建
    

    3.1 创建DOM的两种方式

        二者最终得到的内容是一致的,均是React的element对象
    
    import React from 'react'
    
    function App() {
      function Fn() {
        // 1、React 创建Dom写法
        // React.createElement('标签名',[属性],'内容')
        return React.createElement('div',[],'hello,fn')
      }
    
      class ClassHe extends React.Component{
        constructor(props) {
          super(props)
        }
        render() {
          // 2、jsx 创建Dom写法
          return <div>hello,class</div>
        }
      }
      return (
        <div className="App">
          <Fn></Fn>
          <ClassHe></ClassHe>
        </div>
      );
    }
    
    export default App;
    

    3.2 jsx中不同类型数据的渲染.js

        1、字符串/数字 => 直接渲染
        2、对象(vue中当成字符串渲染)
            element对象 => 直接渲染 
            普通对象 => 取到每一项后可以渲染
        3、数组(普通/元素数组) => 把数组中的每一项进行渲染
        4、表达式 => 得到运行结果渲染
        5、方法 => 无法渲染
        6、布尔值 => 不渲染
        7、undefined/null => 不渲染
    
    import React from 'react'
    
    function App() {
    
      // 1、字符串
      const str = 'good !!!'
    
      // 2、数字
      const num = 123
    
      // 3、普通对象
      const obj = {
        a:1
      }
    
      // 4、element 对象
      const eleObj = <span>span</span>
    
      // 5、普通数组
      const arr = [1, 2, 3]
      
      // 6、elememt 数组
      const eleArr = [
        <p>1111</p>,
        <p>2222</p>,
        <p>3333</p>
      ]
    
      // 7、表达式
      // 如果数组的长度为3 则显示对象中的a
    
      // 8、方法 无法渲染
    
      // 9、布尔值
      const boll = false
    
      // 10、undefined / null;
      var ss 
      const na = null
    
      return (
        <div className="App">
          <span> 字符串:</span> 
          {str} <br />
          <span> 数字:</span>
          {num} <br />
          <span>普通对象:</span>
          {/* 直接取取不到,需要拿到具体的 */}
          {obj.a} <br />
          <span>元素对象:</span>
          {eleObj} <br />
          <span>普通数组:</span>
          {arr} <br />
          <span>元素数组:</span>
          {eleArr}
          <span>表达式:</span>
          {arr.length === 3 ? obj.a : ''} <br />
          <span>布尔值:</span>
          {boll} <br />
          <span>undefined:</span>
          {ss} <br />
          <span>null</span>
          {na} <br />
        </div>
      );
    }
    
    export default App;
    
    

    4、事件绑定

        1、写法类似原生 on + 方法名(首字母大写)
        2、给事件赋值为某个方法,但是不要执行 
    

    4.1 方法写在外面

    import React from 'react'
    
    class App extends React.Component{
    
    // 声明函数时 赋值语句 + 箭头函数
    handleClick = ()=> {
        console.log('点击了按钮');
    }
    render() {
        return (
        <button onClick={this.handleClick}>点我触发事件</button>
        )
    }
    }
    
    export default App;
    

    4.2 方法写在里面

    import React from 'react'
    
    class App extends React.Component{
      render() {
        return (
          <button onClick={() => {
            console.log('点击了按钮');
          }}>点我触发事件</button>
        )
      }
    }
    
    export default App;
    

    4.3 注意事项

    【特别注意】
        1、类组件想要拿到事件处理函数中this要处理 不然会undefined
            (1) 事件处理函数声明时,声明为【箭头函数+赋值语句】
            (2) 使用bind改变this指向,在需要传参时多用
            (3) 内联式写法,函数写为【匿名函数+箭头函数】
        2、给事件绑定的是一个方法,且不要直接调用
    
    1. 事件处理函数声明时,声明为【箭头函数+赋值语句】
    import React from 'react'
    
    class App extends React.Component{
    
    // 声明函数时 赋值语句 + 箭头函数
    handleClick = ()=> {
        console.log(this);  // App
    }
    render() {
        return (
        <button onClick={this.handleClick()}>点我触发事件</button>
        )
    }
    }
    
    export default App;
    
    1. 使用bind改变this指向,在需要传参时多用
    import React from 'react'
    
    class App extends React.Component{
      
      // 2、使用bind在模板中改变this指向,传参时多用
      handleClick(a){
        console.log(this,a);  // App 传参
      }
      render() {
        return (
          <button onClick={this.handleClick.bind(this,'传参')}>点我触发事件</button>
        )
      }
    }
    
    export default App;
    
    1. 内联式写法,函数写为【匿名函数+箭头函数】
    import React from 'react'
    
    class App extends React.Component{
      
      // 3、内联 【匿名函数 + 箭头函数】
      render() {
        return (
          <button onClick={() => {
            console.log(this);  // App
          }}>点我触发事件</button>
        )
      }
    }
    
    export default App;
    

    4.4 事件绑定其他操作

        1、传递参数 :bind(this,'参数')
        2、获取事件对象 e
        3、阻止默认行为、冒泡等
    
    import React from 'react'
    
    class App extends React.Component {
    
      // 声明函数时 赋值语句 + 箭头函数
      handleClick = (a,b,e) => {
        console.log('接收参数', a, b);  
        // 不传参 第一个参数
        // 传参 最后一个参数
        console.log('合成事件对象', e);
        console.log('原生事件对象', e.nativeEvent);
        e.stopPropagation();   // 阻止冒泡
        e.preventDefault();    // 阻止默认行为
      }
      render() {
        return (
          <button onClick={this.handleClick.bind(this,1,2)}>点我触发事件</button>
        )
      }
    }
    export default App;
    

    5、响应式数据(类组件)

        1、react不能像vue一样【直接修改】触发更新
        2、react直接修改能修改值,无法触发更新
        3、react没有像vue的get和set监听,借助【setState】触发更新
    

    5.1 setState的本质

        1、修改数据
        2、触发更新
    
        以下两种写法是等价的
        add = () => {
            this.setState({
                a:++this.state.a
            })
        }
    
        add = () => {
            this.state.a += 1
            this.setState({})
        }
    

    5.2 setState 获取最新值

        1、setState 修改值是异步操作
        2、获取最新值要在setStete第二个参数【回调函数】中获取
    
        this.setState({
            // 在这修改值
          a:++this.state.a
        }, () => {
            // 在这拿到最新的值
          console.log('拿到a最新的值',this.state.a);
        })
    

    5.3 setState 细节

        1、setState传递对象,通过浅合并(Object.assign),并非替换
        2、由于浅合并,深层次的修改需要先赋值一份
    
    import React from 'react'
    
    class App extends React.Component {
    
      // 1、声明状态
      state = {
        a: 0,
        b: 1,
        c: {
          c1: 2,
          c2: 3
        }
      }
    
      // 2、修改状态
      add = () => {
        this.setState({
          a: ++this.state.a,
          c: {
            // 由于浅合并,深层次的修改需要先赋值一份
            ...this.state.c,
            c2:4
          }
        }, () => {
          console.log('拿到a最新的值',this.state.a);
        })
      }
      render() {
        return <div>
          <span>获取状态:</span>
          {this.state.a} <br />
          <span>c2的值:</span>
          {this.state.c.c2} <br />
          <span>修改状态:</span>
          <button onClick={this.add}>点我修改</button> <br />
        </div>
      }
    }
    
    export default App;
    

    5.4 setState的一些特性

        1、多次修改数据,会合并为一次,最后触发更新
        2、setState每次调用都会触发更新(无论数据是否修改)
            借助 PureComponent 优化类组件
                a、数据不变,组件不刷新
                b、当修改对象和数组时,要先解除引用,否则不更新
        3、不要再render中调用setState
    
    // 修改arr [页面不变-因为地址不变]
      addArr1 = () => {
        this.state.arr.push(4)
        this.setState({
          arr:this.state.arr
        }, () => {
          console.log(this.state.arr);
        })
      }
    
      // 先解除引用 再修改
      addArr = () => {
        let arr_ = [...this.state.arr]
        arr_.push(4)
        this.setState({
          arr: arr_
        }, () => {
          console.log(this.state.arr);
        })
      }
    

    6、条件渲染

        1、利用js编写自定义逻辑
        2、根据逻辑(true/false)渲染相应的内容
        3、主要方式
            (1) 三元表达式
            (2) && ||
            (3) if else
    
    import React from 'react'
    
    class App extends React.PureComponent {
    
      state = {
        show: true,
        isHot:true
      }
    
      fn = () => {
        if (this.state.show) {
          return <span>if</span>
        } else {
          return <span>else</span>
        }
      }
    
      handleClick = () => {
        this.setState({
          show: !this.state.show,
          isHot:!this.state.isHot
        })
      }
      render() {
        return <div>
          <h3>条件渲染</h3>
          {/* 1、三元表达式 */}
          {this.state.show ? '显示' : '隐藏'} <br />
          {/* 2、&&  ‘true才执行’ */}
          {this.state.isHot && '天气很热'} <br />
          {/* 3、if else */}
          {this.fn()} <br />
          <button onClick={this.handleClick}>点我切换</button>
        </div>
      }
    }
    
    export default App;
    

    7、列表渲染

        1、使用数组遍历方法 将后端返回的数组中每一项取出来渲染成jsx
            (1) 拿到原始数据:后端数据
            (2) 将每一项数据转化为DOM元素
            (3) jsx 渲染
        2、常用方法
            (1) map 有返回值
            (2) forEach 没有返回值
            (3) filter 过滤
    
    import React from 'react'
    
    class App extends React.PureComponent {
    
      state = {
        arr: [1, 2, 3],
        eleArr: [
          <div>1</div>,
          <div>2</div>,
          <div>3</div>,
        ]
      }
    
      getArr = () => {
        let newArr = []
        this.state.arr.forEach(item => {
          newArr.push(<p key={item}>{ item}</p>)
        })
        return newArr
      }
    
      render() {
        return <div>
          <h3>列表渲染</h3>
          {this.state.arr} <br />
          {this.state.eleArr}
          <hr />
          {/* 1、使用map */}
          {
            this.state.arr.map(item => (
              <h3 key={item}>{ item }</h3>
            ))
          }
          <hr />
          {/* 2、使用forEach */}
          {this.getArr()}
        </div>
      }
    }
    
    export default App;
    

    8、样式操作

        1、class类名设置
            (1) 必须写成 className
            (2) 样式单独写在一个css文件中
                如果不做处理,样式会全局生效(产生样式污染)
            (3) 只能接受一个字符串 '' {}
        2、style内联写法
            不能像原生一样写成字符串'',必须写成对象 {{ }}
        3、解决样式污染
            (1) 改名 将 .css => .module.css
            (2) 将样式文件引入为对象 import sonStyle from ''
            (3)【sonStyle.son】/【sonStyle['son']】取出类名使用
        4、动态控制类名
            引入状态,根据状态使用条件渲染出切换类名(拼接字符串)
            (1) 手动拼接字符串(少量)
            (2) 借助 classnames 拼接
                a、帮助我们生成计算好的类名的字符串
    

    8.1 手动拼接字符串

    import React from 'react'
    import './App.css'
    
    class App extends React.PureComponent {
    
      state = {
        isShow : true
      }
      
      handle = () => {
        this.setState({
          isShow:!this.state.isShow
        })
      }
      render() {
        return (
          <div className="App">
            {/* 手动拼接 */}
            <span className={ this.state.isShow ? 'color' :''}> 动态添加类名</span> <br />
            <button onClick={this.handle}>点我切换</button>
          </div>
        )
      }
    }
    
    export default App;
    

    8.2 借助 classnames 拼接

    import React from 'react'
    import classnames from'classnames'
    import style from'./App.module.css'
    
    class App extends React.PureComponent {
    
      state = {
        isShow : true
      }
      
      handle = () => {
        this.setState({
          isShow:!this.state.isShow
        })
      }
      render() {
        return (
          <div className={style.App}>
            {/* 借助classnames拼接 */}
              <span className={classnames({
                {/* 不需要改变this指向 */}
                [style['color']]:this.state.isShow
              })}> 动态添加类名</span> <br />
              <button onClick={this.handle}>点我切换</button>
          </div>
        )
      }
    }
    
    export default App;
    

    9、受控组件和非受控组件

      回想原生:
        1、获取表单的值   onInput={this.handleClick}
          a、绑定监听事件 input/change
          b、通过【e.target.value】获取
        2、设置表单的值   value={this.state.inputValue}
          设置value/checke属性
    
    import React from 'react'
    
    class App extends React.PureComponent {
    
      state = {
        inputValue:''
      }
      handleClick = (e) => {
        this.setState({
          inputValue: e.target.value
        })
      }
      
      change = () => {
        this.setState({
          inputValue: 11
        })
      }
      render() {
        return (
          <div>
            <input value={this.state.inputValue} onInput={this.handleClick} />
            <span> {this.state.inputValue}</span> <br />
            <button onClick={this.change}>变更inputValue</button>
          </div>
        )
      }
    }
    
    export default App;
    

    9.1 受控组件(双向的)

        1、表单的值可以获取【state】,并可以由开发者靠代码【setState】去更改
        2、可以通过设置state中的值改变表单中的值
        3、将表单数据添加到state中,可以通过【state/setState】对数据进行获取和修改
    

    9.2 受控组件(无状态的)

        1、表单的值我们只能获取【通过给输入框打标识获取】
        2、我们仅做了事件监听,没有设置 value/checked 属性
        3、没有设置 state
    

    9.3 关于复选框

        1、 value  选中后的值
        2、checked 控制是否选中
    
  • 相关阅读:
    SSH Tunneling隧道 - 探究与实践
    [django框架2]ORM进阶知识
    ABAP 采购组 条目 Z001 不存在T161内-请检查输入
    pycharm插件translation 更新TTK失败,请检查网络连接的解决办法
    java多线程保证顺序执行
    Elasticsearch
    怎么在VM虚拟机中安装kali linux系统?
    站长号词库:今日热门长尾关键词挖掘 20221201
    列主高斯消元法
    Git拉取远程仓库代码与本地分支代码相关流程
  • 原文地址:https://blog.csdn.net/weixin_61791370/article/details/139669846