通俗讲React技术栈(整合篇)

React是用于构建页面的JavaScript 库(只关注于View)

构建用户界面,其实就是把数据展示出来。React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

为什么要学习React

当然是为了统一宇宙…这是不可能的.由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。也就是说React是最流行的一门框架
在社区方面,React由于诞生的较早,所以社区比较强大,一些常见的问题、坑、最优解决方案,文档、博客在社区中都是可以很方便就能找到的。而且是由强大Facebook进行维护的,安全可靠。


React的特点

声明式

React 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图,在数据改变时 React 也可以高效地更新渲染界面。

以前都是自己亲自操作dom,有了声明式,就是我们不用亲自做,只需去操作数据.

组件化

React 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图,在数据改变时 React 也可以高效地更新渲染界面。

  1. 什么是模块化?就是以代码的角度去分析问题;把我们的编程时候的业务逻辑;分割到不同的模块来进行开发,可以使代码重用,变量不会污染。
  2. 组件化:就是从UI的角度去分析;把一个页面;把一个页面去拆成互不相干的小组件。如果要实现一个页面,将需要的组件拼接在一起。方便了UI元素的重用,也就是说组件时元素的集合体

一次学习,随处编写

无论你现在正在使用什么技术栈,你都可以随时引入 React 开发新特性。

这里主要是React Native,混合应用,最接近原生应用;可以跨平台。体验会好一些;也能够调用硬件底层的API。

  1. 原生开发:它的英文单词是(NativeApp),指的就是使用 IOS、Android 官方提供的工具、开发平台、配套语言进行 手机App开发的方式;
  2. 混合开发:(HybirdApp)就是使用前端已有的技术,HTML + CSS + JS ,然后再搭配一些相关的打包编译技术,就能够开发出一个手机App,安装到手机中进行使用.

高效

虚拟Dom
  • DOM的本质是什么:就是用js表示的UI元素。Dom是由浏览器提供的功能,所以我们只能使用浏览器提供的API创建Dom对象
  • 虚拟DOM是我们程序员手动模拟的,并不是浏览器提供的
  • React通过一些API来创建一种特别的js对象,比如: React.createElement()就是一个简单的虚拟Dom
  • 虚拟DOM都会被React转化为真实的DOM.我们编码时只需要操作react虚拟DOM的相关数据,react会转化为真实dom变化更新界面
Diff算法

tree diff:新旧DOM树,逐层对比的方式,就叫做 tree diff,每当我们从前到后,把所有层的节点对比完后,必然能够找到那些 需要被更新的元素;

component diff:在对比每一层的时候,组件之间的对比,叫做 component diff;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件的类型不同,则立即将旧组件移除,新建一个组件,替换到被移除的位置;

element diff:在组件中,每个元素之间也要进行对比,那么,元素级别的对比,叫做 element diff;

单向数据流

React遵循从上到下的数据流向,即单向数据流。对于React来说:单向数据流与单一数据源限定了要想在组件中更新另一个组件的状态;需要进行状态提升。(可以类比vue利用$emit来子组件向父组件传值)

  1. 单向数据流的理解(简单的单向数据流)
    当用户访问了界面或则操作了界面,即view层;view发出用户交互了的action,此时action会对state或则说data进行更新,即model层;state更新了会触发view更新的过程。这样的数据总是单向流动的;便于推测和维护
  2. 单向数据流的特点
  • 所有状态的改变可记录、可跟踪,源头易追溯;
  • 组件的数据只要唯一的入口和出口,让组件更直观更容易理解使得组件更容易维护
  • 一旦数据变化,就去更新页面(data-页面),但是没有(页面-data)
  • 如果用户在页面上做了变动,那么就手动收集起来(双向是自动),合并到原有的数据中。
    React是单向数据绑定,而vue是双向数据绑定(比如v-model);当然vue也是单向数据流(vuex),只是实现了数据的双向绑定。

先了解一下组件的三大属性

state

  1. state是组件对象最重要的属性, 值是对象(可以包含多个数据)
  2. 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
  3. state是组件私有的数据,如果想要使用 组件中 state 上的数据,直接通过 this.state.key 来访问即可,key是属性;修改的话需要this.setState()进行修改
  constructor(props) {
    super(props)
    this.state = {
    }
  }

props

  • 每个组件对象都会有props(properties的简写)属性
  • 组件标签的所有属性都保存在props中
  • 通过标签属性从组件外向组件内传递变化的数据
    父组件
import React, { Component } from 'react';
// 子组件,使用props来接收值
function Child(props){
  return <div>{JSON.stringify(props)}</div>
}
// 父组件
class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      val:[
        {fatherValue:'这是我父组件内部的值,将其传给子组件',
        childValue:'我组件接收了来自父组件的值'}
      ]
    }
  }
  render() {
    return (
      <div className="App">
        <Child {...this.state.val[0]}></Child>
      </div>
    );
  }
}
  1. …是es6的扩展运算符;将对象的所有属性通过props传递
  2. 有些情况下,组件内部的值是必须的,所以我们尽量给组件内部定义一个默认值
  static defaultProps = {
    key:val
  }
  1. 使用props-type对props中的属性值进行类型限制和必要性限制
  static propTypes = {
    key: ReactTypes.string.isRequired 
  }

refs与事件处理

  1. 组件内的标签都可以定义ref属性来标识自己
<button ref={'btn'}>按钮</button>
  1. 在组件中可以通过this.refs来得到对应的真实DOM元素
  componentDidMount(){
    console.log(this.refs.btn)
  }
  1. 作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据

使用React

react和react-dom

react这套包,是专门用来创建React组件、组件生命周期等这些东西的;react-dom里面主要封装了和 DOM 操作相关的包,比如,要把 组件渲染到页面上.

cnpm i react react-dom -S
import React from 'react'
import ReactDOM from 'react-dom'
  1. 在 react 中,如要要创建 DOM 元素了,只能使用 React 提供的 JS API 来创建;React.createElement() 方法,用于创建 虚拟DOM 对象,它接收 3个及以上的参数
var myH1 = React.createElement('h1', null, '这是一个大大的H1')
  1. 使用reactDOM将元素渲染到界面上
ReactDOM.render(myH1, document.getElementById('app'))

JSX

  • 全称: JavaScript XML
  • react定义的一种类似于XML的JS扩展语法: XML+JS
  • 作用: 用来创建react虚拟DOM(元素)对象
  • 使用:浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行;还需要进行配置,使用option或则.babelrc进行配置
cnpm i babel-preset-react -D
  • jsx语法的本质:它不是字符串, 也不是HTML/XML标签;它最终产生的是一个JS对象;是以 React.createElement 的形式来实现的,并没有直接把 用户写的 HTML代码,渲染到页面上
  • 语法规则:当 编译引擎,在编译JSX代码的时候,如果遇到了<那么就把它当作 HTML代码去编译,如果遇到了 {} 就把 花括号内部的代码当作 普通JS代码去编译。
  • JSX必须被唯一的根元素包裹
var mydiv = <div>
  <h1 title={mytitle + 'aaaaa'}>当做HTML代码编译</h1>
  <p className="myp">如果要添加一个类,即class属性,必须使用className,因为class是关键字</p>
  <label htmlFor="">label标签的 for 属性需要替换为 htmlFor</label>
  {/* 这是多行注释,你肯定看不到我 */}
</div>

上面这是使用 jsx 语法创建的div元素;很好的诠释了语法规范。记住它,就记住了全世界…那是不可能的

创建组件的两种方式(React面向组件编程)

无状态组件

用构造函数创建出来的组件:专业的名字叫做“无状态组件”;本质上讲:就是无state属性

function MyComponent () {
  return <h2>工厂函数组件(简单组件)</h2>
}

如果要直接使用props,必须先定义,否则无法直接使用

export default function Hello(props) {
  return <p>haha --- {props.name}</p>
}
有状态组件

用class关键字创建出来的组件:专业的名字叫做“有状态组件”;本质上讲:就是有state属性

class MyComponent2 extends React.Component {
  render () {
    console.log(this) // MyComponent2的实例对象
    return <h2>ES6类组件(复杂组件)</h2>
  }
}
  • 在class定义的组件中,可以直接使用 this.props 来直接访问,不需要预先接收 props
  • 通过 extends 关键字,继承了 React.Component 之后,这个类,就是一个组件的模板了
  • 如果使用 extends 实现了继承,那么在 constructor 的第一行,一定要显示调用一下 super().表示对父类构造函数引用;在 constructor 中,如果想要访问 props 属性,不能直接使用 this.props, 而是需要在 constructor 的构造器参数列表中,显示的定义 props 参数来接收,才能正常使用。
  constructor(props) {
    super(props)
    this.state = {
    }
  }

prop和state的区别

state组件自身内部可变化的数据;可以使用setState修改数据,可读可写;props从组件外部向内部传递的数据;组件内部只读不修改


React生命周期函数

通俗讲React技术栈(整合篇)_第1张图片
感谢大家看到这里,可能大家已经开始从入门到…放弃;从开始到火化;为了将来能遨游太空,继续努力…

  1. 什么是组件的生命周期函数
    组件的创建,运行,销毁的过程中,总是伴随着各种各样的事件;这些在组件特定时期,触发的事件,叫做组件的生命周期,也是生命钩子

  2. 三个生命周期状态
    Mount:插入真实 DOM;Update:被重新渲染;Unmount:被移出真实 DOM

  3. 生命周期函数的流程

  • 第一次初始化渲染显示: ReactDOM.render()
    * constructor(): 创建对象初始化state
    * componentWillMount() : 将要插入回调
    * render() : 用于插入虚拟DOM回调
    * componentDidMount() : 已经插入回调
  • 每次更新state: this.setSate()
    * componentWillUpdate() : 将要更新回调
    * render() : 更新(重新渲染)
    * componentDidUpdate() : 已经更新回调
  • 移除组件: ReactDOM.unmountComponentAtNode(containerDom)
    * componentWillUnmount() : 组件将要被移除回调
  1. 生命周期钩子
    本图采用祖母绿,奶奶灰,妈妈红…扯远了。我使用文字和图形结合,这样图文结合更直观。
    通俗讲React技术栈(整合篇)_第2张图片

React脚手架

脚手架

用来帮助快速创建一个基于该框架的模板项目

  1. 包含了所有需要的配置
  2. 指定好了所有的依赖
  3. 可以直接安装/编译/运行一个效果

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

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

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

  1. 模块化: js是一个一个模块编写的
  2. 组件化: 界面是由多个组件组合编写实现的
  3. 工程化: 实现了自动构建/运行/打包的项目

Create React App

Create React App 是一个用于学习 React 的舒适环境,也是用 React 创建新的单页应用的最佳方式。

创建项目并启动

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

通俗讲React技术栈(整合篇)_第3张图片

  1. create-react-app 是一个全局的命令行工具用来创建一个新的项目
  2. react-scripts 是一个生成的项目所需要的开发依赖
  3. 脚本命令
    npm start启动项目,文件修改将会自动更新
    npm test在交互监视模式下启动测试运行程序
    npm run build在生产环境中编译代码,并放在build目录中,能够正确的打包代码,并且优化,压缩,使用hash重命名文件
    npm run eject这是一个单向操作,一旦你使用eject,那么就不能恢复了.如果你对create-react-app这个构建工具和配置项不满意,你可以在任何时候eject,从而导出可配置的模板.
  4. 项目结构
    /node_module/ 第三方依赖模块文件
    /public/ index.html是我们的主文件
    /src/ webpack编译的源码文件夹
    /.gotgnore/ git版本管制忽略的配置
    /package.json/ 应用包配置文件
    /README/ 应用描述说明的readme文件
    /yarn.lock/ 记录每一个依赖项的确切版本信息;


react ajax

说明
  1. React本身只关注于界面, 并不包含发送ajax请求的代码
  2. 前端应用需要通过ajax请求与后台进行交互(json数据)
  3. react应用中需要集成第三方ajax库(或自己封装)
常见的请求库
  1. axios
  • 封装XmlHttpRequest对象的ajax
  • promise风格
  • 可以用在浏览器端和node服务器端
axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
})
.then(function (response) {
  console.log(response);
})
.catch(function (error) {
  console.log(error);
});
  1. fetch
  • 原生函数, 但老版本浏览器不支持
  • 不再使用XmlHttpRequest对象提交ajax请求
  • 为了兼容低版本的浏览器, 可以引入兼容库fetch.js
fetch(url).then(function(response) {
  return response.json()
}).then(function(data) {
  console.log(data)
}).catch(function(e) {
  console.log(e)
});

路由

路由
  1. 一个路由就是一个映射关系(key:value)
  2. 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件
路由的实现
  • history库
    1. 管理浏览器会话历史(history)的工具库
    2. 包装的是原生BOM中window.history和window.location.hash
  • history API
    1. History.createBrowserHistory(): 得到封装window.history的管理对象
    2. History.createHashHistory(): 得到封装window.location.hash的管理对象
    3. history.push(): 添加一个新的历史记录
    4. history.replace(): 用一个新的历史记录替换当前的记录
    5. history.goBack(): 回退到上一个历史记录
    6. history.goForword(): 前进到下一个历史记录
    7. istory.listen(function(location){}): 监视历史记录的变化
React router

React-router提供了一些router的核心api,包括Router, Route, Switch等,但是它没有提供dom操作进行跳转的api。

React-router-dom

React-router-dom提供了BrowserRouter, Route, Link等api;我们可以通过dom的事件控制路由。例如点击一个按钮进行跳转,大多数情况下我们是这种情况,所以在开发过程中,我们更多是使用React-router-dom。

路由组件
  1. BrowserRouter:是路由的基本,也就是路由路由根容器.跟HashRouter二者选择其一,他的路径是没有‘#’哈希值的
  2. HashRouter:表示一个路由根容器,将来所有路由相关的东西,都要包裹在里面,而一个网站中;只需要使用一次就好了。在HashRouter只能有唯一一个根元素
  3. Route:表示一个路由规则,也是 一个占位符
  4. Redirect:重定向
  5. Link:表示一个路由链接
  6. NavLink:控制路由跳转的,不同于Link是NavLink的api更多
  7. Switch:Switch常常会用来包裹Route,它里面不能放其他元素,用来只显示一个路由。通俗来讲:使用 路由中的 Switch 组件,能够指定,如果前面的路由规则优先匹配到了,则放弃匹配后续的路由
  8. 其它:history对象、match对象、withRouter函数

React UI

material-uihttp://www.material-ui.com/#/)
mobile.ant.design
Ant Design of React


redux

redux是什么

  1. redux是一个独立专门用于做状态管理的JS库(不是react插件库)
  2. 可以用在react, angular, vue等项目中, 但基本与react配合使用
  3. 集中式管理react应用中多个组件共享的状态

先写到这里

文档参考

React的生命周期函数
create-react-app详解
yarn和npm
React配置跨域
fetch
react-router-dom
单向数据流和双向绑定各有什么优缺点
深入浅出React(四):虚拟DOM Diff算法解析
React 源码剖析系列 - 不可思议的 react diff
Promise
Promose神器

你可能感兴趣的:(react,react)