@llqintel
2017-02-14T02:15:12.000000Z
字数 4161
阅读 1653
前端
React并不是完整的MVC/MVVM框架,它专注与提供清晰,简洁的View层解决方案。但又与模板引擎不同,React还包括Controller
Vue算是MVVM?
与Vue区别?
Virtual DOM
DOM操作性能消耗较大,React把真实的DOM树转换成js对象树,即Virtual DOM。
每次数据更新后,重新计算VM,并和上次生成的VM对比,发生变化的部分做批量更新。React还提供了直观的shouldComponentUpdate,来减少不必要的VM对比。
优点
VM提升了React的性能,但DOM节点的比对也需要计算资源,所以提升不明显。
最大的好处就是方便和其他平台集成。
函数式编程
函数式编程
命令式:就像给电脑下命令(C,Java等)
声明式:整个过程变成构建在f函数作用在要处理的.. React把不断重复构建UI的过程抽象成组件,而且给定特定参数的情况下约定渲染对应的UI界面。
JSX语法
只允许一个标签被包裹
标签一定要闭合
DOM元素小写,组件元素首字母大写
注释 要用{}包裹起来
元素属性 class=>className for=>htmlFor
Boolean属性 使用属性表达式<Checkbox checked={false}/>
展开属性可以使用ES6 rest/spread
<C {...this.props}>
html转义
默认都是转义,防止XSS
//不转义<div dangerouslySetInnerHTML={{__html: 'cc© 2015'}}></div>
组件的演变
React组件与Web Components
组件设计
基本封装性生命周期的呈现明确的数据流动(参数)
Web Components组成部分
HTML TemplateCustom Elements 组件展示形式Shadow DOM 组件的作用域范围HTML Imports 新的引入方式
React组件
自定义元素是库自己创建的,与Web Components规范不通用包含了模板的概念,即jsx实现均在方法和类中,可以做到相互隔离,但不包括css遵循ES6 module规范
无状态组件
不存在state, 也没有生命周期方法。创建时始终保持了一个实例,避免了不必要的检查和内存分配,做到了内部优化。
没有shuouledComponentUpdate,每次都渲染
在React中,数据是自顶向下流动,即父元素到子元素。
setState是异步方法,一个生命周期内setState方法会合并操作。
智能组件:内部更新
木偶组件:外部更新
设计React组件时,一定要满足一个原则:直观。组件如果能分解,一定要分解。
React.Children.mapReact.cloneElement
Virtual DOM在内存中以对象的形式存在,如果想在这些对象上添加事件,非常简单。
注意点:JSX中必须以驼峰来书写事件名
实现机制
事件委托: 把所有事件绑定到最外层,使用一个统一的事件监听器。简化可事件的处理和回收机制,效率也有很大提升。自动绑定: 自动绑定this为当前组件,ES6 class或者纯函数时,需要手动绑定bind双冒号语法<button onClick={::this.handleClick}>确定</button构造器内绑定箭头函数
使用原生事件
在组件卸载时需要手动移除,否则可能会早生内存泄露的问题。
阻止React事件冒泡的行为对原生事件不起作用,而原生事件中却可以阻止React事件冒泡。
不要混用原生与React事件
每当表单的状态发生变化,都会被写入state中。
消除局部状态,使得整个应用的状态更可控在执行setState之前,对表单进行校验与处理使用defaultValue或defaultChecked来设置默认值表单值每次发生变化都要调用一次
一个表单组件没有value props(或checked prop)
value
input textarea select
checked
radio
select
option
inline style 彻底抛弃css,使用js或json来书写css,能够css提供js一样强大的模块化能力。但不能使用媒体查询,:hover,:active等伪类处理起来也比较复杂。CSS Modules
要解决的问题:
全局污染:样式命名重复,容易被覆盖
命令混乱
依赖管理不彻底:引入组件时,除了需要引入js还需要单独引入css
无法共享变量
代码压缩不彻底
引入:import和:export两个伪类
结合webpack的css-loader,就可以利用js来管理css。只转换class相关的样式,id选择器,伪类,标签选择器不做处理
css?modules&localIdentName=[name]_[local]-[hash:base64]:5
使用composes组合样式
.base { .. }.normal{composes: base;..
对应模块名,节点名,节点状态
:export关键字
可以使用react-css-modules库,避免重复输入styles
父组件向子组件
通过props
子组件向父组件
回调函数自定义事件,如vue中on绑定, emit触发
跨级组件通信
父子层层传递使用context实现,但犹如全局变量一样会带来一些副作用,除了界面主题,用户信息等真正全局意义的信息否则不建议使用context
没有嵌套关系的组件通信
自定义事件(发布订阅模式,Node.js Events模块)
类似的概念:拷贝继承,组合
单继承在实现抽象时有一些不变之处,为了弥补缺失,java引入接口,而js引入类似mixin的技巧,创造类似于多继承的效果。
实现
把一个对象原型的方法拷贝给另一个对象(可选择拷贝)同名覆盖深度拷贝,浅拷贝
jQuery中实现方法是extend(支持深度拷贝),ES6中Object.assign
//浅拷贝function mixin(dest, src){var destProto = dest.prototype,srcProto = src.prototype;for(var key in srcProto){console.log(key);if(!(key in destProto)) destProto[key] = srcProto[key]}}
React中mixin不同之处
同名方法不会覆盖,而会报错生命周期方法叠加在一起顺序执行
通过decorator(修饰器)与ES6 class来实现mixin
mixin的问题
破坏了原有组件的封装,添加了新的方法,但也引入了新的state和props,意味着组件的不可见状态也需要我们去维护。mixin也可能依赖其他的mixin,这样会建立一个mixin依赖链。命名冲突增加复杂性,维护性差
类似于higher-order-function(高阶函数):接收函数输入或是输出函数,比如map, reduce , sort等
实现方法如下:
通过高阶组件来传递props
控制props
可以读取,增加或是移除传入原生组件的props
通过refs使用引用
ref回调函数来实现,拿到原始组件的参数
抽象state
将原始组件作为展示型组件,分离内部状态
使用其他元素包裹
增加样式或者布局
mixin与高阶组件的区别
mixin是侵入式的,高阶组件无侵入,符合函数式编程思想。对于原始组件来说,并不会感知到高阶组件的存在,只要把功能套在上面就可以,从而避免了mixin产生的副作用。
高阶组件返回的组件继承于原始组件,高阶组件可以使用原始组件的引用,使用原始组件的state,props,生命周期和render方法
渲染劫持
高阶组件可以控制原始组件的渲染结果。
控制state
高阶组件可以读取,修改或删除原始组件的state,不过尽量避免这样做,可以通过重新命名state,以防止混淆
组件命名
displayname
组件参数
判断对象是否具有某属性
//之前做法if(props.activeIndex){//一些操作}//上面代码存在隐式转换,如果activeIndex为false,0或者其他Boolean(activeIndex)===false的值,则会出错if('activeIndex' in props){..}
hashchange
pushState
replaceState
popstate
http://www.tuicool.com/articles/juMjAnj
React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map 来遍历子节点,而不用担心 this.props.children 的数据类型是 undefined 还是 object
业务与数据解耦
容器组件 展示组件
解决混乱的数据流动方式
核心思想数据和逻辑永远单向流动
所有的请求和控制只能从action发起,统一由dispatcher来分配。
view可以保持足够的简洁,不需要关心太多的逻辑;
MVC下数据或逻辑的改动可以来自完全不同的源头,Flux架构追查问题的复杂度和困难显然要小很多。
viwe->action->dispatcher->store->view
单一数据源, combineReducers
状态是只读的
flux中没有setter而限制了我们直接修改应用的能力,而在redux中执行的更彻底,根本没有store
状态修改均由纯函数完成
与Flux的最大不同,flux中直接修改了store中的数据,导致无法保存每次数据变化前后的状态。而redux中,每一个reducer都是纯函数,即接受一定的输入,必定会得到一定的输出。