Vue
Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
React
与 Vue 不同,react 库是由 Facebook 创建的。最初是为了 Facebook 广告流量管理创建的。那时 Facebook 遇到了维护和编码方面的问题。它以动态创建和交互式 UI 的能力而闻名。
监听数据变化的实现原理的不同之处
Vue 通过 getter/setter 以及一些函数的劫持,能精确知道数据变化,不需要特别的优化就能达到很好的性能
React 默认是通过比较引用的方式进行的,如果不优化(PureComponent/shouldComponentUpdate)可能导致大量不必要的VDOM的重新渲染
为什么 React 不精确监听数据变化呢?这是因为 Vue 和 React 设计理念上的区别,Vue 使用的是可变数据,而React更强调数据的不可变。所以应该说没有好坏之分,Vue更加简单,而React构建大型应用的时候更加鲁棒。
因为一般都会用一个数据层的框架比如 Vuex 和 Redux,所以这部分不作过多解释,在最后的 vuex 和 redux的区别 中也会讲到。
核心思想对比
vue与react都推崇组件式的开发理念,但是在设计的核心思想上有很大差别。
Vue的核心思想
vue的整体思想仍然是拥抱经典的html(结构)+css(表现)+js(行为)的形式,vue鼓励开发者使用template模板,并提供指令供开发者使用(v-if、v-show、v-for等等),因此在开发vue应用的时候会有一种在写经典web应用(结构、表现、行为分离)的感觉。另一方面,在针对组件数据上,vue2.0通过Object.defineProperty
对数据做到了更细致的监听,精准实现组件级别的更新。
React的核心思想
react整体上是函数式的思想,组件使用jsx语法,all in js,将html与css全都融入javaScript,jsx语法相对来说更加灵活,我一开始刚转过来也不是很适应,感觉写react应用感觉就像是在写javaScript。当组件调用setState或props变化的时候,组件内部render会重新渲染,子组件也会随之重新渲染,可以通过shouldComponentUpdate
或者PureComponent
可以避免不必要的重新渲染(个人感觉这一点上不如vue做的好)。
数据管理(Vue的props、data vs React的props、state)
组件数据管理通常包含2部分,来自父组件的数据props与自身的数据。
vue与react中的props都是单向数据流的,父级prop的更新会向下流动到子组件中,但是反过来则不行。prop可以是数组或对象,用于接收来自父组件的数据。
vue
props
vue中的props支持传递静态或动态props
,静态props一般传递字符串。
<blog-post title="My journey with Vue"></blog-post>
静态prop传递布尔值true可以这样写,传值false仍然需要使用动态prop传值。
<blog-post disabled></blog-post>
动态赋值使用v-bind,可以简写为:。
<blog-post v-bind:title="tile"></blog-post>
// 简写形式
<blog-post :title="tile"></blog-post>
动态prop常用来传递对象、数组、布尔值(false值,true值可以直接传属性)等。
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>
data
vue中使用data来管理组件的数据,vue 将会递归将 data
的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对)。一旦观察过,不需要再次在数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。
当一个组件被定义,data必须声明为返回一个初始数据对象的函数。
export default {
name: 'NewComponent',
data() {
return {
name: 'xxx',
age: 12
}
}
}
当需要在组件内部修改数据时,可以直接通过vue实例修改:
methods: {
changeName() {
this.name = 'new Name';
}
}
react
props
react中的props与vue一样可以传递静态或动态props,静态props一般传递字符串,在函数组件和class组件都可以使用props,函数组件使用props参数获取父组件传下来的props。
函数组件获取props
:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
class组件使用this.props
获取组件props
:
class Welcome extends React.Component {
constructor(props) {
super(props);
}
render() {
const { name } = this.props;
return <div>{name}</div>;
}
}
动态props:
<Welcome name={name} />
class组件state
class组件在构造函数(constructor)中定义组件内数据(state),修改数据必须通过setState修改,不能直接修改state,这点非常重要。
class组件使用state
:
class Welcome extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'xx'
};
this.changeName = this.changeName.bind(this);
}
changeName() {
this.setState({
name: 'new name'
});
}
render() {
const { name } = this.state;
return <div onClick={this.changeName}>{name}</div>;
}
}
数据流的不同
在Vue1.0中我们可以实现两种双向绑定:在父子组件之间props 可以双向绑定,组件与DOM之间可以通过 v-model 双向绑定
在 Vue2.x 中去掉了第一种,也就是父子组件之间不能双向绑定了(但是提供了一个语法糖自动帮你通过事件的方式修改),并且 Vue2.x 已经不鼓励组件对自己的 props 进行任何修改了。
所以现在我们只有 组件 <--> DOM 之间的双向绑定这一种。
然而 React 从诞生之初就不支持双向绑定,React一直提倡的是单向数据流,他称之为 onChange/setState() 模式。
不过由于我们一般都会用 Vuex 以及 Redux 等单向数据流的状态管理框架,因此很多时候我们感受不到这一点的区别了。