1、Vue双向数据绑定的原理
vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:(1)第一步:需要observe(发布者)的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化 (2) 第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图 (3)第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:1、在自身实例化时往属性订阅器(dep)里面添加自己 2、自身必须有一个update()方法3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。(4)第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
2、Vue虚拟DOM树的原理
在大型项目中,不断的改变DOM,开销非常大;希望以最小的修改量实现DOM树的更新。(维护状态,更新视图)
原理步骤:(Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存,只将变更写入DOM)
(1)用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
(2)当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
(3)把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新了
注意:视图的结构确实是整个全新渲染了,但是最后操作DOM的时候确实只变更有不同的地方
Virtual DOM 的 diff 算法只对同级元素进行对比;Virtual DOM 算法主要是实现上面步骤的三个函数:element,diff,patch。
原地复用,用key值解决。(同级中相同的节点类型会复用)
https://www.zhihu.com/question/29504639/answer/73607810
https://blog.csdn.net/yczz/article/details/51292169
3、Vue-router如何实现路由跳转的
(1)监控路由变化的history对象
安装插件\根据路由配置生成router实例 \将router实例传入根vue实例
(2)主动触发<router-link>
router-link绑定了click方法,触发history.push或者history.replace,从而触发history.transitionTo 同时会监控hashchange和popstate来对路由变化作对用的处理
4、Vuex的状态管理的流程
在Vue组件中dispatch actions,action中commit mutations,mutations是唯一可以触发state中数据状态更新的方法。
5、Vue的生命周期钩子函数有哪些,mouted钩子和created钩子不同
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。更新前/后:当data变化时,会触发beforeUpdate和updated方法。销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在。
6、Vue父子间通信
(1)子组件使用props:[]暴露出属性,父组件直接传值修改props——父向子传值
(2)自定义事件:在子组件的实现方法中利用this.$emit("a")触发a事件,当父组件调用子组件时,直接在该子组件上@a进行触发——子向父传值
7、用Vue实现一个非父子组件间的点击改变对方背景色或者改变对方内容;再用Jquery实现;并将Vue和Jquery进行对比
过程:(1)新建Vue对象(2)将父组件的id挂载到el上(3)用data填充数据,massage,活动的class一会style信息等(4)添加method方法
注意:对css的操作可以通过绑定class或者绑定style。
以下时Jquery方法(样式同上):
区别:
Vue直接操作视图层,不需要操作DOM节点,我们只需要关注逻辑,完全实现了视图层和逻辑层的解耦;
Jquery的操作是基于DOM节点的操作,它的优势在于良好的封装和兼容,使调用简单方便。
8、Vue中的请求代码应该放在组件的method中还是Vuex的action中?你是怎么做的?
我在项目中的做法:将登陆请求以及对返回数据的处理写在业务组件的method中,将姓名和邮箱信息等利用localstorage中,放到vuex的module中处理,其它页面需要显示相关信息时,取得数据即可。因为这是组件自己的请求,放在method中是没问题的,不存在复用问题。
我个人的思考是:大型项目中,要实现代码复用,可以将请求封装到Actions中,业务代码逻辑中只有对Actions的调用操作,将请求返回的数据处理好之后传入mutations中,mutations中仅仅是对数据进行增删改的处理,然后映射到state中。在组件中dispatch Actions后,异步commit mutations,直接改变state中的数据,state中的数据变化直接触发View视图的更新,符合数据流的走向。
9、Vue中computed、method和watch的区别?
computed计算属性:HTML DOM加载完成后立即执行,相当于赋值。计算属性是根据依赖进行缓存的,只有当依赖改变时,才会重新计算求值;依赖不改变时,不会调用该函数而是直接返回之前的值。
method属性:需要一定的条件触发调用后才能执行,比如click。只要页面重新渲染就会调用method中的函数。
PS:当一个性能开销很大的计算属性A,要遍历很大的数组,又有别的计算属性依赖于A,这时,利用计算属性的缓存原理,可以避免多次重复计算。这种情况下显然不适合用method。
watch侦听器:(自定义侦听器)Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
10、为什么要使用key?
key是Vue中识别节点的通用机制;页面更新重新渲染时,同一级的节点默认是原地复用的渲染规则。
key 的特殊属性主要用在 Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法(如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。)。使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。(高效更新虚拟DOM)
有相同父元素的子元素必须有独特的key。重复的key会造成渲染错误。