React.js 初级入门学习, 你学废了吗?

文章目录

  • React.js 初级入门学习, 你学废了吗?
    • React 简介
    • React学习路线
    • React与Vue的对比
      • 组件化方面
      • 开发团队方面
      • 更多对比
    • 为什么要用React
    • React 特点
    • React中的核心概念
      • 虚拟DOM (Virtual DOM)
        • 什么是DOM?
        • 什么是VituralDOM?
        • 为什么需要VituralDOM?
        • 简单总结虚拟DOM(Vitural DOM)的处理方式
        • 简单总结虚拟DOM
      • Diff算法
      • 了解更多
    • React 入门
      • 环境准备
        • 搭建本地开发环境
        • 开发者工具
      • Hello React
      • createElement()的问题
      • JSX 的基本使用
      • JSX的注意点
      • React组件
        • React创建组件的两种方式
        • 函数式组件 和 class 组件的使用场景
        • 给组件传递数据
        • 封装组件到独立的文件中
        • props和state
          • props
          • state
        • 组件的生命周期
        • 组件生命周期函数总览
          • 组件生命周期 - 创建阶段(Mounting)
          • 组件生命周期 - 运行阶段(Updating)
          • 组件生命周期 - 卸载阶段(Unmounting)
          • 了解更多
        • state和setState
        • 组件绑定事件
          • 事件绑定中的this
            • 通过bind绑定
            • 通过箭头函数绑定
      • 条件渲染
      • 列表 & Key
      • 受控组件
    • 学习参考

React.js 初级入门学习, 你学废了吗?

React 简介

React 起源于Facebook的内部项目,因为该公司对市场上所有JavaScript MVC框架,都不满意,就决定自己写一套,用来架设Instagram(照片交友)的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

由于React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来Web开发的主流工具。

React学习路线

React 学习路线图

react-developer-roadmap

React与Vue的对比

组件化方面

  1. 什么模块化:是从代码的角度来进行分析的;把一些可复用的代码,抽离为单个的模块;便于项目的维护和开发
  2. 什么是组件化:是从UI界面的角度来进行分析的;把一些可复用的UI元素,抽离为单独的组件;便于项目的维护和开发;
  3. 组件化的好处:随着项目规模的增大,手里的组件越来越多;很方便就能把现有的组件,拼接为一个完整的页面;
  4. Vue是如何实现组件化的:通过.vue文件,来创建对应的组件
  • template 结构
  • script 行为
  • style 样式

React.js 初级入门学习, 你学废了吗?_第1张图片

  1. React如何实现组件化:
    React中有组件化的概念,但是并没有像vue这样的组件模板文件;React中,一切都是以JS来表现的

开发团队方面

  • React是由Facebook前端官方团队进行维护和更新的;因此,React的维护开发团队,技术实力比较雄厚;
  • Vue:第一版,主要是有作者尤雨溪专门进行维护的,当Vue更新到2.x版本后,也有了一个以尤雨溪为主导的开源小团队,进行相关的开发和维护;

更多对比

参考:vue还是react?小孩子才做选择题!

为什么要用React

  1. 使用组件化开发方式,符合现代Web开发的趋势
  2. 技术成熟,社区完善,配件齐全,适用于大型Web项目(生态系统健全)
  3. 由Facebook专门的团队维护,技术支持可靠
  4. 使用方式简单,性能非常高,支持服务端渲染

React 特点

  1. 声明式设计 −React采用声明范式,可以轻松描述应用。
  2. 高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
  3. 灵活 −React可以与已知的库或框架很好地配合。
  4. JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
  5. 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  6. 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

React中的核心概念

  1. 虚拟DOM(Virtual DOM)
  2. Diff算法(虚拟DOM的加速器,提升React性能的法宝)

虚拟DOM (Virtual DOM)

什么是DOM?

DOM (Document Object Model) 译为文档对象模型,是浏览器中的概念,通过JS对象来表示页面上的元素,并提供了操作DOM对象的APl

HTML DOM 树形结构如下:

React.js 初级入门学习, 你学废了吗?_第2张图片

什么是VituralDOM?

用JS对象结构表示 DOM 树的结构

为什么需要VituralDOM?

既然有了DOM 为啥还需要VituralDOM?

为了实现页面DOM元素的高效更新

举例:比如我们要实现对日期的排序。

React.js 初级入门学习, 你学废了吗?_第3张图片

  1. 表格中的数据通过请求后台加载到前台浏览器内存中,构成一个对象数组
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄'
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄'
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1516 弄'
        }
  1. 点击按钮之后需要对内存中的对象数组进行排序,然后输出到HTML中

  2. 如何将排序后的数组渲染到页面上?

    • for循环数组,拼接标签,拼接成一个字符串,然后替换掉原先的HTML页面的
      标签内的内容
    • 使用模板引擎 比如ejs, 使用for标签实现,其本质上也是拼接成字符串,只是模板引擎帮我们完成了这些的工作。
    • 上面的方式是否存在性能问题?如何才能做到最优的性能?

      • 按需更新,只重新渲染更新的数据所对应的页面元素
    • 如何做到按需更新?

      • 获取内存中的新旧两棵DOM树,进行对比,得到需要被按需更新的DOM元素:
      • 一个网页渲染的过程:
        1. 浏览器请求服务器获取页面HTML代码
        2. 浏览器要现在内存中,解析DOM结构,并在存览器内存中,渲染出一棵DOM树
        3. 浏览器把DOM树,呈现到页面上
      • 所以我们需要先获取内存的新旧DOM树,比较之后按需更新,最后在把内存中最新的DOM树渲染到页面上。
    • 如何获取内存中的新旧两棵DOM树?

      • 浏览器没有提供API去获取浏览器内存中的DOM新旧DOM树。
      • 真正的 DOM 元素非常庞大,这是因为标准就是这么设计的。而且操作它们的时候你要小心翼翼,轻微的触碰可能就会导致页面重排,这可是杀死性能的罪魁祸首
        React.js 初级入门学习, 你学废了吗?_第4张图片
    • 如何解决上述的问题,如何比较新旧两棵DOM树?

      • 聪明的程序员想到了可以通过手工模拟的方式去模拟DOM结构–> 虚拟DOM
    • 如何模拟DOM树结构?

      • 我们知道通过HTML能描述一个DOM树,除了HTML标签的方式还可以使用什么方式去模拟?—> js对象的方式。相对于 DOM 对象,原生的 JavaScript 对象处理起来更快,而且更简单。DOM 树上的结构、属性信息我们都可以很容易地用 JavaScript 对象表示出来
      • 比如我们需要模拟下面这个div标签的DOM节点元素,要怎么用JS对象去描述?
    • <div id="myDiv" title="标题">
      		 这是我的Div标签
      		<p>这是一个p标签p>
      div>
      
        • 通过js对象可以进行如下的描述
      {
         tagName:"div",
         title:"标题",
      	children:[
         		"这是我的Div标签",
            {
            	tagName:"p",
             children:[
              "这是一个p标签"
              ]
            }
         ]
      }
      
      1. 当DOM节点元素发生变化时候,就可以通过虚拟DOM去获取到更新的节点元素。

      比如上面的div节点变成了如下:

      <div id="myDiv" title="标题111">
      		 这是我的Div标签
      		<p>这是一个p标签1111p>
      div>
      

      模拟出来的虚拟DOM表示如下:

      {
          "tagName": "div",
          "title": "标题111",
          "children": [
              "这是我的Div标签",
              {
                  "tagName": "p",
                  "children": [
                      "这是一个p标签111"
                  ]
              }
          ]
      }
      

      通过模拟虚拟DOM就可以很容易知道新旧两个DOM树之间更新的部分在哪里。

      React.js 初级入门学习, 你学废了吗?_第5张图片

      简单总结虚拟DOM(Vitural DOM)的处理方式

      1. 用JS对象结构表示DOM树的结构,然后用这个虚拟DOM树构建一个真正的DOM树,插到文档当中
      2. 当状态变更的时候,重新构造一棵新的虚拟DOM树。然后用新的树和旧的树进行比较,记录两棵树差异
      3. 把第2步骤所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了

      所以React所有操作都是针对虚拟DOM,然后再把这个虚拟DOM变成浏览器中的DOM元素,最后在渲染到页面上。

      简单总结虚拟DOM

      用JS对象的形式来模拟页面上DOM嵌套关系(虚拟DOM是以JS对象的形式存在的)这就是React 中虚拟DOM的概念

      • 本质:用JS对象模拟DOM元素和嵌套关系
      • 目的:就是为了实现页面元素的高效更新

      Diff算法

      通过前面的虚拟DOM我们就可以模拟出浏览器内存中的新旧DOM树,但是要做到高效的更新,还是离不开高效的更新算法,所以我们下面就要提到Diff算法。

      当使用React的时候,在某个时间点render() 函数创建了一棵React元素树(虚拟DOM树),
      在下一个state或者props更新的时候,render() 函数将创建一棵新的React元素树(虚拟DOM树),
      React将对比这两棵树的不同之处,计算出如何高效的更新UI(只更新变化的地方)

      • 只比较同一层级,不跨级比较

      • tag 不相同,则直接删掉重建,不再深度比较
        React.js 初级入门学习, 你学废了吗?_第6张图片

      • tag和key(所以一般list都要求要指定key属性),两者都相同,则认为是相同节点,不再深度比较

      了解更多

      如何实现一个 Virtual DOM 算法

      理解 Virtual DOM

      React 入门

      环境准备

      搭建本地开发环境

      npx create-react-app my-app
      cd my-app
      npm start
      

      React.js 初级入门学习, 你学废了吗?_第7张图片

      参考:https://react.docschina.org/tutorial/tutorial.html#setup-option-2-local-development-environment

      React.js 初级入门学习, 你学废了吗?_第8张图片

      开发者工具

      React.js 初级入门学习, 你学废了吗?_第9张图片

      在这里插入图片描述

      Hello React

      前面说React 通过读取虚拟DOM(React DOM),然后使用它们来构建 DOM 以及保持随时更新,所以我们第一步就是需要创建虚拟DOM(React DOM)

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      const title = React.createElement("h1", {className: "main"},
          "Hello React!!") //

      Hello React!!

      ReactDOM.render(title, document.getElementById('root'))

      React.js 初级入门学习, 你学废了吗?_第10张图片

      嵌套子节点,在

      标签外套一层
      标签:

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      
      const title = React.createElement("h1", {className: "main"},
          "Hello React!!")
      const div = React.createElement("div", {id:"myDiv"},
          "这是个Div",title) //
      这是个Div

      Hello React!!

      ReactDOM.render(div, document.getElementById('root'))

      createElement()的问题

      说明:createElement()方式,代码编写不友好,太复杂

      var dv = React.createElement(
        "div",
        { className: "shopping-list" },
        React.createElement(
          "h1",
          null,
          "Shopping List for "
        ),
        React.createElement(
          "ul",
          null,
          React.createElement(
            "li",
            null,
            "Instagram"
          ),
          React.createElement(
            "li",
            null,
            "WhatsApp"
          )
        )
      )
      // 渲染
      ReactDOM.render(dv, document.getElementById('root'))
      

      JSX 的基本使用

      • JSX语法,最终会被编译为createElement()方法
      • 推荐:使用 JSX 的方式创建组件
      • JSX - JavaScript XML
      • JSX的语法需要通过 babel-preset-react 编译后,才能被解析执行

      JSX的注意点

      • 如果在 JSX 中给元素添加类, 需要使用 className 代替 class, 因为class是js的关键字
      • 在 JSX 中注释语法:{/* 中间是注释的内容 */}
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <h1 className="main">Hello, React! {/*这是注释*/}</h1>,
          document.getElementById('root')
      );
      
      

      React.js 初级入门学习, 你学废了吗?_第11张图片

      • 在 JSX 中可以直接使用 JS代码,直接在 JSX 中通过 {} 中间写 JS代码即可
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <h1 className="main">Hello, React! {alert("Hello World")}</h1>,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第12张图片

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      const a1 = true
      const a2 = 100
      const a3 = "Hello React"
      const a4 = new Date()
      const element = <h1>Hello, {a3}</h1> //React元素
      const user = {firstName:'Kevin',lastName:'Cai'}
      function fun(user){
        return user.firstName + ' ' + user.lastName;
      }
      ReactDOM.render(
          <div>
            <h1>{a1.toString()}</h1>
            <h1>{a2 + 1}</h1>
            <h1>{a3}</h1>
            <h1>{a4.toLocaleString()}</h1>
            <h1>{a1 ? "条件为真" : "条件为假"}</h1>
            {element}
            {fun(user)}
          </div>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第13张图片

      • 在JSX中只有一个根结点

      下面这种方式是有问题的

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <h1 className="main">Hello, React!</h1>
          <h1>Hello World!</h1>,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第14张图片

      下面这种方式才是OK的:

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <div>
            <h1 className="main">Hello, React!</h1>
            <h1>Hello World!</h1>
          </div>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第15张图片

      • 在JSX中节点元素必须闭合,要符合XML规范

      下面这种方式在编译的时候就会报错了

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <div>
            <h1 className="main">Hello, React!</h1>
            <hr>
            <h1>Hello World!</h1>
          </div>,
          document.getElementById('root')
      )
      

      节点元素必须要闭合

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      ReactDOM.render(
          <div>
            <h1 className="main">Hello, React!</h1>
            <hr/>
            <h1>Hello World!</h1>
          </div>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第16张图片

      React.js 初级入门学习, 你学废了吗?_第17张图片

      React组件

      React创建组件的两种方式

      • 通过 JS函数创建(无状态组件)
      • 通过 class创建(有状态组件)
      1. 定义组件最简单的方式就是编写 JavaScript 函数
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
      }
      
      const element = <Welcome name="Kevin" />;
      ReactDOM.render(
          element,
          document.getElementById('root')
      );
      

      该函数是一个有效的 React 组件,因为它接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。这类组件被称为“函数组件”,因为它本质上就是 JavaScript 函数。

      【注意】

      • 函数名称必须为大写字母开头,React通过这个特点来判断是不是一个组件
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      class welcome extends React.Component {
        render() {
          return <h1>Hello, {this.props.name}</h1>;
        }
      }
      
      const element = <welcome name="Kevin" />;
      ReactDOM.render(
          element,
          document.getElementById('root')
      );
      

      如果函数名称是小写,React是不会把它当做一个组件,所以页面上是不会显示的。

      React.js 初级入门学习, 你学废了吗?_第18张图片

      • 函数必须有返回值,返回值可以是:JSX对象或null
      • 返回的JSX,必须有一个根元素
      • 组件的返回值使用()包裹,避免换行问题
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      class Welcome extends React.Component {
        render() {
          return 
          <h1>Hello, {this.props.name}</h1>;
        }
      }
      
      const element = <Welcome name="Kevin" />;
      ReactDOM.render(
          element,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第19张图片

      这个时候可以使用()来包裹,避免换行的问题,建议都加上,避免格式化问题导致出问题。

      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      class Welcome extends React.Component {
        render() {
          return(
          <h1>Hello, {this.props.name}</h1>);
        }
      }
      
      const element = <Welcome name="Kevin" />;
      ReactDOM.render(
          element,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第20张图片

      1. 同时还可以使用 ES6 的 class 来定义组件:
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      //  react对象继承字React.Component
      class Welcome extends React.Component {
      // class创建的组件中 必须有rander方法 且显示return一个react对象或者null
        render() {
          return <h1>Hello, {this.props.name}</h1>;
        }
      }
      
      const element = <Welcome name="Kevin" />;
      ReactDOM.render(
          element,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第21张图片

      上述两个组件在 React 里是等效的。

      函数式组件 和 class 组件的使用场景

      1. 如果一个组件仅仅是为了展示数据,那么此时就可以使用 函数组件
      2. 如果一个组件中有一定业务逻辑,需要操作数据,那么就需要使用 class 创建组件,因为,此时需要使用 state

      给组件传递数据

      • 组件中有一个 只读的对象 叫做 props,无法给props添加属性
      • 获取方式:函数参数 props
      • 作用:将传递给组件的属性转化为 props 对象中的属性
      import React from 'react'
      import ReactDOM from 'react-dom'
      import './index.css'
      
      function Welcome(props) {
        // props ---> { name: 'Kevin', age: 20 }
        return (
            <div>
              <div>Welcome React</div>
              <h3>姓名:{props.name}----年龄是:{props.age}</h3>
            </div>
        )
      }
      
      //传递 props:name 和 age(如果你想要传递number类型数据 就需要向下面这样)
      const element = <Welcome name="Kevin" age={20}/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第22张图片

      封装组件到独立的文件中

      Vue.js是使用.vue文件来声明一个组件,同样React也可以把我们的自定义组件封装到一个独立的文件中。

      // 1. 引入React模块
      // 由于 JSX 编译后会调用 React.createElement 方法,所以在你的 JSX 代码中必须首先拿到React。
      import React from 'react'
      import '../index.css'
      // 2. 使用function构造函数创建组件
      function Welcome(props) {
        return (
            <div>
              <div className="main">Welcome React</div>
              <h3>姓名:{props.name}----年龄是:{props.age}</h3>
            </div>
        )
      }
      // 3. 导出组件
      export default Welcome
      

      使用import Welcome from './component/Welcome' 来导入组件

      import React from 'react'
      import ReactDOM from 'react-dom'
      import Welcome from './component/Welcome'
      
      //传递 props:username 和 age(如果你想要传递number类型数据 就需要向下面这样)
      const element = <Welcome name="Kevin" age={20}/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第23张图片

      props和state

      props
      • 作用:给组件传递数据,一般用在父子组件之间
      • 说明:React把传递给组件的属性转化为一个对象并交给 props
      • 特点:props是只读的,无法给props添加或修改属性
      // props 是一个包含数据的对象参数,不要试图修改 props 参数
      // 返回值:react元素
      function Welcome(props) {
        // 返回的 react元素中必须只有一个根元素
        return <div>hello, {props.name}</div>
      }
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props)
        }
      
        render() {
          return <h1>Hello, {this.props.name}</h1>
        }
      }
      
      state

      状态即数据

      • 作用:用来给组件提供组件内部使用的数据
      • 注意:只有通过class创建的组件才具有状态
      • 注意:状态是私有的,完全由组件来控制
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props)
          this.state = {
            name: 'Kevin'
          }
        }
      
        render() {
          return <h1>Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      组件的生命周期

      简单说:一个组件从开始到最后消亡所经历的各种状态,就是一个组件的生命周期

      组件生命周期函数的定义:从组件被创建,到组件挂载到页面上运行,再到页面关闭组件被卸载,这三个阶段总是伴随着组件各种各样的事件,那么这些事件,统称为组件的生命周期函数!

      组件生命周期函数总览

      组件的生命周期包含三个阶段:创建阶段(Mounting)、运行和交互阶段(Updating)、卸载阶段(Unmounting)

      组件生命周期 - 创建阶段(Mounting)
      • constructor()
        • 作用:获取props和初始化state
        • 说明:通过 constructor() 的参数props获取
        • 设置state和props
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
        }
      
        render() {
          return <h1>Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第24张图片

      • componentWillMount()
        • 说明:组件被挂载到页面之前调用,其在render()之前被调用,因此在这方法里同步地设置状态将不会触发重渲染
        • 注意:无法获取页面中的DOM对象
        • 注意:可以调用 setState() 方法来改变状态值
        • 用途:发送ajax请求获取数据
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
        }
      
        //组件被挂载到页面之前调用,其在render()之前被调用,因此在这方法里同步地设置状态将不会触发重渲染
        componentWillMount() {
          console.warn(document.getElementById('hello')) // null
          this.setState({
            name: "Kevin Cai"
          })
        }
      
        render() {
          return <h1 id="hello">Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第25张图片

      在这里插入图片描述

      • render()
        • 作用:渲染组件到页面中,无法获取页面中的DOM对象
        • 注意:不要在render方法中调用 setState() 方法,否则会递归渲染
        • 原因说明:状态改变会重新调用render(),render()又重新改变状态
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
        }
        //渲染组件到页面中,无法获取页面中的DOM对象
        render() {
          console.warn(document.getElementById('hello')) // null
          return <h1 id="hello">Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第26张图片

      React.js 初级入门学习, 你学废了吗?_第27张图片

      不要再render方法中更新state,状态改变会重新调用render(),render()又重新改变状态,会导致无限递归

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
        }
      
        //渲染组件到页面中,无法获取页面中的DOM对象
        render() {
          console.warn(document.getElementById('hello')) // null
          this.setState({
            name: "Kevin Cai"
          })
          return <h1 id="hello">Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第28张图片

      • componentDidMount()
        • 组件已经挂载到页面中
        • 可以进行DOM操作,比如:获取到组件内部的DOM对象
        • 可以发送请求获取数据
        • 可以通过 setState() 修改状态的值
        • 注意:在这里修改状态会重新渲染
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      class Welcome extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
        }
      
        componentDidMount() {
          // 此时,就可以获取到组件内部的DOM对象
          console.warn(document.getElementById('hello')) 
        }
        render() {
          return <h1 id="hello">Hello, {this.state.name}</h1>
        }
      }
      
      const element = <Welcome name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第29张图片

      组件生命周期 - 运行阶段(Updating)
      • 特点:该阶段的函数执行多次
      • 说明:每当组件的props或者state改变的时候,都会触发运行阶段的函数
      • componentWillReceiveProps()
        • 说明:组件接受到新的props前触发这个方法,props改变
        • 参数:当前组件props值
        • 可以通过 this.props 获取到上一次的值
        • 使用:若你需要响应属性的改变,可以通过对比this.props和nextProps并在该方法中使用this.setState()处理状态改变
        • 注意:修改state不会触发该方法

      通过如下的代码来演示props的改变:

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Parent extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //设置state和props
            name: props.name
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.setState({
            name: "Kevin Cai"
          })
        }
      
        render() {
          return <button id="hello" onClick={this.handleClick}>
            Parent - Hello {this.state.name}, <Child name={this.state.name}/>
          </button>
        }
      }
      
      class Child extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
        }
      
        componentWillReceiveProps(nextProps) {
          console.log("Child - componentWillReceiveProps")
          console.log(`this.props-->${JSON.stringify(this.props)}`)
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
        }
      
        render() {
          return <h3>Child - Hello, {this.props.name}</h3>
        }
      }
      
      const element = <Parent name="Kevin"/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第30张图片

      在这里插入图片描述

      • shouldComponentUpdate()
        • 作用:根据这个方法的返回值决定是否重新渲染组件,返回true重新渲染,否则不渲染
        • 优势:通过某个条件渲染组件,降低组件渲染频率,提升组件性能
        • 说明:如果返回值为false,那么,后续render()方法不会被调用
        • 注意:这个方法必须返回布尔值!!!
        • 场景:根据随机数决定是否渲染组件,或者比如进度条的更新。
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = {
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.setState(state => ({
            count: state.count + 1
          }))
        }
      
        // - 参数:
      //   - 第一个参数:最新属性对象
      //   - 第二个参数:最新状态对象
        shouldComponentUpdate(nextProps, nextState) {
          console.log('shouldComponentUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
          return nextState.count % 2 === 0
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}
          </button>
        }
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第31张图片

      React.js 初级入门学习, 你学废了吗?_第32张图片

      • componentWillUpdate()
        • 作用:组件将要更新
        • 参数:最新的属性和状态对象
        • 注意:不能修改状态 否则会循环渲染
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = {
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.setState(state => ({
            count: state.count + 1
          }))
        }
      
      
        shouldComponentUpdate(nextProps, nextState) {
          console.log('shouldComponentUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
          return nextState.count % 2 === 0
        }
      
        componentWillUpdate(nextProps, nextState) {
          console.log('componentWillUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}
          </button>
        }
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第33张图片

      React.js 初级入门学习, 你学废了吗?_第34张图片

      • render() 渲染
        • 作用:重新渲染组件,与Mounting阶段的render是同一个函数
        • 注意:这个函数能够执行多次,只要组件的属性或状态改变了,这个方法就会重新执行
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = {
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.setState(state => ({
            count: state.count + 1
          }))
        }
      
      
        shouldComponentUpdate(nextProps, nextState) {
          console.log('shouldComponentUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
          return nextState.count % 2 === 0
        }
      
        componentWillUpdate(nextProps, nextState) {
          console.log('componentWillUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
        }
      
        render() {
          console.log("render.....")
          return <button onClick={this.handleClick}>{this.state.count}
          </button>
        }
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第35张图片

      • componentDidUpdate()
        • 作用:组件已经被更新
        • 参数:旧的属性和状态对象
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = {
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.setState(state => ({
            count: state.count + 1
          }))
        }
      
      
        shouldComponentUpdate(nextProps, nextState) {
          console.log('shouldComponentUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
          return nextState.count % 2 === 0
        }
      
        componentWillUpdate(nextProps, nextState) {
          console.log('componentWillUpdate')
          console.log(`nextProps-->${JSON.stringify(nextProps)}`)
          console.log(`nextState-->${JSON.stringify(nextState)}`)
        }
      
        render() {
          console.log("render.....")
          return <button onClick={this.handleClick}>{this.state.count}
          </button>
        }
      
        componentDidUpdate(prevProps, prevState) {
          console.log('componentDidUpdate')
          console.log(`prevProps-->${JSON.stringify(prevProps)}`)
          console.log(`prevState-->${JSON.stringify(prevState)}`)
        }
      
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第36张图片

      组件生命周期 - 卸载阶段(Unmounting)
      • 组件销毁阶段:组件卸载期间,函数比较单一,只有一个函数,这个函数也有一个显著的特点:组件一辈子只能执行依次!
      • 使用说明:只要组件不再被渲染到页面中,那么这个方法就会被调用( 渲染到页面中 -> 不再渲染到页面中 )
      • componentWillUnmount()
        • 作用:在卸载组件的时候,执行清理工作,比如
          • 清除定时器
          • 清除componentDidMount创建的DOM对象
      了解更多

      React.js 初级入门学习, 你学废了吗?_第37张图片
      上图参考自下方链接的博文

      React生命周期的图解

      React生命周期图解

      生命周期图谱

      state和setState

      • 注意:使用 setState() 方法修改状态,状态改变后,React会重新渲染组件
      • 注意:不要直接修改state属性的值,这样不会重新渲染组件!!!
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = {
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          this.state.count = 1 //这样方式,不会重新渲染组件
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第38张图片

      • 使用:
        • 初始化state
        • setState修改state

      使用的正确姿势:

      • 修改state的方式一
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //初始化 state
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          // 修改 state 的值
          // 方式一:
          this.setState({
            count: this.state.count + 1
          })
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      
      • setState() 是异步操作
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //初始化 state
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          // 修改 state 的值
          // 方式一:
          this.setState({
            count: this.state.count + 1
          })
          console.log(this.state.count) //输出当前的this.state.count
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第39张图片

      可以看到输出的结果并不是最新的,说明setState方法并不是同步的,而是异步的。

      那如果我们就想要拿到最新的count的结果呢? 要怎么做?

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //初始化 state
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          // 修改 state 的值
          // 方式一:
          this.setState({
            count: this.state.count + 1
          },function(){
            // 由于 setState() 是异步操作,所以,如果想立即获取修改后的state
            // 需要在回调函数中获取
            console.log(this.state.count) //输出当前的this.state.count
          })
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第40张图片

      • 修改state的方式二
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //初始化 state
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          // 修改 state 的值
          // 方式二:
          this.setState(function(prevState, props) {
            console.log("prevState:",prevState)
            console.log("props:",props)
            return {
              count: prevState.count + props.increment
            }
          })
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter increment = {1}/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第41张图片

      或者还可以写成如下:

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Counter extends React.Component {
        constructor(props) {
          super(props) //通过 constructor() 的参数props获取
          this.state = { //初始化 state
            count: 0
          }
          // 为了在回调中使用 `this`,这个绑定是必不可少的
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          // 修改 state 的值
          // 方式二:
          // 或者 - 注意: => 后面需要带有小括号,因为返回的是一个对象
          this.setState((prevState, props) => ({
            count: prevState.count + props.increment
          }))
        }
      
        render() {
          return <button onClick={this.handleClick}>{this.state.count}</button>
        }
      
      }
      
      const element = <Counter increment = {1}/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      

      组件绑定事件

      React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:

      • React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
      • 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。

      例如,传统的 HTML:

      <button onclick="activateLasers()">
        Activate Lasers
      button>
      

      在 React 中略微不同:

      <button onClick={activateLasers}>
        Activate Lasers
      button>
      

      在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault 。例如,传统的 HTML 中阻止链接默认打开一个新页面,你可以这样写:

      <a href="#" onclick="console.log('The link was clicked.'); return false">
        Click me
      a>
      

      在 React 中,可能是这样的:

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function ActionLink() {
        function handleClick(e) {
          e.preventDefault();
          console.log('The link was clicked.');
        }
      
        return (
            <a href="#" onClick={handleClick}>
              Click me
            </a>
        );
      }
      
      const element = <ActionLink/>
      ReactDOM.render(
          element,
          document.getElementById('root')
      )
      
      事件绑定中的this

      必须谨慎对待 JSX 回调函数中的 this,在 JavaScript 中,class 的方法默认不会绑定 this。如果你忘记绑定 this.handleClick 并把它传入了 onClick,当你调用这个函数的时候 this 的值为 undefined

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class Toggle extends React.Component {
        constructor(props) {
          super(props);
          this.state = {isToggleOn: true};
        }
      
        handleClick() {
          console.log(this)
          this.setState(state => ({
            isToggleOn: !state.isToggleOn
          }));
        }
      
        render() {
          return (
              <button onClick={this.handleClick}>
                {this.state.isToggleOn ? 'ON' : 'OFF'}
              </button>
          );
        }
      }
      
      ReactDOM.render(
          <Toggle />,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第42张图片

      通过bind绑定
      • 原理:bind能够调用函数,改变函数内部this的指向,并返回一个新函数
      • 说明:bind第一个参数为返回函数中this的指向,后面的参数为传给返回函数的参数
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class MyButton extends React.Component {
        constructor(props) {
          super(props);
          this.state = {msg : "button"}
        }
      
        handleClick() {
          console.log(this)
          this.setState({
            msg: '点击事件修改state的值'
          })
        }
      
        render() {
          return (
              <button onClick={this.handleClick.bind(this)}>
                {this.state.msg}
              </button>
          )
        }
      }
      
      ReactDOM.render(
          <MyButton />,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第43张图片

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class MyButton extends React.Component {
        constructor(props) {
          super(props);
          this.state = {msg : "button"}
        }
      
        handleClick(arg1, arg2) {
          console.log(this)
          this.setState({
            msg: '点击事件修改state的值' + arg1 + arg2
          })
        }
      
        render() {
          return (
              // 有参数
              <button onClick={this.handleClick.bind(this, 'abc', [1, 2])}>
                {this.state.msg}
              </button>
          )
        }
      }
      
      ReactDOM.render(
          <MyButton />,
          document.getElementById('root')
      )
      
      

      React.js 初级入门学习, 你学废了吗?_第44张图片

      • 在构造函数中使用bind
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class MyButton extends React.Component {
        constructor(props) {
          super(props);
          this.state = {msg : "button"}
      
          this.handleClick = this.handleClick.bind(this)
        }
      
        handleClick() {
          console.log(this)
          this.setState({
            msg: '点击事件修改state的值'
          })
        }
      
        render() {
          return (
              <button onClick={this.handleClick}>
                {this.state.msg}
              </button>
          )
        }
      }
      
      ReactDOM.render(
          <MyButton />,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第45张图片

      通过箭头函数绑定
      • 原理:箭头函数中的this由所处的环境决定,自身不绑定this
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class MyButton extends React.Component {
        constructor(props) {
          super(props);
          this.state = {msg : "button"}
        }
      
        handleClick(arg1, arg2) {
          console.log(this)
          this.setState({
            msg: '点击事件修改state的值' + arg1 + arg2
          })
        }
      
        render() {
          return (
              <button onClick={() => { this.handleClick('参数1', '参数2') }}>
                {this.state.msg}
              </button>
          )
        }
      }
      
      ReactDOM.render(
          <MyButton />,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第46张图片

      条件渲染

      React 中的条件渲染和 JavaScript 中的一样,使用 JavaScript 运算符 if 或者条件运算符去创建元素来表现当前的状态,然后让 React 根据它们来更新 UI。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function UserGreeting(props) {
        return <h1>Welcome back!</h1>;
      }
      
      function GuestGreeting(props) {
        return <h1>Please sign up.</h1>;
      }
      
      
      function Greeting(props) {
        const isLoggedIn = props.isLoggedIn;
        if (isLoggedIn) {
          return <UserGreeting />;
        }
        return <GuestGreeting />;
      }
      
      ReactDOM.render(
          // Try changing to isLoggedIn={true}:
          <Greeting isLoggedIn={false} />,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第47张图片

      • 与运算符 &&

      通过花括号包裹代码,你可以在 JSX 中嵌入任何表达式。这也包括 JavaScript 中的逻辑与 (&&) 运算符。它可以很方便地进行元素的条件渲染。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function UserGreeting(props) {
        return <h1>Welcome back!</h1>;
      }
      
      function GuestGreeting(props) {
        return <h1>Please sign up.</h1>;
      }
      
      
      function Greeting(props) {
        const isLoggedIn = props.isLoggedIn;
        return isLoggedIn && <UserGreeting />;
      }
      
      ReactDOM.render(
          // Try changing to isLoggedIn={true}:
          <Greeting isLoggedIn={true} />,
          document.getElementById('root')
      );
      

      true && expression 总是会返回 expression, 而 false && expression 总是会返回 false。
      因此,如果条件是 true,&& 右侧的元素就会被渲染,如果是 false,React 会忽略并跳过它。

      React.js 初级入门学习, 你学废了吗?_第48张图片

      • 三目运算符

      另一种内联条件渲染的方法是使用 JavaScript 中的三目运算符 condition ? true : false。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function UserGreeting(props) {
        return <h1>Welcome back!</h1>;
      }
      
      function GuestGreeting(props) {
        return <h1>Please sign up.</h1>;
      }
      
      
      function Greeting(props) {
        const isLoggedIn = props.isLoggedIn;
        //三目运算符
        return isLoggedIn ? <UserGreeting /> : <GuestGreeting />;
      }
      
      ReactDOM.render(
          // Try changing to isLoggedIn={true}:
          <Greeting isLoggedIn={false} />,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第49张图片

      列表 & Key

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function NumberList(props) {
        const numbers = props.numbers;
        const listItems = numbers.map((number) =>
            <li>{number}</li>
        );
        return (
            <ul>{listItems}</ul>
        );
      }
      
      const numbers = [1, 2, 3, 4, 5];
      ReactDOM.render(
          <NumberList numbers={numbers} />,
          document.getElementById('root')
      );
      

      React.js 初级入门学习, 你学废了吗?_第50张图片

      当我们运行这段代码,将会看到一个警告 Warning: Each child in a list should have a unique “key” prop.,意思是当你创建一个元素时,必须包括一个特殊的 key 属性。

      key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function NumberList(props) {
        const numbers = [1, 2, 3, 4, 5];
        const listItems = numbers.map((number) =>
            <li key={number.toString()}>
              {number}
            </li>
        );
        return (
            <ul>{listItems}</ul>
        );
      }
      
      const numbers = [1, 2, 3, 4, 5];
      ReactDOM.render(
          <NumberList numbers={numbers} />,
          document.getElementById('root')
      );
      

      一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用数据中的 id 来作为元素的 key

      当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      function NumberList(props) {
        const listItems = props.numbers.map((number, index) =>
            <li key={index}>
              {number}
            </li>
        )
        return (
            <ul>{listItems}</ul>
        )
      }
      
      const numbers = [1, 2, 3, 4, 5]
      ReactDOM.render(
          <NumberList numbers={numbers}/>,
          document.getElementById('root')
      )
      

      受控组件

      在HTML当中,像input,textarea和select这类表单元素会维持自身状态,并根据用户输入进行更新。
      在React中,可变的状态通常保存在组件的state中,并且只能用 setState() 方法进行更新.
      React根据初始状态渲染表单组件,接受用户后续输入,改变表单组件内部的状态。
      因此,将那些值由React控制的表单元素称为:受控组件。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class NameForm extends React.Component {
        constructor(props) {
          super(props);
          this.state = {value: ''};
      
          this.handleChange = this.handleChange.bind(this);
          this.handleSubmit = this.handleSubmit.bind(this);
        }
      
        handleChange(event) {
          this.setState({value: event.target.value});
        }
      
        handleSubmit(event) {
          alert('提交的名字: ' + this.state.value);
          event.preventDefault();
        }
      
        render() {
          return (
              <form onSubmit={this.handleSubmit}>
                <label>
                  名字:
                  <input type="text" value={this.state.value} onChange={this.handleChange} />
                </label>
                <input type="submit" value="提交" />
              </form>
          );
        }
      }
      
      ReactDOM.render(
          <NameForm/>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第51张图片

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class EssayForm extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            value: '请撰写一篇关于你喜欢的 DOM 元素的文章.'
          };
      
          this.handleChange = this.handleChange.bind(this);
          this.handleSubmit = this.handleSubmit.bind(this);
        }
      
        handleChange(event) {
          this.setState({value: event.target.value});
        }
      
        handleSubmit(event) {
          alert('提交的文章: ' + this.state.value);
          event.preventDefault();
        }
      
        render() {
          return (
              <form onSubmit={this.handleSubmit}>
                <label>
                  文章:
                  <textarea value={this.state.value} onChange={this.handleChange} />
                </label>
                <input type="submit" value="提交" />
              </form>
          );
        }
      }
      
      ReactDOM.render(
          <EssayForm/>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第52张图片

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class FlavorForm extends React.Component {
        constructor(props) {
          super(props);
          this.state = {value: '葡萄柚'};
      
          this.handleChange = this.handleChange.bind(this);
          this.handleSubmit = this.handleSubmit.bind(this);
        }
      
        handleChange(event) {
          this.setState({value: event.target.value});
        }
      
        handleSubmit(event) {
          alert('你喜欢的风味是: ' + this.state.value);
          event.preventDefault();
        }
      
        render() {
          return (
              <form onSubmit={this.handleSubmit}>
                <label>
                  选择你喜欢的风味:
                  <select value={this.state.value} onChange={this.handleChange}>
                    <option value="葡萄柚">葡萄柚</option>
                    <option value="酸橙">酸橙</option>
                    <option value="椰子">椰子</option>
                    <option value="芒果">芒果</option>
                  </select>
                </label>
                <input type="submit" value="提交" />
              </form>
          );
        }
      }
      
      ReactDOM.render(
          <FlavorForm/>,
          document.getElementById('root')
      )
      

      React.js 初级入门学习, 你学废了吗?_第53张图片

      学习参考

      React入门看这篇就够了

      React官网文档

      React 菜鸟教程

      你可能感兴趣的:(React.js)