vue or react?That's a question.
近两年前端技术层出不穷,目前市面上已经有了不少供前端人员使用的开发框架,转眼19年已过大半,前端框架领域日趋成熟,实现了三足鼎立的局面,老大哥Angular依然占据了半壁江山,react和vue也势头强劲,迎头遇上,在国内发展迅速,形势一片大好。css
最近在学习使用框架的时候,分别使用vue和react开发了两个移动端产品,对这两个框架的学习曲线有了一些感悟,这两个都是如今比较热门的js框架,它俩在使用方式上和学习复杂度上仍是有很大区别的,这里简单总结下二者的差别。html
主要从如下几个方面入手方面展开:前端
vue由尤雨溪开发,一开始是我的项目,目前由饿了么团队进行维护。vue近几年来特别的受关注,三年前的时候angularJS霸占前端JS框架市场很长时间,接着react框架横空出世,由于它有一个特性是虚拟DOM,从性能上碾轧angularJS,这个时候,vue1.0悄悄的问世了,它的优雅,轻便也吸引了一部分用户,开始受到关注,16年中旬,VUE2.0问世,无论从性能上,仍是从成本上都隐隐超过了react,火的一塌糊涂,这个时候,angular开发团队也开发了angular2.0版本,而且改名为angular,吸取了react、vue的优势,加上angular自己的特色,也吸引到不少用户,目前已经迭代到5.0了。友情提示注意下vue的诞生时间,若是正好有小伙伴在面试,被问到你是从何时开始接触而且使用vue的,你要是回答用了五、6年了那场面就十分尴尬了。vue
起初facebook在建设instagram(图片分享)的时候,由于牵扯到一个东西叫数据流,那为了处理数据流而且还要考虑好性能方面的问题,Facebook开始对市场上的各类前端MVC框架去进行一个研究,然而并无看上眼的,因而Facebook以为,仍是本身开发一个才是最棒的,那么他们决定抛开不少所谓的“最佳实践”,从新思考前端界面的构建方式,他们就本身开发了一套,果真大牛创造力仍是很强大的。java
React 起源于 Facebook 的内部项目,由于该公司对市场上全部 JavaScript MVC 框架,都不满意,就决定本身写一套,用来架设Instagram 的网站。作出来之后,发现这套东西很好用,就在2013年5月开源了。node
vue的官网中说它是一款渐进式框架,采用自底向上增量开发的设计。这里咱们须要明确一个概念,什么是渐进式框架。在声明式渲染(视图模板引擎)的基础上,咱们能够经过添加组件系统(components)、客户端路由(vue-router)、大规模状态管理(vuex)来构建一个完整的框架。Vue从设计角度来说,虽然可以涵盖全部这些内容,可是你并不须要一上手就把全部东西全用上,由于没有必要。不管从学习角度,仍是实际状况,这都是可选的。声明式渲染和组建系统是Vue的核心库所包含内容,而客户端路由、状态管理、构建工具都有专门解决方案。这些解决方案相互独立,你能够在核心的基础上任意选用其余的部件,不必定要所有整合在一块儿。能够看到,所说的“渐进式”,其实就是Vue的使用方式,同时也体现了Vue的设计的理念。react
react主张函数式编程,因此推崇纯组件,数据不可变,单向数据流,固然须要双向的地方也能够手动实现,好比借助 onChange 和 setState 来实现一个双向的数据流。而vue是基于可变数据的,支持双向绑定,它提供了v-model这样的指令来实现文本框的数据流双向绑定。android
vue推荐的作法是webpack+vue-loader的单文件组件格式,vue保留了html、css、js分离的写法,使得现有的前端开发者在开发的时候能保持原有的习惯,更接近经常使用的web开发方式,模板就是普通的html,数据绑定使用mustache风格,样式直接使用css。其中<style>标签还提供了一个可选的scoped属性,它会为组件内 CSS 指定做用域,用它来控制仅对当前组件有效仍是全局生效。webpack
模板和JSX是各有利弊的东西。模板更贴近咱们的HTML,可让咱们更直观地思考语义结构,更好地结合CSS的书写。ios
同时vue也支持JSX语法,由于是真正的JavaScript,拥有这个语言自己的全部的能力,能够进行复杂的逻辑判断,进行选择性的返回最终要返回的DOM结构,可以实现一些在模板的语法限制下,很难作到的一些事情。
用过react的开发者可能知道,react是没有模板的,直接就是一个渲染函数,它中间返回的就是一个虚拟DOM树,React推荐的作法是 JSX + inline style, 也就是把HTML和CSS全都写进JavaScript了,即'all in js'。JSX实际就是一套使用XML语法,用于让咱们更简单地去描述树状结构的语法糖。在react中,全部的组件的渲染功能都依靠JSX。你能够在render()中编写相似XML的语法,它最终会被编译成原生JavaScript。不只仅是 HTML 能够用 JSX 来表达,如今的潮流也愈来愈多地将 CSS 也归入到 JavaScript 中来处理。JSX是基于 JS 之上的一套额外语法,学习使用起来有必定的成本。
vue提供了CLI 脚手架,能够帮助你很是容易地构建项目。全局安装以后,咱们就能够用 vue create命令建立一个新的项目,vue 的 CLI 跟其余 CLI不一样之处在于,有多个可选模板,有简单的也有复杂的,可让用户自定义选择须要安装的模块,还能够将你的选择保存成模板,便于后续使用。
极简的配置,更快的安装,能够更快的上手。它也有一个更完整的模板,包括单元测试在内的各类内容都涵盖,可是,它的复杂度也更高,这又涉及到根据用例来选择恰当复杂度的问题。
React 在这方面也提供了 create-react-app,可是如今还存在一些局限性:
而要注意的是这些限制是故意设计的,这有它的优点。例如,若是你的项目需求很是简单,你就不须要自定义生成过程。你能把它做为一个依赖来更新。
vue是实现了双向数据绑定的mvvm框架,当视图改变动新模型层,当模型层改变动新视图层。在vue中,使用了双向绑定技术,就是View的变化能实时让Model发生变化,而Model的变化也能实时更新到View。
Vue采用数据劫持&发布-订阅模式的方式,vue在建立vm的时候,会将数据配置在实例当中,而后经过Object.defineProperty对数据进行操做,为数据动态添加了getter与setter方法,当获取数据的时候会触发对应的getter方法,当设置数据的时候会触发对应的setter方法,从而进一步触发vm的watcher方法,而后数据更改,vm则会进一步触发视图更新操做。
react是单向数据流,react中属性是不容许更改的,状态是容许更改的。react中组件不容许经过this.state这种方式直接更改组件的状态。自身设置的状态,能够经过setState来进行更改。在setState中,传入一个对象,就会将组件的状态中键值对的部分更改,还能够传入一个函数,这个回调函数必须向上面方式同样的一个对象函数能够接受prevState和props。经过调用this.setState去更新this.state,不能直接操做this.state,请把它当成不可变的。
调用setState更新this.state,它不是立刻就会生效的,它是异步的。因此不要认为调用完setState后能够立马获取到最新的值。多个顺序执行的setState不是同步的一个接着一个的执行,会加入一个异步队列,而后最后一块儿执行,即批处理。
setState是异步的,致使获取dom可能拿的仍是以前的内容,因此咱们须要在setState第二个参数(回调函数)中获取更新后的新的内容。
vue中diff算法实现流程
react中diff算法实现流程
React会逐个对节点进行更新,转换到目标节点。而最后插入新的节点,涉及到的DOM操做很是多。diff总共就是移动、删除、增长三个操做,而若是给每一个节点惟一的标识(key),那么React优先采用移动的方式,可以找到正确的位置去插入新的节点。
vue会跟踪每个组件的依赖关系,不须要从新渲染整个组件树。而对于React而言,每当应用的状态被改变时,所有组件都会从新渲染,因此react中会须要shouldComponentUpdate这个生命周期函数方法来进行控制。
指令 (Directives) 是带有 v-
前缀的特殊特性,指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地做用于 DOM。
vue中提供不少内部指令供咱们使用,它可让咱们进行一些模板的操做,例若有时候,咱们的data中的存放的数据不是个简单的数字或者字符串,而是数组Array类型,这个时候,咱们要把数组的元素展现在视图上,就须要用到vue提供的 v-for 指令,来实现列表的渲染。
由于react中没有v-for指令,因此循环渲染的时候须要用到map()方法来渲染视图,而且将符合条件的元素放入一个新数组返回。
vue中的每一个组件内部自动实现了shouldComponentUpdate
的优化,在vue里面因为依赖追踪系统的存在,当任意数据变更的时,Vue的每个组件都精确地知道本身是否须要重绘,因此并不须要手动优化。用vue渲染这些组件的时候,数据变了,对应的组件基本上去除了手动优化的必要性。而在react中咱们须要手动去优化其性能,可是当数据特别多的时候vue中的watcher也会特别多,从而形成页面卡顿,因此通常数据比较多的大型项目会倾向于使用react。在react官网中,官方也建议咱们使用React来构建快速响应的大型 Web 应用程序。
当props或state发生改变的时候会触发shouldComponentUpdate
生命周期函数,它是用来控制组件是否被从新渲染的,若是它返回true,则执行render函数,更新组件;若是它返回false,则不会触发从新渲染的过程。
有的时候咱们但愿它在更新以前,和以前的状态进行一个对比,这个时候咱们就须要重写shouldComponentUpdate
来避免没必要要的dom操做,对比当前的props或state和更新以后的nextProps或nextState,返回true时 ,组件更新;返回false,则不会更新,节省性能。
shouldComponentUpdate(nextProps, nextState) { if (this.props.a !== nextProps.a) { return true; } if (this.state.b !== nextState.b) { return true; } return false; }
咱们也能够建立一个继承React.PureComponent的React组件,它自带shouldComponentUpdate
,能够对props进行浅比较,发现更新以后的props与当前的props同样,就不会进行render了。
class Test extends React.PureComponent{ constructor(props){ super(props); } render(){ return <div>hello...{this.props.a}</div> } }
因为React.PureComponent进行的是浅比较,也就是说它只会对比原对象的值是否相同,当咱们的props或state为数组或者对象这种引用类型的时候,咱们修改它的数值,因为数据引用指针没有发生改变,因此组件也是不会从新渲染的。这个时候咱们就须要进行深拷贝,建立一个新的对象或数组,将原对象的各项属性的"值"(数组的全部元素)拷贝过来,是"值"而不只仅是"引用地址"。咱们可使用slice()方法:
ew_state.todos = new_state.todos.slice();
或者引入immutable库来实现数据不可变。
native指的是使用原生API来开发App,好比ios使用OC语言,android使用java。
vue和Weex进行官方合做,weex是阿里巴巴发起的跨平台用户界面开发框架,它的思想是多个平台,只写一套代码,weex容许你使用 vue 语法开发不只仅能够运行在浏览器端,还能被用于开发 iOS 和 Android 上的原生应用的组件。即只须要编写一份代码,便可运行在Web、iOS、Android上。
weex相对来讲上手比较简单,安装vue-cli以后就可使用,学习门槛低,可是它的社区目前还处于成长期,react native的社区很是成熟活跃,有很是丰富的组件可供扩展。
react native是Facebook在2015年3月在F8开发者大会上开源的跨平台UI框架,需针对iOS、Android不一样编写2份代码,使用react native须要按照文档安装配置不少依赖的工具,相对比较麻烦。weex的思想是多个平台,只写一套代码,而react-native的思想是多个平台能够写多套代码,但其使用的是同一套语言框架。
weex的目标在于抹平各个平台的差别性,从而简化应用开发。而react-native认可了各个平台之间的差别,退而求其次,在语言和框架层面对平台进行抽象,从方法论的角度去解决多平台开发的问题。
服务端渲染核心在于方便seo优化,后端先调用数据库,得到数据以后,将数据和页面元素进行拼装,组合成完整的html页面,再直接返回给浏览器,以便用户浏览。
2016 年 10 月 25 日,zeit.co背后的团队对外发布了 Next.js,一个 React 的服务端渲染应用框架。几小时后,与 Next.js 殊途同归,一个基于 Vue.js 的服务端渲染应用框架应运而生,咱们称之为:Nuxt.js。
服务端渲染支持流式渲染,由于HTTP请求也是流式,Vue 的服务端渲染结果能够直接 pipe 到返回的请求里面。这样一来,就能够更早地在浏览器中呈现给用户内容,经过合理的缓存策略,能够有效地提高服务端渲染的性能。
Next是一个React框架,容许使用React构建SSR和静态web应用
【初始化阶段(4个)】
(1)beforeCreate
此钩子函数不能获取到数据,dom元素也没有渲染出来,此钩子函数不会用来作什么事情。
(2)created
此钩子函数,数据已经挂载了,可是dom节点仍是没有渲染出来,在这个钩子函数里面,若是同步更改数据的话,不会影响运行中钩子函数的执行。能够用来发送ajax请求,也能够作一些初始化事件的相关操做。
(3)beforeMount
表明dom节点立刻要被渲染出来了,可是尚未真正的渲染出来,此钩子函数跟created钩子函数基本同样,也能够作一些初始化数据的配置。
(4)mounted
是生命周期初始化阶段的最后一个钩子函数,数据已经挂载完毕了,真实dom也能够获取到了。
【运行中阶段(2个)】
(5)beforeUpdate
运行中钩子函数beforeUpdate默认是不会执行的,当数据更改的时候,才会执行。数据更新的时候,先调用beforeUpdate,而后数据更新引起视图渲染完成以后,再会执行updated。运行时beforeUpdate这个钩子函数获取的数据仍是更新以前的数据(获取的是更新前的dom内容),在这个钩子函数里面,千万不能对数据进行更改,会形成死循环。
(6)updated
这个钩子函数获取的数据是更新后的数据,生成新的虚拟dom,跟上一次的虚拟dom结构进行比较,比较出来差别(diff算法)后再渲染真实dom,当数据引起dom从新渲染的时候,在updated钩子函数里面就能够获取最新的真实dom了。
【销毁阶段(2个)】
(7)beforeDestroy
切换路由的时候,组件就会被销毁了,销毁以前执行beforeDestroy。在这个钩子函数里面,咱们能够作一些善后的操做,例如能够清空一下全局的定时器(created钩子函数绑定的初始化阶段的事件)、清除事件绑定。
(8)destoryed
组件销毁后执行destroyed,销毁后组件的双向数据绑定、事件监听watcher相关的都被移除掉了,可是组件的真实dom结构仍是存在在页面中的。
添加keep-alive标签后会增长active和deactive这两个生命周期函数,初始化操做放在actived里面,一旦切换组件,由于组件没有被销毁,因此它不会执行销毁阶段的钩子函数,因此移除操做须要放在deactived里面,在里面进行一些善后操做,这个时候created钩子函数只会执行一次,销毁的钩子函数一直没有执行。
【初始化阶段(5个)】:
(1)getDefaultProps:实例化组件以后,组件的getDefaultProps钩子函数会执行
这个钩子函数的目的是为组件的实例挂载默认的属性
这个钩子函数只会执行一次,也就是说,只在第一次实例化的时候执行,建立出全部实例共享的默认属性,后面再实例化的时候,不会执行getDefaultProps,直接使用已有的共享的默认属性
理论上来讲,写成函数返回对象的方式,是为了防止实例共享,可是react专门为了让实例共享,只能让这个函数只执行一次
组件间共享默认属性会减小内存空间的浪费,并且也不须要担忧某一个实例更改属性后其余的实例也会更改的问题,由于组件不能本身更改属性,并且默认属性的优先级低。
(2)getInitialState:为实例挂载初始状态,且每次实例化都会执行,也就是说,每个组件实例都拥有本身独立的状态。
(3)componentWillMount:执行componentWillMount,至关于Vue里的created+beforeMount,这里是在渲染以前最后一次更改数据的机会,在这里更改的话是不会触发render的从新执行。
(4)render:渲染dom
render()
方法必须是一个纯函数,他不该该改变state
,也不能直接和浏览器进行交互,应该将事件放在其余生命周期函数中。 若是shouldComponentUpdate()
返回false
,render()
不会被调用。
(5)componentDidMount:至关于Vue里的mounted,多用于操做真实dom
【运行中阶段(5个)】
当组件mount到页面中以后,就进入了运行中阶段,在这里有5个钩子函数,可是这5个函数只有在数据(属性、状态)发送改变的时候才会执行
(1)componentWillReceiveProps(nextProps,nextState)
当父组件给子组件传入的属性改变的时候,子组件的这个函数才会执行。初始化props时候不会主动执行
当执行的时候,函数接收的参数是子组件接收到的新参数,这个时候,新参数尚未同步到this.props上,多用于判断新属性和原有属性的变化后更改组件的状态。
(2)接下来就会执行shouldComponentUpdate(nextProps,nextState),这个函数的做用:当属性或状态发生改变后控制组件是否要更新,提升性能,返回true就更新,不然不更新,默认返回true。
接收nextProp、nextState,根据根据新属性状态和原属性状态做出对比、判断后控制是否更新
若是shouldComponentUpdate()
返回false
,componentWillUpdate
,render
和componentDidUpdate
不会被调用。
(3)componentWillUpdate,在这里,组件立刻就要从新render了,多作一些准备工做,千万千万,不要在这里修改状态,不然会死循环 至关于Vue中的beforeUpdate
(4)render,从新渲染dom
(5)componentDidUpdate,在这里,新的dom结构已经诞生了,至关于Vue里的updated
【销毁阶段】
当组件被销毁以前的一刹那,会触发componentWillUnmount,临死前的挣扎
至关于Vue里的beforeDestroy,因此说通常会作一些善后的事情,例如使定时器无效,取消网络请求或清理在componentDidMount
中建立的任何监听。
vue在调用$destroy方法的时候就会执行beforeDestroy生命周期函数,而后组件被销毁,这个时候组件的dom结构还存在于页面结构中,也就说若是想要对残留的dom结构进行处理必须在destroyed生命周期函数中处理。
react执行完componentWillUnmount以后把事件、数据、dom都所有处理掉了,也就是说当父组件从渲染这个子组件变成不渲染这个子组件的时候,子组件至关于被销毁,因此根本不须要其余的钩子函数了。react销毁组件的时候,会将组件的dom结构也移除,vue则否则,在调用destory方法销毁组件的时候,组件的dom结构仍是存在于页面中的,this.$destory组件结构仍是存在的,只是移除了事件监听,因此这就是为何vue中有destroyed,而react却没有componentDidUnmount。
vuex是一个专门为vue构建的状态集管理工具,vue和react都是基于组件化开发的,项目中包含不少的组件,组件都会有组件嵌套,想让组件中的数据被其余组件也能够访问到就须要使用到Vuex。
[图片上传失败...(image-2a0a7e-1565257938346)]
vuex的流程
建立store,将状态挂载到state上,在根实例里面配置store,以后咱们在组件中就能够经过this.$store.state来使用state中管理的数据,可是这样使用时,当state的数据更改的时候,vue组件并不会从新渲染,因此咱们要经过计算属性computed来使用,可是当咱们使用多个数据的时候这种写法比较麻烦,vuex提供了mapState辅助函数,帮助咱们在组件中获取并使用vuex的store中保存的状态。
能够根据某一个状态派生出一个新状态,vuex也提供了mapGetters辅助函数来帮助咱们在组件中使用getters里的状态。
咱们不能直接在组件中更改state,而是须要使用mutations来更改,mutations也是一个纯对象,里面包含不少更改state的方法,这些方法的形参接收到state,在函数体里更改,这时,组件用到的数据也会更改,实现响应式。vuex提供了mapMutations方法来帮助咱们在组件中调用mutations 的方法。
Actions相似于mutations,不一样在于:Actions提交的是mutations,而不是直接变动状态。Actions能够包含任意异步操做。也就是说,若是有这样的需求:在一个异步操做处理以后,更改状态,咱们在组件中应该先调用actions,来进行异步动做,而后由actions调用mutations来更改数据。在组件中经过this.$store.dispatch方法调用actions的方法,固然也可使用mapMutations来辅助使用。
2015年Redux出现,将 Flux 与函数式编程结合一块儿,很短期内就成为了最热门的前端架构。它的出现主要是为解决react中组件之间的通讯问题。建议把数据放入到redux中管理,目的就是方便数据统一,好管理。项目一旦出现问题,能够直接定位问题点。组件扩展的时候,后续涉及到传递的问题。原本的话,组件使用本身的数据,可是后来公用组件,还须要考虑如何值传递,在redux中能够存储至少5G以上的数据。
redux的流程
从redux工具中取出createStore去生成一个store。
reducer是一个纯函数,接收当前状态和action,返回一个状态,返回什么,store的状态就是什么,须要注意的是,不能直接操做当前状态,而是须要返回一个新的状态。
想要给store建立默认状态其实就是给reducer一个参数建立默认值。
vue和react的核心都是专一于轻量级的视图层,虽然只是解决一个很小的问题,可是它们庞大的生态圈提供了丰富的配套工具,一开始它并不会给你提供全套的配置方案,将全部的功能都一次性给你打包好,它只会给你提供一些简单的核心功能,当你须要作一个更复杂的应用时,再增添相应的工具。例如作一个单页应用的时候才须要用路由;作一个至关庞大的应用,涉及到多组件状态共享以及多个开发者共同协做时,才可能须要大规模状态管理方案。
框架的存在就是为了帮助咱们应对不一样的项目复杂度,当咱们面对一个大型、复杂的开发项目时,使用太简陋的工具会极大的下降开发人员的生产力,影响工做效率,框架的诞生就是在这些工程中提取一些重复的而且已经受过验证的模式,抽象到一个已经帮你设计好的API封装当中,帮助咱们去应对不一样复杂度的问题。因此在开发的过程当中,选择一个合适的框架就会事半功倍。可是,框架自己也有复杂度,有些框架会让人一时不知如何上手。当你接到一个并不复杂的需求,却使用了很复杂的框架,那么就至关于杀鸡用牛刀,会遇到工具复杂度所带来的反作用,不只会失去工具自己所带来优点,还会增长各类问题,例如学习成本、上手成本,以及实际开发效率等。
因此并非说作得少的框架就不如作的作的框架,每一个框架都有各自的优点和劣势,并不能找到彻底符合需求的框架,最重要的适合当前项目,目前两大框架的生态圈一片繁荣,react社区是当前最活跃的,最快的时候三天更新一个版本,一个问题可能存在几十种不一样的解决方案,这就须要咱们前端人员去在不一样的功能之间作取舍,之后前端框架的发展方向应该是小而精、灵活以及开放的,核心功能+生态附加库能够帮咱们更加灵活的构建项目,为了跟上前进的脚步,就须要不停的吸取最新的内容,这也是从事前端开发领域的一大乐趣,但愿你们都能在学习中得到长足的进步。
参考文章及站点:
React官网
Vue官网
Vue官网:对比其余框架
https://vue.docschina.org/v2/...
Nuxt.js
vue和react对比(详解)
https://www.cnblogs.com/yangy...
react和vue对比
https://www.jianshu.com/p/3fb...
vue和react的区别之我见
https://www.jianshu.com/p/b7c...
如何选择正确的后端渲染框架:Next, Nuxt, Nest?
https://www.jianshu.com/p/00d...
react服务端渲染
https://www.jianshu.com/p/5cb...
Vue.js 服务器端渲染指南
https://ssr.vuejs.org/zh/#%E4...
React Native--概述及与Weex和Native开发的对比(一)
https://www.jianshu.com/p/613...
Weex 和 React Native的比较
https://www.jianshu.com/p/323...
Weex 和 React Native 的比较看这里
https://www.cnblogs.com/Free-...
【前端前沿看点】深度本质分析对比weex和react native
https://blog.csdn.net/chaunce...
Vue2.0 中,“渐进式框架”和“自底向上增量开发的设计”这两个概念是什么?
https://www.zhihu.com/questio...
Vue做者尤雨溪:Vue 2.0,渐进式前端解决方案
https://mp.weixin.qq.com/s?__...;idx=1&sn=14fe8a5c72aaa98c11bf6fc57ae1b6c0&source=41#wechat_redirect
vue内置指令与自定义指令
https://www.cnblogs.com/ilove...
React的setState和数据绑定
https://blog.csdn.net/weixin_...
React实现数据双向绑定
https://blog.csdn.net/Chad97/...
【译】react:css in js