1 Vue.js 双向绑定的原理
Vue.js 2.0 采纳数据劫持(Proxy 模式)联合发布者 - 订阅者模式(PubSub 模式)的形式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时公布音讯给订阅者,触发相应的监听回调。
每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会告诉 watcher 从新计算,从而以致它关联的组件得以更新。
Vue.js 3.0, 放弃了 Object.defineProperty,应用更快的 ES6 原生 Proxy (拜访对象拦截器, 也称代理器)
步骤:
须要 observe 的数据对象进行递归遍历,包含子属性对象的属性,都加上 setter 和 getter 这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变动
compile 解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者,一旦数据有变动,收到告诉,更新视图
Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,次要做的事件是: ①在本身实例化时往属性订阅器 (dep) 外面增加本人 ②本身必须有一个 update()办法 ③待属性变动 dep.notice()告诉时,能调用本身的 update()办法,并触发 Compile 中绑定的回调,则功成身退。
MVVM 作为数据绑定的入口,整合 Observer、Compile 和 Watcher 三者,通过 Observer 来监听本人的 model 数据变动,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer 和 Compile 之间的通信桥梁,达到数据变动 -> 视图更新;视图交互变动(input) -> 数据 model 变更的双向绑定成果。
2. Vue.js 3.0 放弃 defineProperty, 应用 Proxy 的起因
Object.defineProperty 缺点
监控到数组下标的变动时,开销很大。所以 Vue.js 放弃了下标变动的检测;
Object.defineProperty 只能劫持对象的属性,而 Proxy 是间接代理对象。Object.defineProperty 须要遍历对象的每个属性,如果属性值也是对象,则须要深度遍历。而 Proxy 间接代理对象,不须要遍历操作。
Object.defineProperty 对新增属性须要手动进行 Observe。vue2 时须要应用 vm.$set 能力保障新增的属性也是响应式
Proxy 反对 13 种拦挡操作,这是 defineProperty 所不具备的
Proxy 作为新规范,久远来看,JS 引擎会持续优化 Proxy,但 getter 和 setter 根本不会再有针对性优化
3. Vue 2 中给 data 中的对象属性增加一个新的属性时会产生什么?如何解决?
视图并未刷新。这是因为在 Vue 实例创立时,新属性并未申明,因而就没有被 Vue 转换为响应式的属性,天然就不会触发视图的更新,这时就须要应用 Vue 的全局 api $set():this.$set(this.obj, ‘new_property’, ‘new_value’)
4. Computed 和 Watch 的区别
computed 计算属性 : 依赖其它属性值, 并且 computed 的值有缓存, 只有它依赖的 属性值产生扭转, 下一次获取 computed 的值时才会从新计算 computed 的值。
watch 侦听器 : 更多的是察看的作用, 无缓存性, 相似于某些数据的监听回调, 每 当监听的数据变动时都会执行回调进行后续操作。
5. data 为什么是一个函数而不是对象
JavaScript 中的对象是援用类型的数据,当多个实例援用同一个对象时,只有一个实例对这个对象进行操作,其余实例中的数据也会发生变化。
而在 Vue 中,咱们更多的是想要复用组件,那就须要每个组件都有本人的数据,这样组件之间才不会互相烦扰。
所以组件的数据不能写成对象的模式,而是要写成函数的模式。数据以函数返回值的模式定义,这样当咱们每次复用组件的时候,就会返回一个新的 data,也就是说每个组件都有本人的公有数据空间,它们各自保护本人的数据,不会烦扰其余组件的失常运行。
6. 父子组件的生命周期程序
加载渲染过程:
父 beforeCreate-> 父 created-> 父 beforeMount-> 子 beforeCreate-> 子 created-> 子 beforeMount-> 子 mounted-> 父 mounted
子组件更新过程:父 beforeUpdate-> 子 beforeUpdate-> 子 updated-> 父 updated
父组件更新过程:父 beforeUpdate-> 父 updated
销毁过程:父 beforeDestroy-> 子 beforeDestroy-> 子 destroyed-> 父 destroyed
7. 服务器渲染
destroyed-> 父 destroyed
8.Vue 的生命周期办法有哪些?个别在哪一步发动申请及起因
beforeCreate:在 new 一个 vue 实例后,只有一些默认的生命周期钩子和默认事件,其余的货色都还没创立。在 beforeCreate 生命周期执行的时候,data 和 methods 中的数据都还没有初始化。不能在这个阶段应用 data 中的数据和 methods 中的办法
create:data 和 methods 都曾经被初始化好了,如果要调用 methods 中的办法,或者操作 data 中的数据,最早能够在这个阶段中操作
beforeMount:执行到这个钩子的时候,在内存中曾经编译好了模板了,然而还没有挂载到页面中,此时,页面还是旧的
mounted:执行到这个钩子的时候,就示意 Vue 实例曾经初始化实现了。此时组件脱离了创立阶段,进入到了运行阶段。如果咱们想要通过插件操作页面上的 DOM 节点,最早能够在和这个阶段中进行
beforeUpdate:当执行这个钩子时,页面中的显示的数据还是旧的,data 中的数据是更新后的,页面还没有和最新的数据放弃同步
updated:页面显示的数据和 data 中的数据曾经放弃同步了,都是最新的
beforeDestory:Vue 实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods,指令,过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed:这个时候上所有的 data 和 methods,指令,过滤器 ……都是处于不可用状态。组件曾经被销毁了。
补充答复:
created 实例曾经创立实现,因为它是最早触发的起因能够进行一些数据,资源的申请。(服务端渲染反对 created 办法)
mounted 实例曾经挂载实现,能够进行一些 DOM 操作
beforeUpdate 能够在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated 能够执行依赖于 DOM 的操作。然而在大多数状况下,你应该防止在此期间更改状态,因为这可能会导致更新有限循环。该钩子在服务器端渲染期间不被调用。
destroyed 能够执行一些优化操作, 清空定时器,解除绑定事件
9.mixin 混入
10. 过滤器 filter
全局
部分
11. 插槽
12.vuex
state:寄存公共数据的中央;
getter:获取依据业务场景解决返回的数据;
mutations:惟一批改 state 的办法,批改过程是同步的;
action:异步解决,通过散发操作触发 mutation;
module:将 store 模块宰割,缩小代码臃肿
9.params 和 query 的区别
答:用法:query 要用 path 来引入,params 要用 name 来引入,接管参数都是相似的,别离是 this.$route.query.name 和 this.$route.params.name。
url 地址显示:query 更加相似于咱们 ajax 中 get 传参,params 则相似于 post,说的再简略一点,前者在浏览器地址栏中显示参数,后者则不显示
留神点:query 刷新不会失落 query 外面的数据
params 刷新 会 失落 params 外面的数据。
10. vue-router 有哪几种导航钩子?
全局导航钩子:router.beforeEach(to,from,next)
组件内的钩子 beforeRouteEnter (to, from, next) beforeRouteUpdate (to, from, next) beforeRouteLeave (to, from, next)
独自路由独享组件 beforeEnter: (to, from, next)