zoukankan      html  css  js  c++  java
  • react-5-从jsx到类组件的生命周期

    react 笔记

    jsx中绑定this

    为什么this会是undefined ?

    1. 可以使用bind方式绑定this

    <button onClick={this.sayHi.bind(this)}>{this.state.btnDes}</button>

    1. 可以使用箭头函数方式绑定this

    <button onClick={() => this.sayHi()}>{this.state.btnDes2}</button>

    jsx中的列表渲染

    一般的,都是使用map进行列表渲染,同时返回一个jsx-dom

        <ul>
              {/* 在这里,一般用map来进行列表渲染 */}
              {
                this.state.movies.map((item, index) => <li onClick={() => this.getItme(item)} key={index}>{item}</li>)
              }
        </ul>
    

    计数器案例

    1. setState的函数形式:

    传递一个函数可以让你在函数内访问到当前的 state 的值。因为 setState 的调用是分批的,所以你可以链式地进行更新,并确保它们是一个建立在另一个之上的,这样才不会发生冲突

     this.setState((pre, next) => {
          console.log(pre, next);
          return {
            val: data
          }
        })
    

    几点提示

    pre : state更改前的上一次状态
    next : state更改后的状态
    函数式必须要return一个对象,分别对应state内的键值对

    1. 绑定属性

    绑定属性类似原生小程序,如
    <input onChange={(e) => { this.changeVal(e) }} value={this.state.val ? this.state.val : 0} />

    1. react并没有双向绑定,因而要使用e事件对象来找到值

    2. 关于num++ 与num+1
      要使用num+1

    在使用setState的时候不能使用num++,否则会导致修改失败 ,并且在事件触发时state也只会保持原值

    JSX语法

    描述:jsx是js的拓展语法,想要使用jsx ,需要给script标签中添加 type="text/babel"属性

    1. jsx规范
    2. jsx顶部只允许有一个根元素,即便是空标签也可以
    3. jsx外层包裹一个小括号,一来方便阅读,二来可以换行书写
      3.jsx中的标签可以是单标签,也可以是双标签,但如果是单标签,需要/>结尾,如<img />, <div />
    4. jsx注释

    通常使用{/* 这里是注释 */}来表示,在jsx上下文环境下,ctrl+/可以自动生成注释行

    1. jsx嵌入变量
      *. jsx中可以正常显示这些类型: string,number,array
      *. jsx中一般不能渲染以下数据类型(会显示dom,但不会显示dom的内容)

      1. null undefined

      如果必须要让null,undefined显示,可以使用String(null/undefined)的方式,也可以直接让其加''

      2.boolean

      如果必须要对bool显示,可以使用bool.tostring()方法变成字符串

      1. obj

      对象不能作为jsx的子类 =》 不允许直接在jsx中渲染obj本身,但可以渲染obj内部的key-value

    jsx嵌入运算符

    在render函数内,可以使用解构的方式将state内的数据拿出来

    render() {
      const {cannotShow1,cannotShow2} = this.state
      return(
        <div>
          <p>render本质上是一个函数,只不过return了一个特殊的对象<p/>
        </div>
      )
    }
    

    jsx可以嵌入以下:

    1. 表达式

    {fN + lN}

    1. 数学程式
    2. 三目运算
    3. 逻辑与
    4. 函数调用

    如果是函数调用,则可以有vue-filter/computed(?有吗 有待考证)

    jsx绑定属性

    1. 一般的可以直接使用
    <p title={'这是' + '绑定属性'}> </p>
    
    1. 但有的会与js本身的关键字/保留字冲突,此时要自主更换,遵循jsx规约
      如:
      class => className
      for => htmlFor
    jsx绑定class(重点)

    jsx下的class要用className替代,想要绑定className样式,需要使用大括号语法

    元素普通的class名,用引号包裹即可

    <span className='hehehe'>这里是普通class</span>

    被绑定了class的元素,外部需要用大括号,这个大括号是jsx语法,普通class与三木运算class需要保留间隔

    <span className={'hhh jjj ' + (isTrue ? 'istrue' : '')}>绑定class时,外部包裹大括号,因为class也是属性</span>

    jsx绑定style(重点)

    style属性必须是一个对象格式,当key是两个字符时,遵循小驼峰格式,value不加引号时会被认为是一个变量
    <span style={{ border: '1px solid red', background: 'red' ,}}>绑定style</span>

    jsx绑定事件

    jsx绑定事件,事件名 依旧要使用小驼峰标识

    jsx如果不绑定this的话,将不能找到类组件本身的constructor里的state(提示state of undefined),

    想要找到正确的this值,需要绑定this,有以下三种方法

    1. jsx中显式绑定this
      <div onClick={this.sayHi.bind(this)}></div>

    缺陷,易导致冗余代码产生

    1. 构造器内,super下绑定this
    constructor(props){
      super(props)
      {/*本质上是给原来的函数事先绑定后this,然后又重新赋值给这个函数 
          在之前比较常用
      */}
      this.sayHi = this.sayHi.bind(this)
    }   
    
    1. jsx中给dom绑定事件时使用箭头函数
    <div onClick={() => this.sayHi()}>11111</div>
    

    请注意:箭头函数下,内部函数必须要加小括号表示执行!

    1. 声明函数时,不再声明普通函数,而是声明箭头函数

    原因:箭头函数在声明时无法绑定this,因而自动一层层向上寻找值(隐式),这种本质上是使用es6中给类添加属性的方法 class fileds

     //外部触发的函数在声明时使用箭头函数
    
     sayHi = () => {
       console.log(this.state.isTrue)
     }
    
     <div onClick={this.sayHi}>11111</div>
    
    jsx什么时候写大括号?

    大括号里写什么 取决于你希望在这个大括号里返回什么

    条件判断

    react逻辑判断遵循js原生逻辑
    *一: 如果逻辑很多,可以使用if判断,
    *二: 如果逻辑很少,可以使用三目运算符判断,
    *三: 三木运算符与&&逻辑与, v-if / v-show
    *四: 本质上是&&逻辑与完成了与v-if相同的效果,即在dom中先删除再生成
    *五: 想要完成v-show,可以操作style的display属性

    map与filter的组合渲染
    1. 过滤再截取

    很多时候只希望渲染符合条件的所有list,因而可以先使用filter再使用map的方式

    {/*
    先使用filter过滤不符合条件的,此时该数组内只剩下符合条件的,然后再使用map渲染列表
    */}
    <ul>
              {
                numArr.filter(item => item > 90)
                  .map(v => <li>{v}</li>)
              }
    
    </ul>
    

    2.过滤截取再渲染

    <ul>
              {
                numArr.filter(item => (item > 30) && (item < 100))
                  .slice(0, 4)
                  .map(v => <li>{v}</li>)
              }
    
    </ul>
    

    总结:jsx允许在map渲染前对原数组进行任何js允许的操作

    jsx源码

    1. jsx的本质
      在普通script标签中无法写jsx的原因是,jsx最终要经过ReactDOM.createElement()将其编译成语法糖
      ReactDOM.createElement(type,config,children)

    传入三个参数:
    *. type: 当前ReactElement传入的类型
    如果是元素标签,那么就用字符串表示'div'
    如果是组件标签,那么就直接使用组件名称
    *. 当前ReactEle的属性以及事件,以键值对对象的方式进行存储
    *. children
    存放在ReactEle中的内容,以children数组的方式进行存储
    如果有多个子元素,需要用babel进行转换

    问题:为什么参数第三个属性是一个参数并且不是一个可变参数,但是编译后却并不报错?

    使用auguments来对后面的参数进行一一匹配:
    const sonArr = auguments.length - 2 //减去2的原因是减去精准匹配参数1,精准匹配参数2

    通过createElement()最终生成了一颗js dom树,这棵树(js对象)就是虚拟dom树 React.render负责将这颗dom树映射到指定的真实dom节点上,从而将虚拟dom树变成了真实dom树结构(浏览器中),RN中其实都相同,只是没有渲染真实dom,而是渲染成了安卓、ios的原生控件,taro?
    流程:jsx => createElement(jsx) => render(createElement(jsx),DOM) = > 真实dom
    render.dom将虚拟dom与真实dom一一映射,这个叫做映射

    为什么要使用虚拟dom
    1. 很难追踪状态发生的改变
    2. 操作真实dom性能较低

      dom操作会引起浏览器的回流和重绘
      设计原则: 元数据的不可变性,【1.只允许使用setstatus修改数据,2.尽量生成新数据而不修改元数据(如果是引用类型,可以进行浅拷贝,然后再赋值进去)】

    以render函数为界:
    功能函数一般放在render函数后面
    组件函数放在render前面

    react-cli 中package.json的版本区别

     "dayjs": "^1.10.5" 
    

    1.10.5:表示目标库始终使用这个版本
    ^1.10.5:表示小版本更新【"5"可变】

    弊端:小版本更新也可能造成版本之间误差,yarn.lock文件表示安装的具体详细版本

    yarn eject的作用

    暴露react-cli的webpack配置,但这是不可逆的
    执行后会暴露config目录和script目录
    执行后package.json会暴露react内部的一些依赖库
    执行后package.json的script每一项的value会发生变化:

    // 之前是这样
      "start": "react-scripts start --open",
      "build": "react-scripts build",
      "test": "react-scripts test",
      "eject": "react-scripts eject"
    
    // 现在是这样  script目录:执行eject后暴露出的目录
      "start": "node script/start.js --open",
      "build": "node script/build.js",
      "test": "node script/test.js",
    

    修改src源代码会直接热更新,修改config目录、script目录时需要重新运行

    vscode自动补全jsx插件

    htmltagwrap

    react组件的类型

    1. 根据组件的定义方式 分为 函数式组件与类组件
    2. 根据组件内部是否需要维护,分为无状态组件与有状态组件
    3. 根据组件的不同职责,可以分为展示型组件和容器型组件

    以上定义方式有很多重叠,但主要都关注数据逻辑与ui展示的分离

    1. 函数组件,无状态组件,展示型组件主要关注UI的展示
    2. 类组件,有状态组件,容器型组件主要关注数据逻辑

    jsx中标签规范

    普通标签不允许大写,jsx会认为是未定义的组件

    组件规约

    1. 凡是组件必须大写字符开头
    2. 类组件需要继承React.Component(16.3后可直接继承Component)
    类组件
    1. constructor是可选的,通常在内部初始化数据(this指向,定义组件变量,接收父组件数据)
    2. constructor中的this.state用于初始化组件内部需要的数据(es7中,可以在constructor外部使用state={xx:xxx}达到相同结果)
    3. render是类组件中唯一需要实现的方法

    函数式组件

    1. 没有内部状态
    2. 没有this对象

    render函数的返回值

    不管是函数式组件还是render函数

    1. react元素

    2. 数组或者fragments:=》 使得render方法可以返回多个元素

    不允许返回对象!

    插件快捷键~ ES7 React/Redux/React-Native/JS snippets

    1. rcc => 生成类组件
    2. rfc => 生成函数式组件
    3. imd => 从库中全部导入
    4. imn => 导入库(如css)
    5. imd => 从库中导入某个变量函数
    6. cp => 从props中解构
    7. cs => 从status中解构
    8. clo => console.log(obj,obj) //obj此时被选中
    9. imr→ import React from 'react'
    10. imrc => import React,{Component} from 'react'

    多退少补

    生命周期

    人或物从诞生到消亡的整个过程

    react的生命周期分为三种:

    1. mount: 组件初次被渲染的阶段(mounting)

    constructor :

    comoponentDidmount:

    1. updata: 组件数据更新,重新更新渲染的阶段updating

    render: 接收props或者setstatus或者强制刷新dom时都会重新调用render函数

    componentDidUpdate

    1. unmount:组件从dom树中被移除的阶段unmounting

    componentWillUnmount

    执行顺序 =》 constructor => render => react内部开始更新或挂载组件 =》 componentDidmount/componentDidUpdate

    类组件版父子组件

    import { Component } from 'react'
    class Son extends Component {
      constructor(props) {
        super(props)
        this.state = {}
      }
      render() {
        return (
          <div>
            <p>我是子组件</p>
          </div>
        )
      }
    }
    class App extends Component {
      constructor(prop) {
        super(prop)
        this.state = {
        }
      }
      render() {
        return (
          <div>
            <p>这是父组件</p>
            <Son />
          </ div>
        )
      }
    }
    export default App
    

    在一个大组件文件里,一个小组件可以定义在这个组件里,然后直接导入大组件内部即可,请注意: 必须保证是纯函数!

    纯函数:在输入时就能保证输出的数据类型和值,且无副作用

    待续。

    作者:致爱丽丝
    本文版权归作者和博客园共有,欢迎转载,但必须在文章页面给出原文链接并标名原文作者,否则保留追究法律责任的权利。
  • 相关阅读:
    《大道至简》读后感
    PowerBuilder学习笔记之1开发环境
    PowerBuilder学习笔记之14用户自定义对象
    查询数据库大小的代码
    JAVA基础_修饰符
    SQLSERVER查询存储过程内容
    Asp.Net WebAPI中Filter过滤器的使用以及执行顺序
    运算符
    判断(if)语句
    变量的命名
  • 原文地址:https://www.cnblogs.com/hjk1124/p/14990824.html
Copyright © 2011-2022 走看看