React 和 Vue 是目前前端最支流的两大框架,最近面试总是被问及 React 和 Vue 的异同比照,这次就大略梳理一下。
GitHub 上 star 比照截图
设计思维
React 官网介绍 React 是一个用于构建用户界面的 JavaScript 库。React 举荐 JSX + inline style, 也就是把 HTML 和 CSS 全都写进 JavaScript 了, 即 ”all in js“,HTML 和 css 都能够放到 js 中。React 主张函数编程,举荐应用纯函数,数据 不可变,单向数据流,然而能够手动编写 onChange 等事件处理函数实现双向数据流。联合 JSX 轻松实现渲染模板
Vue 官网介绍 Vue 是一套用于构建用户界面的渐进式框架, 与其它大型框架不同的是,Vue 被设计为能够自底向上逐层利用。Vue 保留了 html、css、js 拆散的写法,使得现有的前端开发者在开发的时候能放弃原有的习惯,更靠近罕用的 web 开发方式,模板就是一般的 html,数据绑定应用 mustache 格调,款式间接应用 css。Vue 认为数据是 可变的,应用 v -model 实现双向数据流。
构建与调试
* 构建工具
React 创立新的单页利用的最佳形式: Create React App
npx create-react-app my-app
cd my-app
npm start
Vue 官网构建工具: vue-cli
npm install -g @vue/cli
vue create my-app
npm run serve
# OR
yarn global add @vue/cli
vue create my-app
npm run serve
* 调试
React Developer Tools 用来调试 react
Redux DevTools 用来调试 redux
Vue.js devtools 用来调试 vue,vuex 等
JSX vs 模板
React 没有模板,是通过类组件的 render 办法的返回值或者函数式组件的返回值来渲染虚构 DOM,通过原生 js 来实现条件渲染、循环渲染、插值等。也能够应用 JSX 语法糖来更简略地去形容树状构造;
Vue 则是应用模板,模板更贴近 HTML 与 js 代码、css 代码分来到,应用 mustache 进行数据绑定,应用指令来实现条件渲染、循环渲染等
数据变动监听
* 数据流比照
React 是单向数据流,且是不容许子组件批改父组件传来的 props,组件的 state 是容许批改的,能够通过 setState(异步的)来进行更改,不容许通过 this.state 这种形式间接更改组件的状态。vue2.x 中也不容许子组件批改父组件传递的 props,组件与 DOM 之间能够通过 v -model 双向绑定
* 监听数据变动形式比照
React 组件在调用 setState 后,默认状况下因为 shouldComponentUpdate()里的返回值是 true 所以全副组件都会从新渲染,造成很多不必要的渲染,能够通过在组件的 shouldComponentUpdate()生命周期办法中来进行渲染优化或者间接应用官网的 PureComponent(shouldComponentUpdate()中进行状态和属性的浅比拟来决定是否须要渲染)
Vue2.x 中通过 Object.defineProperty()把 data 对象中所有属性增加到 vm 上。为每一个增加到 vm 上的属性,都指定一个 getter/setter。在 getter/setter 外部去操作(读 / 写)data 中对应的属性。Vue3 中通过 new Proxy()和 Reflect 来为数据指定一个 getter/setter。当设置数据的时候会触发对应的 setter 办法,从而进一步触发 vm 的 watcher 办法,而后数据更改,vm 则会进一步触发视图更新操作。vue 可能更加准确的晓得数据变动,只从新渲染与变动数据绑定的 DOM
事件
React 通过属性来绑定事件,React 类组件须要本人手动处理事件 this 指向的问题
class Demo extends React.Component{
/*
通过 onXxx 属性指定事件处理函数(留神大小写)
a.React 应用的是自定义 (合成) 事件, 而不是应用的原生 DOM 事件 —————— 为了更好的兼容性
b.React 中的事件是通过事件委托形式解决的(委托给组件最外层的元素) ————————为了的高效
*/
constructor(props){super(props);
// 初始化状态
this.state = {number: 22}
// 解决 this 指向问题
this.showInfo3 = this.showInfo3.bind(this)
}
showInfo1 = ()=> {console.log(this.state);
}
showInfo2 = (e, number)=> {console.log(number);
console.log(this.state);
}
showInfo3() {console.log(this.state);
}
showInfo4(number) {return (e) => {console.log(number);
console.log(this.state);
}
}
render(){
return(
<div>
<button onClick={this.showInfo1}> 点我提示信息(不传参)</button>
<button onClick={this.showInfo3}> 点我提示信息(不传参)</button>
<button onClick={(e) => {this.showInfo2(e,66)}}> 点我提示信息(传参)</button>
<button onClick={this.showInfo4(88)}> 点我提示信息(传参)</button>
</div>
)
}
}
Vue 中的事件处理函数都放到 methods 配置对象中,并把 methods 中的每一个事件处理函数都放到 vm 身上并把函数的 this 绑定到 vm 身上,通过指令来实现事件绑定
<button @click="showInfo1"> 点我提示信息(不传参)</button>
<button @click="showInfo2($event,66)"> 点我提示信息(传参)</button>
const vm = new Vue({
el:'#root',
methods:{showInfo1(event){console.log(this); // 此处的 this 是 vm
},
showInfo2(event,number){console.log(this); // 此处的 this 是 vm
console.log(number); //66
}
}
})
组件通信形式
React 组件通信的几种形式:
- 父子组件通信:props
- 兄弟组件(非嵌套组件):音讯订阅 - 公布(pubs-sub)、集中式治理(redux、dva)
- 祖孙组件(跨级组件):音讯订阅 - 公布(pubs-sub)、集中式治理(redux、dva)、Context(生产者 - 消费者模式,用的少)
Vue 组件通信的几种形式:
- 父子组件通信:props 与自定义事件
- 兄弟组件(非嵌套组件):全局事件总线、音讯订阅 - 公布(pubs-sub)、集中式治理(vuex、redux)
- 祖孙组件(跨级组件):全局事件总线、音讯订阅 - 公布(pubs-sub)、集中式治理(vuex、redux)、provide/inject
生态比照
小程序
- Taro(基于 React)
- uni-app(基于 Vue)
挪动端 App
- ReactNative
- Weex
其余比照
- React 认为数据不可变,所以一个嵌套比拟深的状态数据 obj:{a:{b:{c: ‘2’}}}, 批改 obj.a.b.c = ‘3’ 是不会进行页面渲染的,只有 this.setState({obj:{a:{b:{c: ‘3’}}}})才会进行页面渲染。Vue 认为数据是可变的,然而只有 data 中初始化的数据才是响应式的,间接 data 中某个对象数据增加新数据是无奈实现响应式的,得应用 Vue.set(),对于数组,Vue 不容许间接利用索引来批改数组能够应用 Vue.set()或 array.splice()
- React 应用高阶组件 HoC 来实现组件组合,vue 则应用 mixins 来实现,因为 vue 默默帮咱们做了这么多事,所以咱们本人如果间接把组件的申明包装一下,返回一个 HoC,那么这个被包装的组件就无奈失常工作。React 最早也是应用 mixins 的,不过起初他们感觉这种形式对组件侵入太强会导致很多问题,就弃用了 mixins 转而应用 HoC。
- React 应用 props、render props 与 children props 来实现相似 Vue 中的具名插槽、作用域插槽和默认插槽
- diff 算法比照,React 和 Vue 都只进行同层比拟,且都是用 key 来优化 diff 算法。React 中认为只有新旧虚构 DOM 的标签名和 key 一样就是同一个虚构节点,而 Vue 在标签名和 key 雷同的根底上还要比照属性;Vue 基于 snabbdom 库,应用双向链表,边比照,边更新 DOM,React 次要应用 diff 队列保留须要更新哪些 DOM,失去 patch 树,再对立操作批量更新 DOM。
Redux 与 Vuex 比照
- Redux 认为数据是不可变的,所以 reducer 中必须是纯函数,不容许批改传入的参数 prevState,所以只能返回一个基于 prevState 的一个全新的 state;
- Redux 中的 action 的值必须是一个个别对象,这也就注定 Redux 不能实现异步 action(值为函数),然而能够应用中间件来实现异步 action,罕用的有 redux-thunk、redux-promise、redux-saga 等;
- Redux 应用 combineReducers(reducers)来实现模块化编码;
- 应用 react-redux 的 connect 办法来创立容器组件把 redux 中的 state、action 传给 UI 组件的 props 中并实现监测 redux 中状态的扭转并且从新渲染组件;
- Vuex 认为数据是可变的,所以不必像 reducer 那样的纯函数;Vue.use(Vuex)后创立完 store,则 vm 上就增加了 $store 属性
- Vuex 中 mutations 是同步的,actions 用来实现一些异步操作,当 state 中的数据须要通过加工后再应用时,能够应用 getters 加工;
- mapState 帮忙咱们映射
state
中的数据为计算属性;mapGetters 用于帮忙咱们映射getters
中的数据为计算属性;mapActions 用于帮忙咱们生成触发actions
的办法,即:蕴含$store.dispatch(xxx)
的函数;mapMutations 用于帮忙咱们生成触发mutations
的办法,即:蕴含$store.commit(xxx)
的函数; - 应用 modules 和 namespaced 来实现模块化