React

React 是⼀个申明式,⾼效且灵便的⽤于构建⽤户界⾯的 JavaScript 库。使⽤ React 能够将⼀ 些简短、独⽴的代码⽚段组合成简单的 UI 界⾯,这些代码⽚段被称作“ 组件” 。

MVC与MVVM

  • MVC

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计榜样,用一种业务逻辑、数据、界面显示拆散的办法组织代码,将业务逻辑汇集到一个部件外面,在改良和个性化定制界面及用户交互的同时,不须要从新编写业务逻辑。MVC被独特的倒退起来用于映射传统的输出、解决和输入性能在一个逻辑的图形化用户界面的构造中。

这里次要讲的是前端的MVC实现,不要跟后端的MVC搞混了。它的目标是:

  1. 代码复用;
  2. 划分职责,不便前期保护;

Model(模型):负责保留利用数据,与后端数据进行同步

View(视图):负责视图展现,将model中的数据可视化

Controller(控制器):负责业务逻辑,依据用户行为对Model数据进行批改

// modelvar myapp = {}; // 创立这个应⽤对象myapp.Model = function() {  var val = 0;  this.add = function(v) {    if (val < 100) val += v; };  this.sub = function(v) {    if (val > 0) val -= v; };  this.getVal = function() {    return val; };  /* 观察者模式 */  var self = this,      views = [];  this.register = function(view) {    views.push(view); };  this.notify = function() {    for(var i = 0; i < views.length; i++) {        views[i].render(self);   } };};// viewmyapp.View = function(controller) {  var $num = $('#num'),      $incBtn = $('#increase'),      $decBtn = $('#decrease');  this.render = function(model) {      $num.text(model.getVal() + 'rmb'); };  /* 绑定事件 */  $incBtn.click(controller.increase);    $decBtn.click(controller.decrease);};// controllermyapp.Controller = function() {  var model = null,      view = null;  this.init = function() {    /* 初始化Model和View */    model = new myapp.Model();    view = new myapp.View(this);    /* View向Model注册,当Model更新就会去告诉View啦 */    model.register(view);    model.notify(); };  /* 让Model更新数值并告诉View更新视图 */  this.increase = function() {    model.add(1);    model.notify(); };  this.decrease = function() {    model.sub(1);    model.notify(); };};// init(function() {  var controller = new myapp.Controller();  controller.init();})();
  • MVVM

MVVM:Model、View、ViewModel。

总结

  • 这二者都是框架的设计模式,设计的目标都是为了解决Model和View的耦合问题
  • MVC呈现比拟早次要利用在后端,如Spring MVC、ASP.NET MVC等,在前端畛域晚期也有利用,如Backbone.js。长处是分层清晰,缺点是数据流凌乱,灵活性带来的保护问题。
  • MVVM在前端畛域有广泛应用,它不仅解决了MV耦合问题,还同时解决了保护二者映射关系的大量繁冗代码和DOM操作代码,在进步开发效率、可读性同时还放弃了优越的性能体现。

JSX语法

JSX称为JS的语法扩大,将UI与逻辑层耦合在组件⾥,⽤{}标识

因为 JSX 语法上更靠近 JS ⽽不是 HTML,所以使⽤ camelCase(⼩驼峰命名)来定义属性的名称; JSX ⾥的 class 变成了 className,⽽ tabindex 则变为 tabIndex。

生命周期

由上图可知,React 16.8+的生命周期分为三个阶段,别离是挂载阶段更新阶段卸载阶段

当你应用生命周期钩子时候,你怎么优化?

React 16之后有三个生命周期被废除:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

挂载阶段

  • constructor

    如果不初始化 state 或不进⾏⽅法绑定,则不须要为 React 组件实现构造函数。

    • 通过给 this.state 赋值对象来初始化外部 state。
    • 为事件处理函数绑定实例
  • getDerivedStateFromProps

    静态方法,当接管到新的props去更新state时,能够应用getDerivedStateFromProps

  • render

    纯函数,只返回须要渲染的货色,不应该蕴含其它的业务逻辑,能够返回原生的DOM、React组件、Fragment、Portals、字符串和数字、Boolean和null等内容

  • componentDidMount

    组件挂载之后调用,能够操作dom与网络申请

更新阶段

  • getDerivedStateFromProps 此办法在更新挂载阶段都可能会调用
  • shouldComponentUpdate shouldComponentUpdate(nextProps, nextState),有两个参数nextPropsnextState,示意新的属性和变动之后的state,返回一个布尔值,true示意会触发从新渲染,false示意不会触发从新渲染,默认返回true,咱们通常利用此生命周期来优化React程序性能
  • render: 更新阶段也会触发此生命周期
  • getSnapshotBeforeUpdate getSnapshotBeforeUpdate(prevProps, prevState),这个办法在render之后,componentDidUpdate之前调用,有两个参数prevPropsprevState,示意之前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate,如果你不想要返回值,能够返回null,此生命周期必须与componentDidUpdate搭配应用
  • componentDidUpdate componentDidUpdate(prevProps, prevState, snapshot),该办法在getSnapshotBeforeUpdate办法之后被调用,有三个参数prevPropsprevStatesnapshot,示意之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的,如果触发某些回调函数时须要用到 DOM 元素的状态,则将比照或计算的过程迁徙至getSnapshotBeforeUpdate,而后在 componentDidUpdate中对立触发回调或更新状态。

卸载阶段

  • componentWillUnmount 当组件被卸载或者销毁了就会调用,咱们能够在这个函数里去革除一些定时器,勾销网络申请,清理有效的DOM元素等垃圾清理工作。
  • UNSAFE_componentWillMount

UNSAFE_componentWillMount() 在挂载之前被调⽤; 它在 render() 之前调⽤,因而在此⽅法中同步调⽤ setState() 不会⽣效; 需要的话⽤componentDidMount代替。

  • UNSAFE_componentWillReceiveProps

UNSAFE_componentWillReceiveProps() 会在已挂载的组件接管新的 props 之前被调⽤; 如果你须要更新状态以响应 prop 更改(例如,重置它),你能够⽐较 this.props 和 nextProps 并在此 ⽅法中使⽤ this.setState() 执⾏ state 转换。

  • UNSAFE_componentWillUpdate

    • 当组件收到新的 props 或 state 时,会在渲染之前调⽤ UNSAFE_componentWillUpdate();
    • 使⽤此作为在更新发⽣之前执⾏筹备更新的机会;
    • 初始渲染不会调⽤此⽅法;

事件处理

  1. this绑定问题:在用户自定义的函数中没有this。
  2. React的数据流是单向的,没有数据绑定。

留神:

  • React 事件的命名采纳小驼峰式(camelCase),而不是纯小写。且事件名称之后不能加 (),否则会间接执行
  • 不能通过返回 false 的形式阻止默认行为。必须显式的应用 preventDefault

React组件中的事件处理函数

  1. constructor函数中bind
class ReactEvent extends Component {     constructor(props) {         super(props);         //强制绑定        this.handleClick = this.handleClick.bind(this);     }     handleClick() {         console.log('Click');     }     render() {     return <button onClick={this.handleClick}>Click Me</button>;     } }
  1. 应用箭头函数
  • render中应用箭头函数
class ReactEvent extends Component {     handleClick() {         console.log('Click');     }     render() {         return <button onClick={() => this.handleClick()}>Click Me</button>;     } }
  • 应用class fields语法
class ReactEvent extends Component {     //此函数会被绑定到ReactEvent类的实例     handleClick = () => {         console.log('Click');     }     render() {         return <button onClick={this.handleClick}>Click Me</button>;     } }
  • 在render中应用bind
class ReactEvent extends Component {     handleClick() {         console.log('Click');     }     render() {         return <button onClick={this.handleClick.bind(this)}>Click Me</button>;     } }

参考文章

  • MVC、MVP和MVVM
  • React生命周期示意图
  • React生命周期