Vue经过Object.defineProperty
定义数据的存取描述符(set和get),来追踪数据变化。css
在Vue组件初始化时,data下的属性会被循环遍历添加上set和get,直到全部的子孙属性都被添加完。当data的某一属性值发生了变化(执行set)时,它就会向订阅了该数据的组件发布通知,去更新组件。前端
在set里,组件能够订阅该数据变化的通知。vue
set和get叫对象的存取描述符,与存取描述符对应的叫数据描述符。两者不能共存,默认状况下,是数据描述符。以下: react
React用比较引用来追踪数据变化的方式。在setState的时候,React会用新的state直接替换掉旧state。webpack
以下面,每次执行handleClick,即使没有改变数据的数值,(但引用地址发生变化了),组件也会从新渲染。这个渲染是不必的。ios
在获得通知数据变化时,React和Vue都采用了vDOM diff算法,各自去更新组件。在追踪数据变化上,Vue比React更加高效。es6
Vue没法检测对象属性的增删变化和数组索引长度的变化,在定义object类型的数据时,通常把它下面的属性也定义了。可是,JS是一门动态语言,能够不预先定义对象,而且任意地操做对象的属性。结合v-model使用时,object类型数据的属性也能够不用预先定义。web
例如,在表单型的组件里,一个常见的行为,不给formData定义title、type等这些属性,v-model会自动响应用户输入,并添加属性到formData上。ajax
<template>
<div>
<input v-model="formData.title" placeholder="请输入标题" />
<select v-model="formData.type">
<option value="1">类别</option>
</select>
</div>
</template>
data() {
return {
formData: {}
}
}
复制代码
props是组件间自上向下通讯数据的方式,子组件逆向修改props,Vue会警告应当避免直接操做props,用data或者computed属性代替,修改值也不会被传递到父组件。算法
然而,借助v-model,object类型props值,也能够由子组件传递给父组件。简单类型的props值仍旧没法修改。
原来,v-model内部检测到绑定的是对象的key时(indexOf('.') > 0),会调用set方法,更新属性到对象上,并给组件添加了订阅事件。
Vue1.0采用的是双向数据绑定,Vue2.0采用的是单向数据流,即只能父对子通讯,子对父通讯要用回调函数的方式。 Vue3.0之前没法检测到数据属性的增删变化,经常使用Vue.prototype.$set和JSON.parse(JSON.stringify)去纠正这一点。将来Vue3.0将用proxy代替
Object.defineProperty
监听数据变化,proxy将直接监听对象,而不是监听属性,它能够检测到数组和对象的增删变化。
JS开发有三大难点,原型、闭包和做用域。在es6 module的帮助下,原型和闭包的坑已经很少了,剩下的做用域成了最常遇到的坑。
在React当中,给组件添加事件必需要修正函数的执行做用域。像下面这样,onClick是定义在全局做用域上的,它的this就是undefined。由于js是静态做用域语言,它做用域是定义时肯定的。在这里,要拿到React组件实例内部的state,全部bind函数的做用域到组件实例上。
Vue采用相似shadow DOM的方式对CSS进行封装,添加了scoped属性后,CSS只做用在组件内部,组件之间的CSS不会互相影响。
React采用css in js、css module、style-component的方式封装CSS,都没有Vue好用。
React的css in js写法
相比React,Vue和JS这门语言契合度是最高的,它没有科班化的数据流管理,没有刀耕火种的JS编写方式。
Vue的追踪数据机制、v-model双向绑定和js/css做用域,都很巧妙的利用JS做为一门动态语言的优点。这使Vue成为一门很是容易上手的技术框架,在快节奏、频繁的迭代的开发需求中占有一席之地。我在商业产品部一年多一共开发和维护了9个项目,包括1个react、1个angular和7个vue项目。Vue很是容易上手,有些简单的需求,就让后端同窗代劳了。
一直以来,都有一个争议点,Vue适合作小型项目,React适合开发大型项目。之前,Vue饱受诟病的是数据流管理,实际上,如今Vue2和React已经相差不大了,借助v-model和vuex,Vue甚至比React更胜一筹。将来Vue3会用Typescript写,构建项目将会更加稳健。
react和vue都在用的组件通讯方式之一,简约又简单。
依赖组件父子关系。
以下,子组件实例化过程当中,若是发现父组件订阅了子组件的事件,就会把订阅的事件添加到events列表里,以此容许开发者来发布事件,即$emit事件。
适用于全部组件,不依赖组件之间的嵌套关系。
在EventBus里,实例化一个Vue实例做为一个观察者,全部的组件都做为订阅者。
// EventBus.js
import Vue from 'vue';
export default new Vue();
复制代码
// 添加订阅者
eventBus.$on('reset-preview', this.closeHandler);
// 发布通知
eventBus.$emit('preview');
复制代码
Vue内部实现了on和emit两个方法,on方法添加订阅者到队列里,emit在事件变化时,发布通知给订阅者。
EventBus虽然不依赖组件嵌套关系,可是数据流向是随意的,对于复杂的业务需求,难以支撑。因此须要一个中心化的观察者,观察数据变化,自上而下组件响应数据变化,自下而上更新数据变化到观察者中心。
emit回调和eventBus的区别是什么?
emit回调是强调组件关系,父组件是订阅者,子组件是发布者。 eventBus不关心组件关系,eventBus实例化的一个实例是发布者,组件都是订阅者。
优势:
使用vuex须要注意的点
vuex和vue同样都是经过劫持setter/getter追踪数据变化的,因此vuex也不能检测到array和object的增删。
例如表单型的数据,须要增长字段,向后台提交。vuex没法处理属性增删,$store.commit到store里,store里的数据不会更新。
例如,一个复杂类型的数据,从服务端请求出来存到vuex里,而后在多个组件之间传递,在数据处理结束以后,又提交给服务端。此时,应该清除vuex保存的数据,以便在下一次打开页面时,vuex里的数据是干净的。
通常,在组件的created生命周期检查vuex缓存是否存在,没有缓存,则从新拉数据。在组件生命周期结束前,重置store,清除数据缓存。
什么状况下适合用vuex呢?
只有在用React实在解决不了的时候,才用Redux。--------Redux做者
过分使用vuex,将使项目变得臃肿,组件之间耦合度增长。
传统型,适用于各页面之间的数据传递。对于一些须要粘贴url让其余人访问的需求,须要在router里加上必须参数,而不能在vuex里。
好比筛选列表页,媒体流量桶管理页。这种页面结构相同,种类又众多。不能拆分红多个页面,但又须要独立的页面展现效果,适合把数据保存在route里。
使用router传参时,须要注意:
用于嵌套的表单型组件
好比建立父任务时,父任务表单里同时又能够添加子任务,子认为有分别能够添加不一样的任务奖励规则。 好比建立订单时,能够添加广告组、广告计划、广告创意,广告创意里能够添加各种素材。 这些嵌套复杂的表单型组件,比较适合用这个。
修改封闭,扩展开放。
功能组件仍是ui组件?简化使用。 好比pagnition处理total < 1时,不显示分页器 好比筛选列表组件,保留UI部分,把提交按钮用slot写进去 功能组件,好比upload组件
尽量减小外部依赖 组件内的功能点,对外界的依赖越少越好。 越简单越好。 参考设计的最高境界,Kiss规则。
建立axios的实例对ajax的封装,减小处理回调的代码量。直接修改axios的拦截器会污染整个工程ajax调用规则。对于屡次import进来的文件,webpack只会打包一次。