React(0x02)-react进阶

React进阶

PropTypes类型检查

PropTypes和DefaultProps主要用于子组件中对父组件传入的数据进行类型检查

使用:

//TodoItem是该组件的组件名

import PropTypes from 'prop-types'

TodoItem.propTypes = {   //规定父组件传入数据的数据类型
  text : PropTypes.string.isRequired,  //强制该属性必须传
  content : PropTypes.oneOfType([PropTypes.number,PropTypes.string]),//传入数据类型可以是多个
  itemDel : PropTypes.func,
  index : PropTypes.number
}

TodoItem.defaultProps = {   //为属性设置默认值,当父组件没有给该属性传值时则默认显示这里设置的值
  text: 'hello word'
}

React响应式

页面刷新(执行render函数)的几种情况:

  • propsstate的数据发生变化时,render函数就会再次执行,从而实现页面的实时刷新
  • 当父组件的render函数刷新时,子组件的render函数也会刷新,实现页面实时刷新

React虚拟DOM

响应式渲染流程:

  1. state数据

  2. JSX模版

  3. 数据+模版结合生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)(损耗了性能)

    ['div', {id: 'abc'}, ['span' { 'hello world']]
    
  4. 用虚拟DOM的结构生成真实的DOM,界面显示

     <div id='abc'><span>hello world</span></div>
    
  5. state发生变化

  6. 数据+模版生成新的虚拟DOM(极大的提升了性能)

    ['div', {id: 'abc'}, ['span' { 'bye bye']]
    
  7. 比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中内容(极大的提升性能)

  8. 直接操作DOM,改变span中的内容

虚拟DOM相对于真实DOM渲染的优势:

  1. 虚拟DOM是JS对象,新虚拟DOM和原虚拟DOM对比时,JS对象对比相较于真实DOM对比消耗的性能要小得多。
  2. 数据更新后不是用新DOM完全替换原DOM,而是先对比新DOM和原DOM,只修改有变化的部分,从而消耗的性能更小。

JSX-->真实DOM:

JSX-->React.createElement-->虚拟DOM(JS对象)-->真实DOM

虚拟DOM的优势:

  1. 性能提升了(相对真实DOM渲染的两个优势)
  2. 可以实现跨端应用
    • web端:虚拟DOM可以生成真实DOM
    • 移动端:虚拟DOM可以生成原生组件

setState()异步处理

React中的setState()是异步函数

  • 支持回调
this.setState(() => {
    return {
    
    }
}, () => {
    //回调内容
})
  • 异步处理容易引起的问题
    • 在数据更新,页面刷新后需要重新获取DOM,此时需要在setState()的回调函数中执行获取DOM的操作,否则获取的结果是上次的DOM而不是这次更新后的结果
    • 原因:因为setState()是异步的,程序会先执行获取DOM的操作,再执行setState()跟新数据,刷新页面
    • 解决方案:将获取DOM的操作写在setState()的回调函数中。

ref的使用

ref可以直接取到DOM中的元素,对该元素进行操作

  • 在元素(也可以是自定义组件)上绑定ref

    <input  ref = {(input) => {this.input = input}} />
    
  • js中获取该元素并操作

    //通过this.input既可以取到input元素
    const value = this.input.value    //取到input元素的值
    

组件

1 UI组件和容器组件

  • UI组件: 只有render()函数,只负责页面的渲染

  • 容器组件:负责页面逻辑

  • 一个UI组件和一个容器组件配合完成一个页面

  • UI组件与容器组件的通信

    • 通信方式和普通的组件之间通信一样
    //容器组件 
    import React, {Component} from 'react'
    import TodoListUI from './TodoListUI'
    import './TodoList.css'
    
    class TodoList extends Component {
      constructor(props) { 
        super(props)        
        this.state = {
           inputValue = '' 
        }
        this.changeInputValue = this.changeInputValue.bind(this) 
      }
    
      render() {          
        return (         
          <TodoListUI
            inputValue = {this.state.inputValue}          //向UI组件传数据
            changeInputValue = {this.changeInputValue}}/> //向UI组件传函数
        )
      }
    
      changeInputValue(){
          ......
      }
    }
    
    export default TodoList;
    
    
    
    //UI 组件
    import React, {Component, Fragment} from 'react'
    
    class TodoListUI extends Component {
      render() {
        return (
              <Input  value = {this.props.inputValue}             //容器组件传入的数据
                      onChange = {this.props.changeInputValue}/>  //容器组件传入的函数 
        )
      }
    }
    
    export default TodoListUI
    

2 无状态组件

  • 无状态组件: 函数式的组件,只有render()函数的UI组件一般会写成无状态组件

    • 函数式组件就是定义方式是函数而不是类
    • 函数定义的组件性能更高,因为没有了周期函数,减少了性能的消耗
  • UI组件改为无状态组件的前后对比

    //UI 组件
    import React, {Component, Fragment} from 'react'
    
    class TodoListUI extends Component {
      render() {
        return (
              <Input  value = {this.props.inputValue}             //容器组件传入的数据
                      onChange = {this.props.changeInputValue}/>  //容器组件传入的函数 
        )
      }
    }
    
    export default TodoListUI
    
    //改进后的无状态组件
    import React, {Fragment} from 'react'
    
    const TodoListUI = (props) => {
      return (
            <Input  value = {props.inputValue}             //容器组件传入的数据
                    onChange = {props.changeInputValue}/>  //容器组件传入的函数 
      )
    }
    
    export default TodoListUI
    

React生命周期

1 生命周期函数执行顺序

1593932477034.png
  1. Initialization : 组件初始化阶段
  • constructor()
    • 在组件创建时执行
  1. Mounting : 组件页面挂载阶段
  • componentWillMount()
    • 在页面挂载之前执行,只会执行一次,后续render()执行刷新时不再执行该函数
  • render()
    • 挂载到页面,刷新页面时执行
  • componentDidMount()
    • 页面挂载完成时执行,只会执行一次,后续render()执行刷新时不再执行该函数
  1. Updation : 组件页面刷新阶段
1593934878734.png
  • componentWillReceiveProps()
    • 接收了父组件传入的参数且父组件的render函数再次执行刷新传入的参数时,该函数会被执行
    • props的数据改变是回执行
  • shouldComponentUpdate()
    • 页面刷新之前执行
    • 必须返回true或false 返回true则后去更新继续 , 返回false则不再执行后续更新
  • componentWillUpdate()
    • shouldComponentUpdate之后,页面刷新之前执行
  • render()
    • 页面刷新时执行
  • componentDidUpdate()
    • 页面更新完成后执行
  1. Unmounting : 组件移除阶段
  • componentWillUnmount()
    • 组件在页面中移除时执行

2 shouldComponentUpdate()的使用场景

  • render函数执行的条件之一是父组件render函数执行

  • 场景:

    • 父组件有数据A、数据B
    • 子组件接收了父组件的数据A
    • 当父组件数据A变化时,父组件的render函数会执行,子组件的render函数也会执行并刷新页面,这是正常的情况
    • 当父组件数据B变化时,父组件的render函数会执行,子组件的render函数也会执行并刷新页面,但此时子组件是不需要刷新的,这就导致了性能的损耗。
  • 解决方案:

    • 在子组件shouldComponentUpdate()函数中判断数据A是否变化,若没有变化则返回false,后续刷新就不会再执行了。
    • 当当父组件数据B变化时,子组件判断数据A没有变化,则不会执行后续刷新,从而避免了性能损耗。
    //nextProps,nextState 可以拿到修改后的数据
    shouldComponentUpdate(nextProps, nextState) {
        if(nextProps.A !== this.props.A){   //修改后的数据和以前的数据比对,看时候有变化
          return true
        }else{
          return false
        }
      }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335