React
React 是?个声明式,?效且灵活的?于构建?户界?的 JavaScript 库。使? React 可以将? 些简短、独?的代码?段组合成复杂的 UI 界?,这些代码?段被称作“ 组件” 。MVC与MVVM
- MVC
文章图片
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
这里主要讲的是前端的MVC实现,不要跟后端的MVC搞混了。它的目的是:
- 代码复用;
- 划分职责,方便后期维护;
View(视图):负责视图展示,将model中的数据可视化
Controller(控制器):负责业务逻辑,根据用户行为对Model数据进行修改
文章图片
// model
var 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);
}
};
};
// view
myapp.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);
};
// controller
myapp.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 语法上更接近 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)
,有两个参数nextProps
和nextState
,表示新的属性和变化之后的state
,返回一个布尔值,true
表示会触发重新渲染,false
表示不会触发重新渲染,默认返回true
,我们通常利用此生命周期来优化React程序性能 - render: 更新阶段也会触发此生命周期
- getSnapshotBeforeUpdate
getSnapshotBeforeUpdate(prevProps, prevState)
,这个方法在render
之后,componentDidUpdate
之前调用,有两个参数prevProps
和prevState
,表示之前的属性和之前的state
,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate
,如果你不想要返回值,可以返回null,此生命周期必须与componentDidUpdate
搭配使用 - componentDidUpdate
componentDidUpdate(prevProps, prevState, snapshot)
,该方法在getSnapshotBeforeUpdate
方法之后被调用,有三个参数prevProps
,prevState
,snapshot
,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate
返回的,如果触发某些回调函数时需要用到 DOM 元素的状态,则将对比或计算的过程迁移至getSnapshotBeforeUpdate
,然后在componentDidUpdate
中统一触发回调或更新状态。
- componentWillUnmount 当组件被卸载或者销毁了就会调用,我们可以在这个函数里去清除一些定时器,取消网络请求,清理无效的DOM元素等垃圾清理工作。
- UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate
- 当组件收到新的 props 或 state 时,会在渲染之前调? UNSAFE_componentWillUpdate();
- 使?此作为在更新发?之前执?准备更新的机会;
- 初始渲染不会调?此?法;
- this绑定问题:在用户自定义的函数中没有this。
- React的数据流是单向的,没有数据绑定。
【【React】基础】注意::React组件中的事件处理函数
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。且事件名称之后不能加 (),否则会直接执行
- 不能通过返回 false 的方式阻止默认行为。必须显式的使用 preventDefault
- constructor函数中bind
class ReactEvent extends Component {
constructor(props) {
super(props);
//强制绑定
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click');
}
render() {
return ;
}
}
- 使用箭头函数
- render中使用箭头函数
class ReactEvent extends Component {
handleClick() {
console.log('Click');
}
render() {
return ;
}
}
- 使用class fields语法
class ReactEvent extends Component {
//此函数会被绑定到ReactEvent类的实例
handleClick = () => {
console.log('Click');
}
render() {
return ;
}
}
- 在render中使用bind
class ReactEvent extends Component {
handleClick() {
console.log('Click');
}
render() {
return ;
}
}
参考文章
- MVC、MVP和MVVM
- React生命周期示意图
- React生命周期