
前情提要
我学习和使用Vue大概有一年时间了,可是最近才开始学习的React,在没使用过React以前就常常看到许多博主都在将二者进行对比,在实践完之后,我想站在我本身的角度看看。css
那就开始了
官方文档
Vue官方文档
React官方文档【中文版】vue
- 我的感受Vue的文档划分的更加好一点,会把许多概念都讲的比较清晰(虽然第一次看的时候啥都没看懂)同时把一些相关的生态系统也概括到了一块儿,例如vue-cli、vue-router、vuex等,比较方便
- React的文档感受比较注重实操,对基础的讲解较少,在教程部分就会教你如何实现一个井字棋的(这一点是比较友好的)
组件
这两个框架都是推荐把页面组件化的,可是二者之间对于组件也有各自的不一样
生命周期
Vue
- 主要分为8个阶段:
beforeCreate
created (在这个阶段就能够首次拿到data中定义的数据)
beforeMount
mounted(在这个阶段Dom树渲染完毕可访问Dom结构)
beforeUpdate
updated
beforeDestroy
destroyed

React
- 主要分为3个阶段:
Mounting初始化 -> Updating运行中 -> Unmounting销毁

-
生命周期中的方法react
- 【react 16.0以后已移除】 componentWillMount():在render()以前执行,因此在这个阶段的setState()不会从新渲染;一般用constructor()代替
- render():在componentWillMount()以后执行
- componentDidMount():在render()以后执行,因此在这个阶段的setState()会从新渲染;这里能够对DOM进行操做
- 【react 16.0以后已移除】 componentWillReceiveProps(nextProps):当已挂载组件收到新的props时执行,但有可能props传入时没有发生改变但仍然从新渲染了,若是想要避免这种状况能够在传入新的props时比较一下新旧props之间是否发生变化;这里须要注意一下,若是只是调用了setState()的话是不会触发这个方法的,只有props发生改变或者没有发生改变时才会触发这个方法
- shouldComponentUpdate(nextProps,nextState):在接收到新的props或者state时肯定是否发生从新渲染,默认值为true;在首次渲染时不会触发这个方法
- 【react 16.0以后已移除】 componentWillUpdate(nextProps,nextState):在shouldComponentUpdate()以后,render()以前触发;在组件初始化时不会被触发
- componentDidUpdate(prevProps,prevState):在componentWillUpdate(nextProps,nextState)以后调用;在组件初始化时不会被触发,此时能够对DOM进行操做
组件形式
Vue Template
- Vue组件的编写结构分为三部分,分别是 template(HTML) script(JS) style(CSS)
- 将三者独立开来,更好的注重每一部分的开发
- CSS:Vue默认是在单文件组件中在<script scoped></script>标签里写CSS样式,咱们能够经过在
<script scoped></script>
标签中写上scoped
,这样这部分样式就只用来控制该组件的样式,而不会影响到其余组件。
-
JS:模版部分使用数据:须要将变量放在双大括号内{{}}
vue-router
<template>
<!-- HTML Code -->
<div>{{name}}</div>
</template>
<script>
export default{
name: 'NewComponent',
data() {
return {
name: 'xx'
}
}
}
</script>
<style scoped>
/* CSS Code */
</style>
React JSX
- React支持Class组件和Function组件
- React组件使用render渲染函数,能够用JavaScript来构建视图页面,常包含了大量的逻辑
- CSS:React是经过使用className字段来设置样式,通常都是引入外部的css,且通常都会使用less预编译
-
JS:将变量放在{}
内vuex
// class组件
class Template extends React.Component{
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
</div>
);
}
}
// function组件
function NewComponent() {
const [name, setName] = useState('');
return (<div>{name}</div>);
}
数据管理
Vue对象属性
React状态管理
class组件state
function组件hooks
数据流
单向数据流中的
单向:我理解的是父级数据的更新会向下流动到子组件中,可是反过来则不行,这样能够防止从子组件意外改变父级组件的状态

Vue双向数据绑定
vue仍然是单向数据流
表现形式
- 使用
v-model
-
通常有两种使用情景:app
-
v-model
实质为语法糖
<input v-model="message" />
// 等价于:
<input
v-bind:value="message" // 与data中声明的数据进行绑定
v-on:input="message=$event.target.value" // 监听输入框中值的变化
/>
// 实现原理
// 修改AST元素,给el添加一个prop,至关于动态绑定了value
addProp(el,'value',`(${value})`);
// 添加事件处理,至关于给input绑定了input事件
addHandler(el,event,code,null,true);
实现原理
- vue使用的是发布者订阅者的模式+数据劫持的方式来实现的,在组件中咱们定义data时,vue会遍历这个对象,经过
Object.defineProperty()
给每个值都添加getter
和setter
方法,而后每个组件都有一个watcher来监听数据的变化,当数据发生变化的时候,即触发setter
时,就会发布消息给订阅者,触发相应的监听回调
Vue2.0的缺陷
- 不具有监听数组的能力,须要从新定义数组的原型来达到响应式
- 没法检测到对象属性的添加和删除
- 只能劫持对象的属性(假如须要对每一个对象的每一个属性进行遍历,若是属性值也是对象那么须要深度遍历,显然能劫持一个完整的对象是更好的选择)
解决方法:Vue.set() || this.$set()
- 若是在实例建立以后添加新的属性到实例上,它不会触发视图更新,由于此时添加的属性并无绑定上
getter
、setter
,所以这个属性是非响应式。若是咱们想要把这个属性变成响应式的话,能够经过Vue.set()
或者this.$set()
这两种方式添加新的属性
- 除了添加新的属性之外,改变数组的一些属性也不会使得视图更新,
- 利用索引直接设置数组的某一项
arr[1] = 10
- 直接修改数组的大小
arr.length = 10
- 对于数组除了能够经过
Vue.set()
、this.$set()
这两种方式,还可使用数组的一些API来触发更新,如splice()
、concat()
等会修改原始数组的API
Vue3.0的改进
-
使用ES6中的proxy框架
- 能够劫持到整个对象而非属性,并返回一个新的对象
- 能够监听到数组的变化
React单向数据流
特色
- React采用单向数据流的形式,即它只接收数据,但不改变数据,只监听数据的改变;当数据发生变化的时候,它会接收使用新的数据,从新进行渲染。
- 我以为单向数据流最大的好处的话,是当多个组件都要对同一个值进行操做的时候,因为数据只有一份,所以可以保持它的一致性。
状态管理器
什么状况下咱们要使用状态管理器呢?
通常是当多个组件须要共同维护一些数据,使用传值的方式会十分复杂,于是咱们能够把这些须要共同维护的数据提取出来,放在store中共同维护,这样就能够保证数据的一致性
Vue
Vuex
- 单一数据源:只有一个store
- mutation(同步操做):修改state只能经过mutation的方式,须要经过store.commit()来提交mutation
- action(异步操做):action里面能够包含多个mutation,最后也是要经过store.commit()来触发mutation,action须要经过store.dispatch()来触发
- model:引入来模块化,就是想要把store进行拆分,每一个 Module 有本身的 state、mutation、action、getter,能够各自维护,最后再把每一个store组合起来,不违背Vuex的单一数据源
React
Redux
- 单一数据源:只有一个store
- state是只读的:须要经过reducer纯函数返回一个新的state
- 单向数据流
- 使用的是不可变数据,每次更新都是使用新的state来替换旧的state
Mobx-React
- 能够有多个store
- store中的state能够直接修改
@observable // 咱们要在须要观察的数据加上@observable
current: number = 1;
total: number = 0;
@action // 将修改被观测变量的行为放在action中
updateCurrent(current: number) {
this.current = current;
}
// 对于异步操做,action没法影响当前函数调用的异步操做,可使用runInAction来解决
async getList() {
// some code
runInAction(() => {
this.total = res.total;
});
}
路由
Vue-Router
vue是单页面应用,页面跳转不会发送请求
hash模式
表层原理
- 使用hash来模拟一个完整的URL,因此当URL发生改变的时候,不会从新加载
- hash出如今URL中,但并不会包含到http请求中,所以当hash值发生变化的时候,并不会引发页面的请求
- 当#后的值发生变化的时候,会向浏览器的历史浏览增长一个记录,当点击后退按钮时,会弹出,以此来实现页面的跳转
- 经过onhashchange事件监听hash值的变化
history模式
// 像这样
http://localhost:8080/home/center
表层原理
- history模式主要使用的是HTML5中提供的API
history.pushState()
和history.replaceState()
来实现
- 须要注意的是,history模式不怕前进,不怕后退,就怕刷新
- history模式下若是刷新页面的话,可能会返回404,由于当刷新页面的时候,会真实的向服务端发送请求,但若是此时该页面没有在服务端配置过的话就会返回404,所以须要服务端进行重定向,可使用Nginx,使用try_file和rewrite实现重定向
React-Router(待完善)
BrowserRouter
HashRouter
脚手架(待补充)
Vue-Cli
Create-React-App
单元测试(待补充)
从Vue到React
- 虽然我是先学习和使用Vue的,可是因为之前学习过Java等一些面向对象的语言,因此从Vue到React的过渡并无不适应,反而以为很熟悉;并且React使用JS来构建页面,能够在里面写逻辑,我以为很是安逸呀。
- 但其实不论是哪种框架,适合这个项目的框架那它就是好框架,不一样的框架有不一样的特殊点,若是这个特殊点和项目的要求想契合的话,那就是它了!