状态(state)

状态就是组件描述某种显示情况的数据,由组件自己设置和更改,也就是所组件自己维护,目的就是为了在不同状态下使组件的显示不同

在组件中只能通过getInitialState的钩子函数来给组件挂载初始状态,在组件内部通过this.state获取

this.props和this.state是纯js对象,在vue中,$data属性是利用Object.defineProperty处理过的,更改$data的数据的时候会触发数据的getter和setter,但是React中没有做这样的处理,如果直接更改的话,React是无法得知的,所以需要使用特殊的更改状态的方法

setState(params)

在setState中传入一个对象,就会将组件的状态中键值对的部分更改,还可以传入一个函数,这个回调函数必须返回像上面方式一样的一个对象,函数可以接收prevState和props

实现下拉菜单的方式

1. 通过数据来控制元素的行内样式中display

<ul style={{display:isMenuShow?'block':'none'}}><li>国内新闻</li></ul>
<ul className={isMenuShow?'show':'hide'}><li>国内新闻</li></ul>

2. 根据数据控制是否渲染该节点、组件

{
isMenuShow?<ul><li>国内新闻</li></ul>:''
}

3. 通过ref对dom、组件进行标记,在组件内部通过this.refs获取到之后,进行操作

<ul ref='content'><li>国内新闻</li></ul>this.refs.content.style.display = this.state.isMenuShow?'block':'none'

属性和状态的对比

相似点:都是纯js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)

不同点:

1. 属性能从父组件获取,状态不能

2. 属性可以有父组件修改,状态不能

3. 属性能在内部设置默认值,状态不可以

4. 属性不在组件内部修改,状态要改

5. 属性能设置子组件初始值,装填不可以

6. 属性可以修改子组件的值,状态不可以

状态只和自己相关,由自己维护

属性不要自己修改,可以从父组件获取,也可以给子组件设置

组件在运行时自己需要修改的数据其实就是状态而已

父子组件传参的交互

我们经常会令父组件将自己的某一条状态传递给子组件,这个时候,当父组件的状态更改的时候,子组件接收到的属性就会发送改变,触发render重新执行

也就是说state更改的时候(使用setState),会触发render重新执行,属性更改的时候,也能做到这一点

组件的生命周期

组件是一个构造器,每一次使用组件都相当于在实例化组件,这个时候,组件就会经历一次生命周期,从实例化实例开始到这个实例销毁的时候,都是一个完整的生命周期

组件的生命周期,我们会分为三个阶段,初始化、运行中、销毁

初始化阶段

1. 实例化组件之后,组件的getDefaultProps钩子函数会执行

这个钩子函数的目的是为组件的实例挂载默认的属性

这个钩子函数只会执行一次,也就是说,只在第一次实例化的时候执行,创建出所有实例共享的默认属性,后面再实例化的时候,不会执行getDefaultProps,直接使用已有的共享的默认属性

理论上来说,写成函数返回对象的方式,是为了防止实例共享,但是React专门为了让实例共享,只能让这个函数只执行一次

组件间共享默认属性会减少内存空间的浪费,而且也不需要担心某一个实例更改属性后其他的实例也会更改的问题,因为组件不能自己更改属性,,而且默认属性的优先级低

2. 执行getInitialState为实例挂载初始状态,且每次实例化都会执行,也就是说,每一个组件实例都拥有自己独立的状态

3. 执行componentWillMount,相当于vue里的created+beforeMount,这里是在渲染前最后一次更改数据的机会,在这里更改不会触发render的重新执行,在这里做数据的获取

4. 执行render,渲染dom

5. 执行componentDidMount,相当于vue里的mouted,多用于操作真实dom

运行中阶段

当组件mount到页面中之后,就进入了运行中阶段,在这有5个钩子函数,但这5个钩子函数只有数据(属性、状态)发生改变的时候才会执行

1. componentWillReceiveProps

当父组件给子组件传入的属性改变的时候,子组件的这个函数才会执行

当执行的时候,函数接收的第一个参数是子组件接收到的新参数,这个时候,新参数还没有同步到this.props上,多用于判断新属性和原有属性的变化后更改组件的状态

2. 接下来会执行shouldComponentUpdated,这个函数的作用

当属性或状态发送改变后控制组件是否更新,提高性能,返回true就更新,否则不更新,默认返回true

接收nextProp、nextState,根据新属性状态和原属性状态进行对比,判断后控制是否更新

3. componentWillUpdate,在这里,组件马上就要重新render了,多做一些准备工作,千万不要在这里修改状态,否则会死循环

相当于vue中的beforeUpdate

4. render,重新渲染dom,不能修改状态,会死循环

5. componentDidUpdate,在这里新的dom结构产生,不能修改状态,会死循环

销毁阶段

当组件被销毁之前,会触发componentWillUnmount

相当于vue里的beforeDestroy,所以会执行一些事件

为什么vue中有beforeDestroy,而React却没有?

vue在调用$destroy方法的时候就会执行beforeDestroy,然后组件被销毁,这个时候组件的结构还存在于页面结构中,也就是说如果想要对残留的dom结构进行处理必须在destroyed处理,但是React执行完componentWillUNmount之后吧事件、数据、dom都全部处理掉了,所以根本不需要其他的钩子函数了

怎么样就算组件被销毁:

1. 当父组件从渲染这个子组件变成不渲染这个子组件的时候,子组件相当于被销毁

2. 调用ReactDOM.unmountComponentAtNode(node)方法来将某节点中的组件销毁

react中的事件对象

React中对于事件进行了处理,解决了一些兼容性问题,React事件对象上面挂载着nativeEvent,这个就是原生的事件对象

React对事件对象做了优化,如果不取值的话,只都是null

React中组件通信方式

父组件与子组件通信

1. 父组件将自己的状态传递给子组件,子组件当做属性来接收,当父组件更改自己状态的时候,子组件接收到的属性就会发生改变

2. 父组件利用ref对子组件做标记,通过调用子组件的方法以更改子组件的状态

子组件与父组件通信

1. 父组件将自己的某个方法传递给子组件,在方法里可以做任意操作,比如可以更改状态,子组件通过this.props接收到父组件的方法后调用

兄弟组件通信

在React没有类似vue中的事件总线来解决这个问题,我们只能借助他们共同的父级组件来实现,将非父子关系转换成多维度的父子关系

复杂的非父子组件通信在React中很难处理,多组件间的数据共享也不好处理,所以我们会使用flux、redux来实现这样的功能,解决这个问题

React中表单元素默认值

在React中,如果需要给表单元素设置默认value和checked,需要设置成defaultValue/defaultChecked,否则设置默认之后,用户无法更改

React中的mixins

在vue中我们可以将一些通用的、公用的方法放入到某一个纯js对象中,然后,在需要使用该方法的组件中使用mixins配置(值为对象)将该js对象中的方法注入到组件中,这样就能实现代码复用,便于维护

在React中曾经也有这样的api,但是在高版本React中推荐我们使用es6中的class来创建组件了,这个时候无法使用mixinsapi,所以mixins被废弃了,如果要使用公用代码抽离,我们可以使用模块化

React-keys

我们在React中循环列表数据的时候,需要对循环出来的虚拟jsx节点传入key这个数据

keys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化,因此你应该给数组中的每一个元素赋予一个确定的标识

状态提升

如果有多个组件共享一个数据,把这个数据放到共同的父级组件中来管理

组合

在vue中有一个内容分发叫slot,在React中也有实现,就是可以在使用组件的时候,在组件标签内部放入一些不固定的内容,在该组件的模板中,只有{this.props.children}来表示

//App
<Dialog
close={this.ToggleDialogShow} isShow={isDialogShow}
>
<ContentA/>
<ContentA/>
<ContentB/>
</Dialog> //dialog
<div style={{display:isShow?'block':'none'}} className="dialog">
<Button handler={this.props.close} text="关闭"/> {this.props.children}//这里就是slot </div>

React学习之路(二)的更多相关文章

  1. Redis——学习之路二(初识redis服务器命令)

    上一章我们已经知道了如果启动redis服务器,现在我们来学习一下,以及如何用客户端连接服务器.接下来我们来学习一下查看操作服务器的命令. 服务器命令: 1.info——当前redis服务器信息   s ...

  2. react.js学习之路二

    看react.js对我来说真的不是难不难的问题,问题是我的思路太难转变了,真是坑死我了,react里面的坑也很多.算了,这些抱怨没啥用,记录一下今天学习的内容. 今天看了to-do-list经典示例 ...

  3. zigbee学习之路(二)点亮LED

    一.前言 今天,我来教大家如何点亮led,这也是学习开发板最基础的步骤了. 二.原理分析 cc2530芯片跟虽然是51的内核,但是它跟51单片机还是有区别的,51单片机不需要对IO口进行配置,而cc2 ...

  4. React 学习之路 (一)

    先说一说对React的体验,总结 首先react相对angular来说入手简单暴力,在学习的这段时间里发现: 我们每天做的事就是在虚拟DOM上创建元素然后在渲染到真实的DOM中 渲染到真实DOM上的R ...

  5. react学习笔记(二)编写第一个react组件

    继续上一节课的内容,打开App.js:会看到如下代码: import React, { Component } from 'react';  //在此文件中引用React,以及reat的组件类 imp ...

  6. Android开发学习之路-二维码学习

    这个月装逼有点少了,为什么呢,因为去考软件射鸡师了,快到儿童节了,赶紧写篇博纪念一下逝去的青春,唔,请忽略这句话. 二维码其实有很多种,但是我们常见的微信使用的是一种叫做QRCode的二维码,像下面这 ...

  7. Python学习之路二

    今天主要学习了列表,python的列表真的事太强大了,由于内容比较多,今天就先简单的介绍一下新学的几个成员函数吧. 首先我们要了解list是一种序列类型,其构造方式有四种形式: (1)空列表 [] ( ...

  8. React学习小结(二)

    一.组件的嵌套 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  9. Spring学习之路二——概念上理解Spring

    一.概念. Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Develop ...

随机推荐

  1. 【前端】Util.js-ES6实现的常用100多个javaScript简短函数封装合集(持续更新中)

    Util.js (持续更新中...) 项目地址: https://github.com/dragonir/Util.js 项目描述 Util.js 是对常用函数的封装,方便在实际项目中使用,主要内容包 ...

  2. sphinx+reStructuredText制作文档

    1 spinx简介 Sphinx 是一种文档工具,它可以令人轻松的撰写出清晰且优美的文档, 由 Georg Brandl 在BSD 许可证下开发. 新版的Python文档 就是由Sphinx生成的,并 ...

  3. 跟着鬼哥学so改动,二,进行篇

    图/文  听鬼哥说故事 继续上文的内容---------------------------------- 0x1:測试文件的编写 经过上一篇文章的基础学习,如今我们開始进行是用的部分. 既然我们能够 ...

  4. (转自知乎https://www.zhihu.com/question/20794107)动态代理

    作者:雨夜偷牛的人链接:https://www.zhihu.com/question/20794107/answer/23330381来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  5. 多线程day01

    多线程作为Java中很重要的一个知识点,在此还是有必要总结一下的. 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程 ...

  6. javaWeb超链接(href)请求-特殊字符处理

    写在前面: 最近在项目中,遇到一个问题,在点击一个超链接时,页面报错.通过浏览器调试就可以知道发送的请求参数是不完整的,因为参数中含有特殊字符.所以就报错啦~~ 原代码,不能正确发送含有特殊字符的参数 ...

  7. 轨迹系列——Socket总结及实现基于TCP或UDP的809协议方法

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在上一篇博客中我详细介绍了809协议的内容.809协议规范了通 ...

  8. SQLMap安装步骤

    SQLMap是利用Python语言写的,所以需要将Python这个语言环境给安装上 : 1.首先下载Python(这里Python版本为2.7.2,可以下载不同或高版本的) 2.然后在下载sqlmap ...

  9. iOS 中Block以及Blocks的使用,闭包方法调用

    OC: -(void)dataWithUrl:(NSString*)string AndId:(NSInteger)id returnName:(void(^)(NSString*name))back ...

  10. ES6/7 异步编程学习笔记

    前言 在ES6的异步函数出现之前,Js实现异步编程只有settimeout.事件监听.回调函数等几种方法 settTmeout 这种方法常用于定时器与动画的功能,因为其本质上其实是浏览器的WebAPI ...