文章目录

  • 前言
  • 一、helloworld
  • 二、React jsx
    • 2.1 jsx
    • 2.2 动态展示列表数据
    • 2.3 虚拟dom创建的两种方式
    • 2.4 代码实例
    • 2.5 步骤
    • 2.6 技术点
  • 三、组件化、模块化
    • 3.1 组件
    • 3.2 组件化
    • 3.3 模块
    • 3.4 模块化
  • 四、组件定义两种方式
    • 3.1 代码实例
    • 3.2 技术点
  • 五、组件三个属性:state、props、refs
    • 3.1 component_state
      • 3.1.1 需求说明
      • 3.1.2 state
      • 3.1.2 代码实例
      • 3.1.3 步骤
      • 3.1.4 步骤、技术点
    • 3.2 component_props
      • 3.2.1 需求说明
      • 3.2.2 props
      • 3.2.3 代码实例
      • 3.2.4 步骤、技术点
      • 3.2.5 问题:区别state和props
    • 3.3 component_refs
      • 3.3.1 需求描述
      • 3.3.2 refs属性
      • 3.3.3 事件处理
      • 3.3.4 强烈注意
    • 3.3.5 代码实例
    • 3.3.6 步骤、技术点
  • 六、组件的组合
    • 6.1 需求描述
    • 6.2 代码实例
    • 6.3 技术点(==注意:数据在哪,操作方法就在哪==)
    • 6.4 React工具使用,查看三个属性
    • 6.5 功能界面的组件化编码流程(无比重要)
  • 七、收集表单数据
    • 7.1 需求描述
    • 7.2 理解
    • 7.3 代码实例
    • 7.4 步骤、技术点
  • 八、组件生命周期
    • 8.1 需求效果
    • 8.2 理解
    • 8.3 生命周期流程图
    • 8.4 生命周期详述
    • 8.5 重要的勾子
  • 九、虚拟DOM与DOM Diff算法
    • 9.1 代码实例
    • 9.2 基本原理图
  • 十、react引用(基于react脚手架)
    • 10.1 使用create-react-app创建react应用
      • 10.1.1 react脚手架
      • 10.1.2 创建项目并启动
      • 10.1.3 react脚手架项目结构
    • 10.2 项目结构
    • 10.2 demo:评论管理
    • 10.3 demo:评论管理
  • 十一、react ajax
    • 11.1 理解
      • 11.1.1 前置说明
      • 11.1.2 常用的ajax请求库
      • 11.1.3 效果
      • 11.1.4 代码实例
    • 11.2 axios
      • 11.2.1 文档
      • 11.2.1 相关API
      • 11.3 demo: github users
      • 11.3.1 需求描述
      • 11.3.2 拆分组件
      • 11.3.3 代码实例
    • 11.4 Fetch
    • 11.4.1 文档
    • 11.4.2 相关API
  • 十二、几个重要技术总结
    • 12.1 组件间通信
    • 12.1.1 方式一: 通过props传递
    • 12.1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
    • 12.1.3 方式三: redux
    • 12.2 事件监听理解
    • 12.2.1 原生DOM事件
    • 12.2.2 自定义事件(消息机制)
    • 12.3 ES6常用新语法
  • 十三、react-router
    • 13.1 项目理解
      • 13.1.1 react-router的理解
      • 13.1.2 SPA的理解
      • 13.1.3 路由的理解
      • 13.1.4 前端路由的实现
    • 13.2 react-router相关API
      • 13.2.1 react-router组件
      • 13.2.2 其它
    • 13.3 基本路由使用
      • 13.3.1 效果
      • 13.3.2 准备
    • 13.4 嵌套路由使用
      • 13.4.1 效果
    • 13.5 向路由组件传递参数数据
      • 13.5.1 效果
    • 13.6 多种路由跳转方式(==重要==)
      • 13.6.1 效果
      • 13.6.2 代码实例
  • 十四、React UI
    • 14.1 最流行的开源React UI组件库
      • 14.1.1 material-ui(国外)
      • 14.1.2 ant-design(国内蚂蚁金服)
    • 14.2 ant-design-mobile使用入门
      • 14.2.1 效果
      • 14.2.2 使用create-react-app创建react应用
      • 14.2.3 搭建antd-mobile的基本开发环境
      • 7.2.4. 实现按需打包(组件js/css)
  • 扩展,数组方法
    • 1. map()
    • 2. unshift()
    • 3. splice()
    • 4. filter()

前言

公司实习的地方,使用react,然后打算学习一下react,并把基础知识点整理一下,毕业设计的前端,也使用react来搭建前端框架。
这里主要有如下react基础知识点:

  1. jsx语法
  2. 组件定义的两种方式:类和方法
  3. 组件三大属性:state、props、ref(这个为标签属性)
  4. 组件的组合
  5. 标签的受控组件和非受控组件
  6. react的生命周期
  7. react应用(基于create-react-app脚手架)
  8. react-axios
  9. react-router
  10. react-UI:antdesign
    最重要的一个 没讲:redux
    代码都已上库到GitHub上。
    传送门: https://github.com/fengfanli/react-study

一、helloworld

先使用react写一个helloworld,体验一下。
先导入react开发版本js,有三个,react.development.js、react-dom.development.js、babel.min.js
react.js:React 的核心库
react-dom.js:提供操作DOM 的react 扩展库
babel.js:为babel库,两个作用1、将es6语法转化为es5,2、解析JSX语法代码为纯JS 语法代码的库(这里使用的是后者语法)

<body><div id="example"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">  // 声明:告诉babel.js这里有jsx语法// 1、创建虚拟DOM元素对象var vDom = <h1>Hello React</h1>    // 不是字符串  jsx 语法// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom, document.getElementById("example"))</script>
</body>

页面:

步骤(重点学习的地方):
在< script type=“text/babel”> 中编写:声明:告诉babel.js这里有jsx语法
2. 创建虚拟DOM元素对象:就是定义一个变量,将HTML标签赋值于变量
3. 将虚拟DOM渲染到页面真实DOM容器中

技术点:

  1. jsx语法:var vDom = <h1>Hello React</h1>
  2. 渲染语法:ReactDOM.render(vDom, document.getElementById("example"))

二、React jsx

2.1 jsx

  1. 全称: JavaScript XML
  2. react定义的一种类似于XML的JS扩展语法: XML+JS
  3. 作用: 用来创建react虚拟DOM(元素)对象
    a. var ele = < h1>Hello JSX!< /h1>
    b. 注意1: 它不是字符串, 也不是HTML/XML标签
    c. 注意2: 它最终产生的就是一个JS对象
  4. 标签名任意: HTML标签或其它标签
  5. 标签属性任意: HTML标签属性或其它
  6. 基本语法规则
    a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
    b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含
  7. babel.js的作用
    a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
    b. 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理

2.2 动态展示列表数据

功能: 在页面中遍历一个数组,将其显示在页面中。
问题: 如何将一个数据的数组 转换为 一个标签的数组 很常用,使用数组的map() 方法 和 箭头函数

    <div id="example1"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 功能:动态展示列表数据* 问题:如何将一个数据的数组 转换为 一个标签的数组   很常用*      使用数组的map() 方法 和 箭头函数* */const names = ['jQuery', 'zepto', 'angular', 'react', 'vue']// 1、创建虚拟DOM// li 标签一定要带 key属性,而且还不能一样 否则警告const ul = (<ul>{names.map(name=> <li key={name}>{name}</li>)}</ul>)// 2、渲染虚拟DOMReactDOM.render(ul, document.getElementById('example'))</script>

页面:

步骤:

  1. 创建虚拟DOM
    使用 {} 大括号写法,在里面写js语法,将数组遍历。
  2. 渲染虚拟DOM(固定形式写法,将定义好的jsx虚拟dom渲染到 真实dom上)

技术点:
3. {} 大括号写法:
4. 数组方法map():js方法,是对数组的遍历,里面为回调函数,方法形式:
map(value):value 为数组的值,
map(value, index):value 为数组的值,index为数组下标

2.3 虚拟dom创建的两种方式

  1. 使用原生js方法:const vDom1 = React.createElement(‘h1’, {id:‘myTitle’},‘hello’)
  2. 使用jsx方法:const vDom2 = < h3 id={myId.toUpperCase()}>{msg.toLowerCase()}< /h3>

2.4 代码实例

<body><div id="test01"></div><div id="test02"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/javascript">/*** 需求,两种方式实现虚拟DOM的创建* 1、使用原生js方法:const vDom1 = React.createElement('h1', {id:'myTitle'},'hello')* 2、使用jsx方法:const vDom2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>*/const msg = 'I Like you!'const myId = 'fengfanli'// 1、创建虚拟DOM元素对象// const element = React.createElement('h1', {id:'myTitle'},'hello')const vDom1 = React.createElement('h2', {id: myId.toLowerCase()}, msg.toUpperCase())// debugger// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom1, document.getElementById('test01'))</script><script type="text/babel">// 1、创建虚拟DOM元素对象const vDom2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>// debugger// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom2, document.getElementById('test02'))</script>
</body>

页面:

2.5 步骤

  1. 创建虚拟dom
  2. 渲染虚拟dom

2.6 技术点

  1. 渲染虚拟dom的两种方法:原生js和jsx

三、组件化、模块化

3.1 组件

  1. 理解: 用来实现特定(局部)功能效果的代码集合(html/css/js)
  2. 为什么: 一个界面的功能更复杂
  3. 作用: 复用编码, 简化项目编码, 提高运行效率

3.2 组件化

当应用是以多组件的方式实现, 这个应用就是一个组件化的应用。

3.3 模块

  1. 理解: 向外提供特定功能的js程序, 一般就是一个js文件
  2. 为什么: js代码更多更复杂
  3. 作用: 复用js, 简化js的编写, 提高js运行效率

3.4 模块化

当应用的js都以模块来编写的, 这个应用就是一个模块化的应用

四、组件定义两种方式

  1. 方式一:使用方法定义,没有状态用此种方式(简单组件)
  2. 方式二:使用定义,(复杂组件)

3.1 代码实例

<body><div id="example1"></div><div id="example2"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 组件定义的两种方式* 1、使用方法定义,没有状态用此种方式(简单组件)* 2、使用类定义,(复杂组件)*/// 1.定义组件//方式1: 工厂函数组件(简单组件):没有状态的组件function MyComponent() {return <h2>工厂函数组件(简单组件)</h2>}//方式2:  ES6类组件(复杂组件)class MyComponent2 extends React.Component{render(){console.log(this)return <h2>工厂函数组件(简单组件)</h2>}}// 2.渲染组件方式ReactDOM.render(<MyComponent />, document.getElementById('example1'))ReactDOM.render(<MyComponent2 />, document.getElementById('example2'))</script>
</body>

页面:

3.2 技术点

  1. 两种定义组件的方式:方法(简单组件)、类(复杂组件)
  2. render()方法,在里面写UI,

五、组件三个属性:state、props、refs

3.1 component_state

3.1.1 需求说明

自定义组件,功能说明如下

  1. 显示 h2 标题,初始文本为:你喜欢我
  2. 点击标题更新为:我喜欢你

3.1.2 state

  1. state是组件对象最重要的属性, 值是对象(可以包含多个数据)

  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)

  3. 初始化状态:

  constructor (props) {super(props)this.state = {stateProp1 : value1,stateProp2 : value2}}
  1. 读取某个状态值
    this.state.statePropertyName // statePropertyName 自定义名称
  2. 更新状态---->组件界面更新
  this.setState({stateProp1 : value1,stateProp2 : value2})

3.1.2 代码实例

<body><div id="example"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 需求:自定义组件,功能说明如下* 1. 显示 h2 标题,初始文本为:你喜欢我* 2. 点击标题更新为:我喜欢你* */// 1.定义组件class Like extends React.Component{// 2)、构造器constructor(props){super(props)// 初始化状态this.state = {isLikeMe: false}// 将新增方法中的this 强制绑定为组件对象this.handleClick = this.handleClick.bind(this)}// 1)、重写组件类的方法render(){// 读取状态const {isLikeMe} = this.state  // 第二种方式return <h2 onClick={this.handleClick}>{isLikeMe?'你喜欢我':'我喜欢你'}</h2>}// 3)、新添加的方法:内部的 this 默认不是组件对象,而是 undefined, 所以要在 构造器中 绑定方法handleClick(){console.log('handleClick()',this)// 得到原有状态 并取反const isLikeMe = !this.state.isLikeMe//更新状态this.setState({isLikeMe})}}// 2.渲染组件ReactDOM.render(<Like />, document.getElementById('example'))
</script>
</body>

3.1.3 步骤

  1. 定义组件类
  2. 编写**render()**方法,在这里写UI组件。
  3. 编写构造器,和里面的state属性初始化。
  4. 然后在编写点击事件这里需要注意这个方法需要绑定到类上,在构造器上进行bind()方法绑定。

3.1.4 步骤、技术点

  1. 编写组件类
  2. render方法
  3. constructor构造器、state属性
  4. 编写点击事件,在构造器bind绑定,注意更新state的方法和获取state的关键字
  5. 渲染组件:ReactDOM.render()

3.2 component_props

3.2.1 需求说明

需求: 自定义用来显示一个人员信息的组件
1). 姓名必须指定
2). 如果性别没有指定, 默认为男
3). 如果年龄没有指定, 默认为18

3.2.2 props

理解

  1. 每个组件对象都会有props(properties的简写)属性
  2. 组件标签的所有属性都保存在props中

作用

  1. 通过标签属性 从组件外向组件内 传递变化的数据
  2. 注意: 组件内部不要修改props数据

编码操作

  1. 内部读取某个属性值
    this.props.propertyName
  2. 对props中的属性值进行类型限制必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
  1. 扩展属性: 将对象的所有属性通过props传递
    <Person {...person}/>
  2. 默认属性值
Person.defaultProps = {
name: 'Mary'
}
  1. 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}

3.2.3 代码实例

<body>
<div id="example1"></div>
<div id="example2"></div>
<div id="example3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** props属性 和 prop-types.js    prop-types.js: 对值进行设定* 需求:自定义用来显示一个人员信息的组件,效果如页面,说明* 1、如果性别没有指定,默认为男* 2、如果年龄没有指定,默认为18*/// 1、定义组件/*** 使用 对象组件* 组件对象有三个 state props refs**/class Person extends React.Component{render(){console.log(this)return(<ul><li>姓名:{this.props.name}</li><li>年龄:{this.props.age}</li><li>性别:{this.props.sex}</li></ul>)}}// 指定属性 默认值Person.defaultProps = {age: 18,sex: '男'}// 对 props 中的属性值进行类型限制和必要性限制Person.propTypes = {name: PropTypes.string.isRequired,age: PropTypes.number}// 2、渲染组件const p1 = {name: 'Tom',age: 18,sex: '女'}ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex} />, document.getElementById("example1"))const p2 = {name: 'Jack',}ReactDOM.render(<Person name={p2.name} age={20}  />, document.getElementById("example2"))/***  ... 的作用*  1、打包*  function fn(...as){}  fn(1, 2, 3)  : 打包的意思*  2、解包*  const arr1 = [1, 2, 3]  const arr2 = [6, ...arr1, 9]  :解包的意思** @type {{name: string}}*/const p3 = {name: 'Feng',}ReactDOM.render(<Person  {...p3} />, document.getElementById("example3"))
</script>
</body>

页面:

3.2.4 步骤、技术点

新添加了一个js:prop-types,这个库是在子组件中,对父组件传给子组件的属性值进行加以设定。

  1. 在渲染虚拟dom,ReactDOM.render(<Person />, document.getElementById("example3"))
    向 HTML标签一样,添加属性,往里面传值,在组件类 Person中通过 this.props.属性名获取值。
  2. 扩展运算符(三点运算符)...将对象的所有属性通过props传递

3.2.5 问题:区别state和props

请区别一下组件的props和state属性

  1. state: 组件自身内部可变化的数据
  2. props: 从组件外部向组件内部传递数据, 组件内部只读不修改

3.3 component_refs

3.3.1 需求描述

需求: 自定义组件, 功能说明如下:

  1. 点击按钮, 提示第一个输入框中的值
  2. 当第2个输入框失去焦点时, 提示这个输入框中的值

3.3.2 refs属性

  1. 组件内的标签都可以定义ref属性来标识自己
    a. <input type="text" ref={input => this.msgInput = input}/>
    b. 回调函数在组件初始化渲染完或卸载时自动调用

  2. 在组件中可以通过this.msgInput来得到对应的真实DOM元素

  3. 作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据

3.3.3 事件处理

  1. 通过onXxx属性指定组件的事件处理函数(注意大小写)
    a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
    b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
  2. 通过event.target得到发生事件的DOM元素对象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target  //返回input对象
}

3.3.4 强烈注意

  1. 组件内置的方法中的this为组件对象

  2. 在组件类中自定义的方法中this为null
    a. 强制绑定this: 通过函数对象的bind()
    b. 箭头函数(ES6模块化编码时才能使用)

3.3.5 代码实例

<body>
<div id="example1"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 事件 与 ref* 需求:自定义组件,功能说明* 1、界面如图所示* 2、点击按钮,提示第一个输入框中的值* 3、当第二个输入框失去焦点时,提示这个输入框中的值*/// 1、创建组件class MyComponent extends React.Component {constructor(props) {super(props)this.showInput = this.showInput.bind(this)this.handleBlur = this.handleBlur.bind(this)}showInput() {const value = this.refs.content.value;alert(value)alert(this.input.value)}// 事件都有一个固定的形参handleBlur(event) {console.log(event)console.log(event.target)   //指的是标签// event.target : 指的是 input 表单框alert(event.target.value)}/* 最后一个比较特别,操作的 dom 元素,是发生事件的元素。*/render() {return (<div><input type="text" ref="content"/> &nbsp;&nbsp;<input type="text" ref={input => this.input = input}/> &nbsp;&nbsp;<button onClick={this.showInput}>提升输入</button>&nbsp;&nbsp;<input type="text" onBlur={this.handleBlur} placeholder="失去焦点提示内容"/></div>)}}// 2、渲染组件ReactDOM.render(<MyComponent/>, document.getElementById("example1"))
</script>
</body>

展示:

3.3.6 步骤、技术点

大体步骤与前一样

  1. 点击事件要在constructor构造器中进行bind()方法绑定。
  2. ref使用方法一:ref属性的value值为唯一值,然后在点击事件中 通过 this.refs.ref属性名获取
  3. ref使用方法二:ref属性的value值为回调函数{input => this.inputMsg = input},返回一个,然后在点击事件中 通过 this.inputMsg 获取

六、组件的组合

6.1 需求描述

功能: 组件化实现此功能

  1. 显示所有todo列表
  2. 输入文本, 点击按钮显示到列表的首位, 并清除输入的文本

6.2 代码实例

<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 界面中有一个文本框和按钮,按钮中显示下面的几个数据* 下面是一个 ul 列表,默认遍历 数组中的数据。* 事件:点击按钮,文本框中的数据出现在下面中的 ul 列表中*//***问题:数据保存在哪个组件内?*     看数据是某个组件需要(给它),还是某些组件需要(给共同的父组件)*问题2:需要在子组件中改变父组件的状态*      子组件不能直接改变父组件的状态*      状态在哪个组件,更新状态的行为(方法)就应该定义在哪个组件*      解决:父组件定义函数,传递给子组件,子组件调用**组件化编写功能的流程*      1、拆分组件*      2、实现静态组件(只有静态界面,没有动态数据和交互)*      3、实现动态组件*          1)实现初始化数据动态显示*          2) 实现交互功能*/// 主界面class Counter extends React.Component {constructor(props) {super(props)// 初始化状态this.state = {todos: ['吃饭', '睡觉', '打豆豆']}this.addTodos = this.addTodos.bind(this)}// 定义一个添加的函数addTodos(todo) {// this.state.todos.unshift(todo)  //不能这么做const {todos} = this.statetodos.unshift(todo)// 更新状态this.setState({todos})}render() {const {todos} = this.statereturn (<div><h1>Simple TODO List</h1><Add count={todos.length} addTodos={this.addTodos}/><List todos={todos}/></div>)}}// 子界面class Add extends React.Component {constructor(prop) {super(prop)this.addData = this.addData.bind(this)}render() {return (<div><input type="text" ref={input => this.todoInput = input}/><button onClick={this.addData}>add # {this.props.count + 1} </button></div>)}addData() {// 1、读取输入的数据const data = this.todoInput.value.trim();// 2、检查合法性if (!data) {return}// 3、添加console.log(data)this.props.addTodos(data)// 4、清除输入this.todoInput.value = ''}}// 数据校验,放在上面出错Add.propTypes = {count: PropTypes.number.isRequired,addTodos: PropTypes.func.isRequired}// 子界面class List extends React.Component {render() {const {todos} = this.props;/* => : 箭头函数的意义,有两个:函数、return, 这里如果加 {}:方法体 的话,里面一定要有 return*//*todos.map((value, index)=><li key={index}>{value}</li>)*/return (<div><ul>{todos.map((value, index) => {return <li key={index}>{value}</li>})}</ul></div>)}}List.propTypes = {todos: PropTypes.array.isRequired}ReactDOM.render(<Counter/>, document.getElementById('example'))
</script>
</body>

6.3 技术点(注意:数据在哪,操作方法就在哪)

  1. 设计三个组件,一个主页面Counter、一个添加页面Add、一个列表页面List
  2. state数据在主页面中,todos数组会传给List组件,todos长度、添加的方法addTodos()会传给Add组件。
  3. 注意,方法也可以作为数据传给子组件。通过this.props进行接收。
  4. 在Add组件中调用父组件的添加方法。
  5. 在List组件中通过this.props.todos 获取数据,然后在render()方法中进行遍历渲染出来。

6.4 React工具使用,查看三个属性

在Google中安装扩展软件,安装React扩展工具。可以查看自己定义的组件,以及三大属性,其实只能看到state和props,这两个是在组件上,ref是在标签上,这个只能在元素中查看。
看截图:
Counter类组件

Add类组件

6.5 功能界面的组件化编码流程(无比重要)

  1. 拆分组件: 拆分界面,抽取组件

  2. 实现静态组件: 使用组件实现静态页面效果

  3. 实现动态组件
    a. 动态显示初始化数据
    b. 交互功能(从绑定事件监听开始)

七、收集表单数据

7.1 需求描述

需求: 自定义包含表单的组件

  1. 输入用户名密码后, 点击登陆提示输入信息
  2. 不提交表单

7.2 理解

  1. 问题: 在react应用中, 如何收集表单输入数据

  2. 包含表单的组件分类
    a. 受控组件: 表单项输入数据能自动收集成状态
    b. 非受控组件: 需要时才手动读取表单输入框中的数据

7.3 代码实例

<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 需求: 自定义包含表单的组件*  1、界面如下所示*  2、输入用户名密码后,点击登陆提示输入信息*  3、不提交表单  event.preventDefault()*/class LoginForm extends React.Component {constructor(prop) {super(prop)this.state = {pwd: ''}this.handleLogin = this.handleLogin.bind(this)this.handleChange = this.handleChange.bind(this)}render() {return (/*** 用户名 为非受控组件* 密码 为受控组件*/<form action="/test" onSubmit={this.handleLogin}>用户名:<input type="text" ref={input => this.username = input}/>密码: <input type="password" value={this.state.pwd} ref={input => this.password = input}onChange={this.handleChange}/><input type="submit" value="登陆"/></form>)}handleLogin(event) {const uname = this.username.value  // 操作DOMconst {pwd} = this.state           // 操作react 属性alert(`准备提交的用户名为${uname}, 密码${pwd}`)// 阻止事件的默认行为(提交)event.preventDefault()}handleChange(event) {// 读取输入框的值const password = event.target.value// 更新pwd的状态this.setState({pwd: password})}}ReactDOM.render(<LoginForm/>, document.getElementById('example'))
</script>
</body>

页面:

7.4 步骤、技术点

步骤与前一致

  1. 这里需要理解**受控组件和非受控组件**。
  2. 受控组件:通过onChange()事件,将input值与state的值链接起来,进行统一。

八、组件生命周期

8.1 需求效果

需求: 自定义组件

  1. 让指定的文本做显示/隐藏的渐变动画
  2. 切换持续时间为2S
  3. 点击按钮从界面中移除组件界面

8.2 理解

  1. 组件对象从创建到死亡它会经历特定的生命周期阶段
  2. React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调
  3. 我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作

8.3 生命周期流程图

8.4 生命周期详述

  1. 组件的三个生命周期状态:

    • Mount:插入真实 DOM
    • Update:被重新渲染
    • Unmount:被移出真实 DOM
  2. React 为每个状态都提供了勾子(hook)函数
    • componentWillMount()(舍弃)
    • componentDidMount()
    • componentWillUpdate()
    • componentDidUpdate()
    • componentWillUnmount()
  3. 生命周期流程:
    a. 第一次初始化渲染显示: ReactDOM.render()

    • constructor(): 创建对象初始化state
    • componentWillMount() : 将要插入回调
    • render() : 用于插入虚拟DOM回调
    • componentDidMount() : 已经插入回调
      b. 每次更新state: this.setSate()
    • componentWillUpdate() : 将要更新回调
    • render() : 更新(重新渲染)
    • componentDidUpdate() : 已经更新回调
      c. 移除组件: ReactDOM.unmountComponentAtNode(containerDom)
    • componentWillUnmount() : 组件将要被移除回调

8.5 重要的勾子

  1. render(): 初始化渲染或更新渲染调用
  2. componentDidMount(): 开启监听, 发送ajax请求
  3. componentWillUnmount(): 做一些收尾工作, 如: 清理定时器
  4. componentWillReceiveProps(): 后面需要时讲

九、虚拟DOM与DOM Diff算法

9.1 代码实例

class HelloWorld extends React.Component {constructor(props) {super(props)this.state = {date: new Date()}}componentDidMount () {setInterval(() => {this.setState({date: new Date()})}, 1000)}render () {console.log('render()')return (<p>Hello, <input type="text" placeholder="Your name here"/>!&nbsp;It is {this.state.date.toTimeString()}</p>)}
}ReactDOM.render(<HelloWorld/>,document.getElementById('example')
)

9.2 基本原理图

十、react引用(基于react脚手架)

10.1 使用create-react-app创建react应用

10.1.1 react脚手架

  1. xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
    a. 包含了所有需要的配置
    b. 指定好了所有的依赖
    c. 可以直接安装/编译/运行一个简单效果

  2. react提供了一个用于创建react项目的脚手架库: create-react-app

  3. 项目的整体技术架构为: react + webpack + es6 + eslint

  4. 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化

10.1.2 创建项目并启动

npm install -g create-react-app
create-react-app hello-react
cd hello-react
npm start

10.1.3 react脚手架项目结构

ReactNews|--node_modules---第三方依赖模块文件夹|--public|-- index.html-----------------主页面|--scripts|-- build.js-------------------build打包引用配置|-- start.js-------------------start运行引用配置|--src------------源码文件夹|--components-----------------react组件|--index.js-------------------应用入口js|--.gitignore------git版本管制忽略的配置|--package.json----应用包配置文件 |--README.md-------应用描述说明的readme文件

10.2 项目结构


项目入口 js index.js

10.2 demo:评论管理

效果:

拆分组件:
应用组件: App

  • state: comments/array
    添加评论组件: CommentAdd
  • state: username/string, content/string
  • props: add/func
    评论列表组件: CommentList
  • props: comment/object, delete/func, index/number
    评论项组件: CommentItem
  • props: comments/array, delete/func

实现静态组件

实现动态组件

  1. 动态展示初始化数据
  • 初始化状态数据
  • 传递属性数据
  1. 响应用户操作, 更新组件界面
  • 绑定事件监听, 并处理
  • 更新state

10.3 demo:评论管理

项目目录:

代码上库啦。

十一、react ajax

11.1 理解

11.1.1 前置说明

  1. React本身只关注于界面, 并不包含发送ajax请求的代码
  2. 前端应用需要通过ajax请求与后台进行交互(json数据)
  3. react应用中需要集成第三方ajax库(或自己封装)

11.1.2 常用的ajax请求库

  1. jQuery: 比较重, 如果需要另外引入不建议使用

  2. axios: 轻量级, 建议使用
    a. 封装XmlHttpRequest对象的ajax
    b. promise风格
    c. 可以用在浏览器端和node服务器端

  3. fetch: 原生函数, 但老版本浏览器不支持
    a. 不再使用XmlHttpRequest对象提交ajax请求
    b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js

11.1.3 效果

需求:

  1. 界面效果如下
  2. 根据指定的关键字在github上搜索匹配的最受关注的库
  3. 显示库名, 点击链接查看库
  4. 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
    在这里插入图片描述

11.1.4 代码实例

<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
<script type="text/babel">/*** 需求:* 1、界面效果如下,* 2、根据指定的关键字在GitHub上搜索匹配的最受关注的库* 3、显示库名,点击链接查看库* 4、测试接口:https://api.github.com/search/repositories?q=r&sort=stars*/class MostStarRepo extends React.Component {state = {repoName: '',repoUrl: ''}// 最后发请求componentDidMount() {// 使用 axios 发送 异步的Ajax 请求  re:可以改变可以传  sort=stars:排序模式const url = 'https://api.github.com/search/repositories?q=re&sort=stars'axios.get(url).then(response => {const result = response.dataconsole.log(response);// 得到数据const {name, html_url} = result.items[0]// 更新状态this.setState({repoName: name,repoUrl: html_url})})// 错误信息.catch(error => {alert(error.message)})// 使用 fetch 发送异步的 Ajax 请求/*fetch(url).then(response => {return response.json()}).then(data => {// 得到数据const {name, html_url} = data.items[0]// 更新状态this.setState({repoName: name,repoUrl: html_url})})*/}render() {const {repoName, repoUrl} = this.stateif (!repoName) {return <h2>Loading</h2>} else {return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>}}}ReactDOM.render(<MostStarRepo/>, document.getElementById('example'))
</script>
</body>

11.2 axios

11.2.1 文档

https://github.com/axios/axios

11.2.1 相关API

  1. GET请求
axios.get('/user?ID=12345').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});axios.get('/user', {params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});
  1. POST请求
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'
})
.then(function (response) {console.log(response);
})
.catch(function (error) {console.log(error);
});

11.3 demo: github users

11.3.1 需求描述

11.3.2 拆分组件

App

  • state: searchName/string
    Search
  • props: setSearchName/func

List

  • props: searchName/string
  • state: firstView/bool, loading/bool, users/array, errMsg/string

11.3.3 代码实例

上库啦······ 库中代码为:13_react-app

  1. 编写静态组件
  2. 编写动态组件:componentWillReceiveProps(nextProps): 监视接收到新的props, 发送ajax
    使用axios库发送ajax请求

11.4 Fetch

11.4.1 文档

  1. https://github.github.io/fetch/
  2. https://segmentfault.com/a/1190000003810652

11.4.2 相关API

  1. GET请求
fetch(url).then(function(response) {return response.json()
}).then(function(data) {console.log(data)
}).catch(function(e) {console.log(e)
});
  1. POST请求
fetch(url, {method: "POST",body: JSON.stringify(data),
}).then(function(data) {console.log(data)
}).catch(function(e) {console.log(e)
})

十二、几个重要技术总结

12.1 组件间通信

12.1.1 方式一: 通过props传递

  1. 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
  2. 通过props可以传递一般数据和函数数据, 只能一层一层传递
  3. 一般数据–>父组件传递数据给子组件–>子组件读取数据
  4. 函数数据–>子组件传递数据给父组件–>子组件调用函数

12.1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制

  1. 工具库: PubSubJS
  2. 下载: npm install pubsub-js --save
  3. 使用:
    import PubSub from ‘pubsub-js’ //引入
    PubSub.subscribe(‘delete’, function(data){ }); //订阅
    PubSub.publish(‘delete’, data) //发布消息

12.1.3 方式三: redux

后面专门讲解

12.2 事件监听理解

12.2.1 原生DOM事件

  1. 绑定事件监听
    a. 事件名(类型): 只有有限的几个, 不能随便写
    b. 回调函数
  2. 触发事件
    a. 用户操作界面
    b. 事件名(类型)
    c. 数据()

12.2.2 自定义事件(消息机制)

  1. 绑定事件监听
    a. 事件名(类型): 任意
    b. 回调函数: 通过形参接收数据, 在函数体处理事件
  2. 触发事件(编码)
    a. 事件名(类型): 与绑定的事件监听的事件名一致
    b. 数据: 会自动传递给回调函数

12.3 ES6常用新语法

  1. 定义常量/变量: const/let
  2. 解构赋值: let {a, b} = this.props import {aa} from ‘xxx’
  3. 对象的简洁表达: {a, b}
  4. 箭头函数:
    a. 常用场景
    组件的自定义方法: xxx = () => {}
    参数匿名函数
    b. 优点:
    简洁
    没有自己的this,使用引用this查找的是外部this
  5. 扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)
  6. 类: class/extends/constructor/super
  7. ES6模块化: export default | import

十三、react-router

13.1 项目理解

13.1.1 react-router的理解

  1. react的一个插件库
  2. 专门用来实现一个SPA应用
  3. 基于react的项目基本都会用到此库

13.1.2 SPA的理解

  1. 单页Web应用(single page web application,SPA)
  2. 整个应用只有一个完整的页面
  3. 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求
  4. 当点击路由链接时, 只会做页面的局部更新
  5. 数据都需要通过ajax请求获取, 并在前端异步展现

13.1.3 路由的理解

  1. 什么是路由?
    a. 一个路由就是一个映射关系(key:value)
    b. key为路由路径, value可能是function/component

  2. 路由分类
    a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
    b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件

  3. 后台路由
    a. 注册路由: router.get(path, function(req, res))
    b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据

  4. 前端路由
    a. 注册路由: < Route path="/about" component={About}>
    b. 当浏览器的hash变为#about时, 当前路由组件就会变为About组件

13.1.4 前端路由的实现

  1. history库
    a. 网址: https://github.com/ReactTraining/history
    b. 管理浏览器会话历史(history)的工具库
    c. 包装的是原生BOM中window.history和window.location.hash

  2. history API
    a. History.createBrowserHistory(): 得到封装window.history的管理对象
    b. History.createHashHistory(): 得到封装window.location.hash的管理对象
    c. history.push(): 添加一个新的历史记录
    d. history.replace(): 用一个新的历史记录替换当前的记录
    e. history.goBack(): 回退到上一个历史记录
    f. history.goForword(): 前进到下一个历史记录
    g. history.listen(function(location){}): 监视历史记录的变化

13.2 react-router相关API

13.2.1 react-router组件

<BrowserRouter>
<HashRouter>
<Route>
<Redirect>
<Link>
<NavLink>
<Switch>

13.2.2 其它

  1. history对象
  2. match对象
  3. withRouter函数

13.3 基本路由使用

13.3.1 效果

13.3.2 准备

  1. 下载react-router: npm install --save react-router@4
  2. 引入bootstrap.css: <link rel="stylesheet" href="/css/bootstrap.css">

13.4 嵌套路由使用

13.4.1 效果

13.5 向路由组件传递参数数据

13.5.1 效果

13.6 多种路由跳转方式(重要)

  1. 一种为标签方式跳转
  2. 一种为事件方式跳转:添加事件,需要借助history对象

原来没加router时,组件的属性有 props、state
加上route时,在Route下的组件上,有了history、location、match三个对象。

13.6.1 效果

13.6.2 代码实例

都上库啦。
代码为 14_react_router,三级路由都在这一个项目中。

十四、React UI

14.1 最流行的开源React UI组件库

14.1.1 material-ui(国外)

  1.  官网: http://www.material-ui.com/#/
    
  2.  github: https://github.com/callemall/material-ui
    

14.1.2 ant-design(国内蚂蚁金服)

  1.  PC官网: https://ant.design/index-cn
    
  2. 移动官网: https://mobile.ant.design/index-cn
  3.  Github: https://github.com/ant-design/ant-design/
    
  4. Github: https://github.com/ant-design/ant-design-mobile/

14.2 ant-design-mobile使用入门

14.2.1 效果

14.2.2 使用create-react-app创建react应用

npm install create-react-app -g
create-react-app antm-demo
cd antm-demo
npm start

14.2.3 搭建antd-mobile的基本开发环境

  1.  下载
    

npm install antd-mobile --save

  1. src/App.jsx
import React, {Component} from 'react'
// 分别引入需要使用的组件
import Button from 'antd-mobile/lib/button'
import Toast from 'antd-mobile/lib/toast'export default class App extends Component {handleClick = () => {Toast.info('提交成功', 2)}render() {return (<div><Button type="primary" onClick={this.handleClick}>提交</Button></div>)}
}
  1.  src/index.js
    
import React from 'react';
import ReactDOM from 'react-dom'
import App from "./App"
// 引入整体css
import 'antd-mobile/dist/antd-mobile.css'ReactDOM.render(<App />, document.getElementById('root'))
  1.  index.html
    
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /><script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
<script>if ('addEventListener' in document) {document.addEventListener('DOMContentLoaded', function() {FastClick.attach(document.body);}, false);}if(!window.Promise) {document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');}
</script>

7.2.4. 实现按需打包(组件js/css)

  1. 下载依赖包
    yarn add react-app-rewired customize-cra babel-plugin-import --save

  2. 修改默认配置:
    package.json

"scripts": {"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test --env=jsdom"
}
  1. config-overrides.js
const {injectBabelPlugin} = require('react-app-rewired');
module.exports = function override(config, env) {config = injectBabelPlugin(['import', {libraryName: 'antd-mobile', style: 'css'}], config);return config;
};
  1. 编码
// import 'antd-mobile/dist/antd-mobile.css'// import Button from 'antd-mobile/lib/button'
// import Toast from 'antd-mobile/lib/toast'
import {Button, Toast} from 'antd-mobile'

扩展,数组方法

1. map()

遍历数组

/**
* 功能:动态展示列表数据
*
* 问题:如何将一个数据的数组 转换为 一个标签的数组   很常用
*      使用数组的map() 方法 和 箭头函数
* */
const names = ['jQuery', 'zepto', 'angular', 'react', 'vue']// 1、创建虚拟DOM// li 标签一定要带 key属性,而且还不能一样 否则警告const ul = (<ul>{names.map(name=> <li key={name}>{name}</li>)}</ul>)

2. unshift()

在数组的头部添加新值

3. splice()

splice(value, 1):删除
splice(value, 0, value2):替换
splice(value): 添加

4. filter()

过滤数组,将下标不等于0的过滤掉,返回一个新的数组。

const comments = [{username: 'Tom', content: 'React 挺好的!'},{username: 'Jack', content: 'React 挺简单的!'}
];state.filter((comment, index) => {return (index !== 0)
});

react学习笔记一:入门级小白到脚手架(create-react-app)开发项目相关推荐

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

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

  2. 学习笔记(2):uni-app实战社区交友类app开发-引入css动画库

    立即学习:https://edu.csdn.net/course/play/28009/381722?utm_source=blogtoedu 1.  百度搜索并打开  animate.css  . ...

  3. 学习笔记(1):uni-app实战社区交友类app开发-引入自定义图标库

    立即学习:https://edu.csdn.net/course/play/28009/381721?utm_source=blogtoedu 1. 在iconfont.cn图标库中打包下载图标文件压 ...

  4. react学习笔记1--基础知识

    什么是react A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES[React是一个用于构建用户界面的JavaScript库.] React之所以快, ...

  5. react render没更新_web前端教程分享React学习笔记(一)

    web前端教程分享React学习笔记(一),React的起源和发展:React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写 ...

  6. react组件卸载调用的方法_好程序员web前端培训分享React学习笔记(三)

    好程序员web前端培训分享React学习笔记(三),组件的生命周期 React中组件也有生命周期,也就是说也有很多钩子函数供我们使用, 组件的生命周期,我们会分为四个阶段,初始化.运行中.销毁.错误处 ...

  7. React学习笔记:入门案例

    React学习笔记:入门案例 React 起源于 Facebook 内部项目,因为市场上所有 JavaScript MVC 框架都不令人满意,公司就决定自己写一套,用来架设 Instagram 的网站 ...

  8. React学习笔记(五) 状态提升

    状态提升究竟是什么东西呢?别急,下面让我们一步一步来看看究竟要怎么使用状态提升 假设我们有这样一个需求,提供两个输入框(分别属于两个组件),保证输入框里面的内容同步 好,下面我们先来封装一个输入框组件 ...

  9. React学习笔记 - 组件Props

    React Learn Note 4 React学习笔记(四) 标签(空格分隔): React JavaScript 三.组件&Props 组件可以将UI切分成一些独立的.可复用的部件,这样你 ...

最新文章

  1. matlab计算方程fsolve,matlab中关于fsolve解非线性方程组的问题
  2. 【企业管理】摆脱三个依赖
  3. python3精要(51)--抛出异常与自定义异常
  4. R语言观察日志(part4)--paste函数
  5. file协议访问linux,Mozilla Firefox for Android 'file'协议未授权访问漏洞(CVE-2014-1501)
  6. int转unsigned int_谢劲课题组在基于锰催化的转金属化基元反应取得系列进展
  7. 分库分表全面了解分析
  8. JVM学习-类文件结构
  9. dc综合与pt静态时序分析(中文)_新能源汽车小三电系统(PDU/DC/OBC)技术研究详解...
  10. [转载]Yahoo!的分布式数据平台PNUTS简介及感悟
  11. java submit execute_ExecutorService中submit和execute的区别
  12. matlab GUI页面 科学计算器代码
  13. 操作系统——进程间通信
  14. pdf照片显示正常打印时被翻转_【20考研】现场确认完没事了?!准考证打印别大意!...
  15. word2010计算机实验报告,Word2010计算机实验报告--
  16. 电阻式温度计 - 铂电阻温度计 - PT100
  17. 体绘制加速技术之数据异步传输
  18. 计算机显示器不亮灯,电脑液晶显示器指示灯不亮是为什么?
  19. adams功能区不显示_基于ADAMS对初始角和相位角修改模拟力矩波动
  20. ASP.NET统计在线人数

热门文章

  1. RH850从0搭建Autosar开发环境【1】- 如何创建Davinci Configurator配置工程
  2. Pyecharts数据可视化之折线图(阶梯图、平滑曲线图、面积图)、K线图、常用配置项
  3. 编译原理——语法分析器(C/C++代码实现)
  4. Mac OS 10.15 修改登录壁纸
  5. 使用three.js + geojson 完成广西地图的绘制(上篇)
  6. 【低功耗蓝牙】② 蓝牙状态切换和事件处理
  7. Hive 数据倾斜问题定位排查及解决(实际案例)
  8. mysql查询总成绩高于240_Egret应用开发实践(02) MVC 模块化 - SegmentFault 思否
  9. 一个简单的SQL注入攻击
  10. opencv图像对齐与图像相减python