共计 13017 个字符,预计需要花费 33 分钟才能阅读完成。
1. Vue 的长处
① 轻量级框架:只关注视图层,是一个构建数据的视图汇合,大小只有几十 kb;
② 简略易学:国人开发,中文文档,不存在语言障碍,易于了解和学习;
③ 双向数据绑定:保留了 Angular 的特点,在数据操作上更为简略;
④ 组件化:保留了 React 的特点,实现了 HTML 的封装和重用,在构建单页面利用方面有着独特的劣势;
⑤ 视图、数据、构造拆散,使数据的更改更为简略,不须要批改逻辑代码,只须要操作数据就能够实现相干操作;
⑥ 虚构 DOM:操作 DOM 是十分消耗性能的,不再应用原生的 DOM 操作节点,应用虚构 DOM 极大的解放了 DOM 操作,然而具体细节还是 DOM 操作,只不过换了一种形式;
⑦ 运行速度更快:相比于 React 而言,同样是操作虚构 DOM,在性能上 Vue 存在很大的劣势。
2. Vue 初始化过程
初始化根组件时进行了选项合并操作,将全局配置合并到根组件的部分配置上;初始化每个子组件时做了一些性能优化,将组件配置对象上的一些深层次属性放到 vm.$options 选项中,以进步代码的执行效率;初始化组件实例的关系属性,比方 parent、children、root、refs 等;解决自定义事件;调用 beforeCreate 钩子函数;初始化组件的 inject 配置项,失去 ret[key] = val 模式的配置对象,而后对该配置对象进行响应式解决,并代理每个 key 到 vm 实例上;数据响应式,解决 props、methods、data、computed、watch 等选项,解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上;调用 created 钩子函数,如果发现配置项上有 el 选项,则主动调用 $mount 办法,也就是说有了 el 选项,就不须要再手动调用 $mount 办法,反之,没提供 el 选项则必须调用 $mount 办法;接下来则进入挂载阶段。
3. 对 MVVM 的了解
MVVM 由 Model、View、ViewModel 三局部形成,Model 层代表数据模型,也能够在 Model 中定义数据批改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展示进去;ViewModel 是一个同步 View 和 Model 的对象。在 MVVM 架构下,View 和 Model 之间并没有间接的分割,而是通过 ViewModel 进行交互,Model 和 ViewModel 之间的交互是双向的,因而 View 数据的变动会同步到 Model 中,而 Model 数据的变动也会立刻反馈到 View 上。ViewModel 通过双向数据绑定把 View 层和 Model 层连贯了起来,而 View 和 Model 之间的同步工作齐全是主动的,无需人为干预,因而开发者只需关注业务逻辑,不须要手动操作 DOM,不须要关注数据状态的同步问题,简单的数据状态保护齐全由 MVVM 来对立治理。
4. Vue 数据双向绑定原理
实现 mvvm 的数据双向绑定,是采纳数据劫持联合发布者 - 订阅者模式的形式,通过 Object.defineProperty()来给各个属性增加 setter,getter 并劫持监听,在数据变动时公布音讯给订阅者,触发相应的监听回调。就必须要实现以下几点:
(1)实现一个数据监听器 Observer,可能对数据对象的所有属性进行监听,如有变动可拿到最新值并告诉订阅者;
(2)实现一个指令解析器 Compile,对每个元素节点的指令进行扫描和解析,依据指令模板替换数据,以及绑定相应的更新函数;
(3)实现一个 Watcher,作为连贯 Observer 和 Compile 的桥梁,可能订阅并收到每个属性变动的告诉,执行指令绑定的相应回调函数,从而更新视图;
5. Vue 的响应式原理
什么是响应式,也即是说,数据产生扭转的时候,视图会从新渲染,匹配更新为最新的值。Object.defineProperty 为对象中的每一个属性,设置 get 和 set 办法,每个申明的属性,都会有一个专属的依赖收集器 subs,当页面应用到某个属性时,触发 ObjectdefineProperty – get 函数,页面的 watcher 就会被放到属性的依赖收集器 subs 中,在数据变动时,告诉更新;当数据扭转的时候,会触发 Object.defineProperty – set 函数,数据对象会遍历本人的依赖收集器 subs,一一告诉 watcher,视图开始更新。
6. vue 中组件的 data 为什么是一个函数?而 new Vue 实例里,data 能够间接是一个对象?
咱们晓得,Vue 组件其实就是一个 Vue 实例。JS 中的实例是通过构造函数来创立的,每个构造函数能够 new 出很多个实例,那么每个实例都会继承原型上的办法或属性。Vue 的 data 数据其实是 Vue 原型上的属性,数据存在于内存当中。Vue 为了保障每个实例上的 data 数据的独立性,规定了必须应用函数,而不是对象。因为应用对象的话,每个实例(组件)上应用的 data 数据是相互影响的,这当然就不是咱们想要的了。对象是对于内存地址的援用,间接定义个对象的话组件之间都会应用这个对象,这样会造成组件之间数据相互影响。应用函数后,应用的是 data()函数,data()函数中的 this 指向的是以后实例自身,就不会相互影响了。而 new Vue 的实例,是不会被复用的,因而不存在援用对象的问题。
7. Vue 中 data 的属性能够和 methods 中办法同名吗,为什么?
能够同名,methods 的办法名会被 data 的属性笼罩;调试台也会呈现报错信息,然而不影响执行;起因:源码定义的 initState 函数外部执行的程序:props > methods > data > computed > watch。
8. Vue 中 created 与 mounted 区别
在 created 阶段,实例曾经被初始化,然而还没有挂载至 el 上,所以咱们无奈获取到对应的节点,然而此时咱们是能够获取到 vue 中 data 与 methods 中的数据的;在 mounted 阶段,vue 的 template 胜利挂载在 $el 中,此时一个残缺的页面曾经可能显示在浏览器中,所以在这个阶段,能够调用节点了。
9. Vue 中 computed 与 method 的区别
相同点:如果作为模板的数据显示,二者能实现响应的性能,惟一不同的是 methods 定义的办法须要执行。
不同点:1.computed 会基于响应数据缓存,methods 不会缓存;2.diff 之前先看 data 里的数据是否发生变化,如果没有变动 computed 的办法不会执行,但 methods 里的办法会执行;3.computed 是属性调用,而 methods 是函数调用。
10. Vue 中对 mixins 的了解和应用
mixins 是一种散发 Vue 组件中可复用性能的非常灵活的形式。混合对象能够蕴含任意组件选项。当组件应用混合对象时,所有混合对象的选项将被混入该组件自身的选项。而 mixins 引入组件之后,则是将组件外部的内容如 data 等办法、method 等属性与父组件相应内容进行合并。相当于在引入后,父组件的各种属性办法都被裁减了。
11. 为什么 vue 采纳异步渲染
vue 是组件级更新,以后组件里的数据变了,它就会去更新这个组件。当数据更改一次组件就要从新渲染一次,性能不高,为了避免数据一更新就更新组件,所以做了个异步更新渲染。(外围的办法就是 nextTick)
源码实现原理:
当数据变动后会调用 notify 办法,将 watcher 遍历,调用 update 办法告诉 watcher 进行更新,这时候 watcher 并不会立刻去执行,在 update 中会调用 queueWatcher 办法将 watcher 放到了一个队列里,在 queueWatcher 会依据 watcher 的进行去重,多个属性依赖一个 watcher,如果队列中没有该 watcher 就会将该 watcher 增加到队列中,而后通过 nextTick 异步执行 flushSchedulerQueue 办法刷新 watcher 队列。flushSchedulerQueue 中开始会触发一个 before 的办法,其实就是 beforeUpdate,而后 watcher.run() 才开始真正执行 watcher,执行完页面就渲染实现啦,更新实现后会调用 updated 钩子。
12. Vue 的异步更新机制是如何实现的?
Vue 的异步更新机制的外围是利用了浏览器的异步工作队列来实现的,首选微工作队列,宏工作队列次之。当响应式数据更新后,会调用 dep.notify 办法,告诉 dep 中收集的 watcher 去执行 update 办法,watcher.update 将 watcher 本人放入一个 watcher 队列(全局的 queue 数组)。而后通过 nextTick 办法将一个刷新 watcher 队列的办法(flushSchedulerQueue)放入一个全局的 callbacks 数组中。如果此时浏览器的异步工作队列中没有一个叫 flushCallbacks 的函数,则执行 timerFunc 函数,将 flushCallbacks 函数放入异步工作队列。如果异步工作队列中曾经存在 flushCallbacks 函数,期待其执行实现当前再放入下一个 flushCallbacks 函数。flushCallbacks 函数负责执行 callbacks 数组中的所有 flushSchedulerQueue 函数。flushSchedulerQueue 函数负责刷新 watcher 队列,即执行 queue 数组中每一个 watcher 的 run 办法,从而进入更新阶段,比方执行组件更新函数或者执行用户 watch 的回调函数。
13. 对 $nextTick 的了解
用法:在下次 DOM 更新循环完结之后执行提早回调。在批改数据之后立刻应用这个办法,获取更新后的 DOM。Vue 实现响应式并不是数据发生变化之后 DOM 立刻变动,而是按肯定的策略进行 DOM 的更新。Vue 在更新 DOM 时是异步执行的。只有侦听到数据变动,Vue 将开启一个队列,并缓冲在同一事件循环中产生的所有数据变更。如果同一个 watcher 被屡次触发,只会被推入到队列中一次。这种在缓冲时去除反复数据对于防止不必要的计算和 DOM 操作是十分重要的。而后,在下一个的事件循环“tick”中,Vue 刷新队列并执行理论 (已去重的) 工作。所以为了在数据变动之后期待 Vue 实现更新 DOM,能够在数据变动之后立刻应用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新实现后被调用。应用场景:在你更新完数据后,须要及时操作渲染好的 DOM 时。
14. Vue 中罕用的一些指令
- v-model 指令:用于表单输出,实现表单控件和数据的双向绑定。
- v-on:简写为 @,根底事件绑定
- v-bind:简写为:,动静绑定一些元素的属性,类型能够是:字符串、对象或数组。
- v-if 指令:取值为 true/false,管制元素是否须要被渲染
- v-else 指令:和 v -if 指令搭配应用,没有对应的值。当 v -if 的值 false,v-else 才会被渲染进去。
- v-show 指令:指令的取值为 true/false,别离对应着显示 / 暗藏。
- v-for 指令:遍历 data 中寄存的数组数据,实现列表的渲染。
- v-once:通过应用 v-once 指令,你也能执行一次性地插值,当数据扭转时,插值处的内容不会更新。
vue 的自定义指令
Vue 除了外围性能默认内置的指令,Vue 也容许注册自定义指令。自定义指令是用来操作 DOM 的。只管 Vue 推崇数据驱动视图的理念,但并非所有状况都适宜数据驱动。自定义指令就是一种无效的补充和扩大,不仅可用于定义任何的 DOM 操作,并且是可复用的。增加自定义指令的两种形式,全局指令:通过 Vue.directive() 函数注册一个全局的指令;部分指令:通过组件的 directives 属性,对该组件增加一个部分的指令。
15. Vue 生命周期
- beforeCreate:初始化事件,进行数据的观测,此时数据曾经和 data 属性进行绑定。
- created:首先会判断对象是否有 el 选项。如果有的话就持续向下编译,如果没有 el 选项,则进行编译,也就意味着进行了生命周期,直到在该 vue 实例上调用 vm.$mount(el),生命周期才会持续。
- beforeMount:构建虚构 DOM,给 vue 实例对象增加 $el 成员,并且替换掉挂载的 DOM 元素。
- mounted:渲染理论 DOM。
- beforeUpdate:依据数据变动从新构建虚构 DOM。
- updated:渲染 DOM。
- beforeDestroy:销毁 Vue 实例所有的数据绑定、子组件以及事件监听器。
- destroyed:Vue 实例已被销毁,生命周期完结。
16.Vue 组件通信有哪些形式
① 父传子:props。父组件通过 props 向下传递数据给子组件。注:组件中的数据共有三种模式:data、props、computed;
② 父传子孙:provide 和 inject。父组件定义 provide 办法 return 须要分享给子孙组件的属性,子孙组件应用 inject 选项来接管指定的咱们想要增加在这个实例上的 属性;
③ 子传父:通过事件模式。子组件通过 $emit()给父组件发送音讯,父组件通过 v -on 绑定事件接收数据。
④ 父子、兄弟、跨级:eventBus.js。这种办法通过一个空的 Vue 实例作为地方事件总线(事件核心), 用它来(emit)触发事件和(emit)触发事件和(emit)触发事件和(on)监听事件,奇妙而轻量地实现了任何组件间的通信。
⑤ 通信插件:PubSub.js;
⑥ Vuex。vuex 是 vue 的状态管理器,存储的数据是响应式的。只须要把共享的值放到 vuex 中,其余须要的组件间接获取应用即可。
17. router 和 route 的区别
router 为 VueRouter 的实例,相当于一个全局的路由器对象,外面含有很多属性和子对象,例如 history 对象。常常用的跳转链接就能够用 this.$router.push,和 router-link 跳转一样。route 相当于以后正在跳转的路由对象。。能够从外面获取 name, path, params, query 等。
18. vue-router 有几种钩子函数?
① 全局路由:全局导航钩子次要有两种钩子:前置守卫(beforeEach)、后置钩子(afterEach);
② 路由独享的钩子:单个路由独享的导航钩子,它是在路由配置上间接进行定义的;
③ 组件内的导航钩子:组件内的导航钩子次要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。他们是间接在路由组件外部间接进行定义的。
19. vue-router 路由传参
router-link 进行页面按钮式路由跳转传参;this.$router.push 进行编程式路由跳转传参。
20. keep-alive
keep-alive 是 Vue 的内置组件,能在组件切换过程中将状态保留在内存中,避免反复渲染 DOM。keep-alive 包裹动静组件时,会缓存不流动的组件实例,而不是销毁它们。
钩子函数:”activated“组件渲染后调用”deactivated“组件销毁后调用
原理:Vue.js 外部将 DOM 节点形象成了一个个的 VNode 节点,keep-alive 组件的缓存也是基于 VNode 节点的而不是间接存储 DOM 构造。它将满足条件(pruneCache 与 pruneCache)的组件在 cache 对象中缓存起来,在须要从新渲染的时候再将 vnode 节点从 cache 对象中取出并渲染。
配置属性:include 字符串或正则表达式。只有名称匹配的组件会被缓存 exclude 字符串或正则表达式。任何名称匹配的组件都不会被缓存 max 数字、最多能够缓存多少组件实例。
21. Vuex 是什么?怎么应用?
Vuex 是实现组件全局状态(数据)治理的一种机制,能够不便实现组件之间的数据共享;Vuex 集中管理共享的数据,易于开发和前期保护;可能高效的实现组件之间的数据共享,进步开发效率;存储在 Vuex 的数据是响应式的,可能实时放弃页面和数据的同步;
Vuex 重要外围属性包含:state, mutations, action, getters, modules。
state:Vuex 应用繁多状态树, 即每个利用将仅仅蕴含一个 store 实例,但繁多状态树和模块化并不抵触。寄存的数据状态,不能够间接批改外面的数据。
mutations:mutations 定义的办法动静批改 Vuex 的 store 中的状态或数据。
action:actions 能够了解为通过将 mutations 外面处里数据的办法变成可异步的解决数据的办法,简略的说就是异步操作数据。view 层通过 store.dispath 来散发 action。
getters:相似 vue 的计算属性,次要用来过滤一些数据。
modules:我的项目特地简单的时候,能够让每一个模块领有本人的 state、mutation、action、getters, 使得构造十分清晰,方便管理。
22. Vuex 和单纯的全局对象有什么区别?
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。不能间接扭转 store 中的状态。扭转 store 中的状态的惟一路径就是显式地提交 (commit) mutation。这样使得咱们能够不便地跟踪每一个状态的变动,从而让咱们可能实现一些工具帮忙咱们更好地理解咱们的利用。
23. 为什么 Vuex 的 mutation 中不能做异步操作?
每个 mutation 执行实现后都会对应到一个新的状态变更,这样 devtools 就能够打个快照存下来,而后就能够实现 time-travel 了。如果 mutation 反对异步操作,就没有方法晓得状态是何时更新的,无奈很好的进行状态的追踪,给调试带来艰难。
24. axios 是什么,其特点和罕用语法
Axios 是一个基于 promise 的 HTTP 库,能够用在浏览器和 node.js 中。前端最风行的 ajax 申请库,react/vue 官网都举荐应用 axios 发 ajax 申请。
特点:
基于 promise 的异步 ajax 申请库,反对 promise 所有的 API;浏览器端 /node 端都能够应用,浏览器中创立 XMLHttpRequests;反对申请/响应拦截器,反对申请勾销;能够转换申请数据和响应数据,并对响应回来的内容主动转换成 JSON 类型的数据;批量发送多个申请;安全性更高,客户端反对进攻 XSRF,就是让你的每个申请都带一个从 cookie 中拿到的 key, 依据浏览器同源策略,混充的网站是拿不到你 cookie 中得 key 的,这样,后盾就能够轻松分别出这个申请是否是用户在混充网站上的误导输出,从而采取正确的策略。
25. 对 SSR 有理解吗,它次要解决什么问题?
Server-Side Rendering 咱们称其为 SSR,意为服务端渲染指由服务侧实现页面的 HTML 构造拼接的页面解决技术,发送到浏览器,而后为其绑定状态与事件,成为齐全可交互页面的过程;
解决了以下两个问题:
seo:搜索引擎优先爬取页面 HTML 构造,应用 ssr 时,服务端曾经生成了和业务想关联的 HTML,有利于 seo;首屏出现渲染:用户无需期待页面所有 js 加载实现就能够看到页面视图(压力来到了服务器,所以须要衡量哪些用服务端渲染,哪些交给客户端)。
毛病:
复杂度:整个我的项目的复杂度进步;性能会受到影响;服务器负载变大,绝对于前后端拆散务器只须要提供动态资源来说,服务器负载更大,所以要谨慎应用。
26. 做过哪些 Vue 的性能优化?
编码阶段尽量减少 data 中的数据,data 中的数据都会减少 getter 和 setter,会收集对应的 watcher。v-if 和 v -for 不能连用。如果须要应用 v -for 给每项元素绑定事件时应用事件代理。SPA 页面采纳 keep-alive 缓存组件。在更多的状况下,应用 v -if 代替 v -show。key 保障惟一。应用路由懒加载、异步组件。防抖、节流。第三方模块按需导入。长列表滚动到可视区域动静加载。图片懒加载。SEO 优化。服务端渲染 SSR。预渲染。打包优化。压缩代码。应用 cdn 加载第三方模块。splitChunks 抽离公共文件。
27. Vue 动静路由
动静路由,动静即不是写死的,是可变的。咱们能够依据本人不同的需要加载不同的路由,做到不同的实现及页面的渲染。动静的路由存储可分为两种,一种是将路由存储到前端。另一种则是将路由存储到数据库。动静路由的应用个别联合角色权限管制一起应用。
益处:应用动静路由能够跟灵便,无需手工保护,咱们能够应用一个页面对路由进行保护。如果将路由存储到数据库,还能够减少安全性。
如何实现:个别咱们在登录的时候,依据登录用户的角色返回此角色能够拜访的页面的路由,前端将路由存储到 vuex(vuex 存储的数据必须可长久的,不要一刷新页面就不见), 咱们在路由前置守卫处动静增加拿到的路由,对页面进行渲染。
28. computed 与 watch
watch
属性监听,是一个对象,键是须要察看的属性,值是对应回调函数,次要用来监听某些特定数据的变动,从而进行某些具体的业务逻辑操作, 监听属性的变动,须要在数据变动时执行异步或开销较大的操作时应用。
computed
计算属性,属性的后果会被缓存,当 computed 中的函数所依赖的属性没有产生扭转的时候,那么调用以后函数的时候后果会从缓存中读取。除非依赖的响应式属性变动时才会从新计算,次要当做属性来应用 computed 中的函数必须用 return 返回最终的后果 computed 更高效,优先应用。data 不扭转,computed 不更新。
应用场景
computed:当一个属性受多个属性影响的时候应用,例:购物车商品结算性能。
watch:当一条数据影响多条数据的时候应用,例:搜寻数据。
29. v-if 和 v-for 的优先级
v-for 的优先级是高于 v -if 的,如果两者同时呈现的话,那每次循环都会执行 v -if,会很节约性能,咱们正确的做法应该是再 v -for 的里面新增一个模板标签 template,在 template 上应用 v -if。
30. v-for 中 key 的作用
- key 的作用是为了在 diff 算法执行时更快的找到对应的节点,进步 diff 速度,更高效的更新虚构 DOM;
- Vue 在 patch 过程中判断两个节点是否是雷同节点,key 是一个必要条件,渲染一组列表时,key 往往是惟一标识,所以如果不定义 key 的话,Vue 只能认为比拟的两个节点是同一个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个 patch 过程比拟低效,影响性能;
- 从源码中能够晓得,Vue 判断两个节点是否雷同时次要判断两者的 key 和元素类型等,因而如果不设置 key, 它的值就是 undefined,则可能永 远认为这是两个雷同的节点,只能去做更新操作,这造成了大量的 dom 更新操作,显著是不可取的。
31. Vue2 和 Vue3 区别
属性监听:
defineProperty: 遍历对象,劫持对象的每一个属性; Proxy: 劫持整个对象,并返回一个代理对象;
对数组办法的反对:
defineProperty: push… 等不能监听;Proxy: 能够监听;
兼容:
defineProperty(ES5)兼容性比 Proxy(ES6)好。
32. webpack 罕用 Loader
- raw-loader:加载文件原始内容(utf-8)
- file-loader:把文件输入到一个文件夹中,在代码中通过绝对 URL 去援用输入的文件 (解决图片和字体)
- source-map-loader:加载额定的 Source Map 文件,以不便断点调试
- svg-inline-loader:将压缩后的 SVG 内容注入代码中
- image-loader:加载并且压缩图片文件
- json-loader 加载 JSON 文件(默认蕴含)
- babel-loader:把 ES6 转换成 ES5
- ts-loader: 将 TypeScript 转换成 JavaScript
- awesome-typescript-loader:将 TypeScript 转换成 JavaScript,性能优于 ts-loader
- sass-loader:将 SCSS/SASS 代码转换成 CSS
- css-loader:加载 CSS,反对模块化、压缩、文件导入等个性
- style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
- postcss-loader:扩大 CSS 语法,应用下一代 CSS,能够配合 autoprefixer 插件主动补齐 CSS3 前缀
- vue-loader:加载 Vue.js 单文件组件
33. webpack 罕用的 Plugin
- define-plugin:定义环境变量 (Webpack4 之后指定 mode 会主动配置)
- ignore-plugin:疏忽局部文件
- html-webpack-plugin:简化 HTML 文件创建 (依赖于 html-loader)
- web-webpack-plugin:可不便地为单页利用输入 HTML,比 html-webpack-plugin 好用
- uglifyjs-webpack-plugin:不反对 ES6 压缩 (Webpack4 以前)
- terser-webpack-plugin: 反对压缩 ES6 (Webpack4)
- webpack-parallel-uglify-plugin: 多过程执行代码压缩,晋升构建速度
- mini-css-extract-plugin: 拆散款式文件,CSS 提取为独立文件,反对按需加载 (代替 extract-text-webpack-plugin)
- serviceworker-webpack-plugin:为网页利用减少离线缓存性能
- clean-webpack-plugin: 目录清理
34. webpack loader 和 plugin 的区别
Loader 实质就是一个函数,在该函数中对接管到的内容进行转换,返回转换后的后果。因为 Webpack 只意识 JavaScript,所以 Loader 就成了翻译官,对其余类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件能够扩大 Webpack 的性能,在 Webpack 运行的生命周期中会播送出许多事件,Plugin 能够监听这些事件,在适合的机会通过 Webpack 提供的 API 扭转输入后果。
Loader 在 module.rules 中配置,作为模块的解析规定,类型为数组。每一项都是一个 Object,外部蕴含了 test(类型文件)、loader、options (参数)等属性。
Plugin 在 plugins 中独自配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
35. 怎么了解 Vue 的单向数据流?
所有的 prop 都使得其父子 prop 之间造成了一个单向上行绑定:父级 prop 的更新会向下流动到子组件中,然而反过来则不行。
这样会避免从子组件意外扭转父级组件的状态,从而导致你的利用的数据流向难以了解。
额定的,每次父级组件产生更新时,子组件中所有的 prop 都将会刷新为最新的值。
这意味着你不应该在一个子组件外部扭转 prop。如果你这样做了,Vue 会在浏览器的控制台中收回正告。
子组件想批改时,只能通过 $emit 派发一个自定义事件,父组件接管到后,由父组件批改。
36. 间接给一个数组项赋值,Vue 能检测到变动吗?
因为 JavaScript 的限度,Vue 不能检测到以下数组的变动:
- 当你利用索引间接设置一个数组项时,例如:vm.items[indexOfItem] = newValue;
- 当你批改数组的长度时,例如:vm.items.length = newLength。
为了解决第一个问题,Vue 提供了以下操作方法:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// vm.$set,Vue.set 的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
为了解决第二个问题,Vue 提供了以下操作方法:
// Array.prototype.splice
vm.items.splice(newLength)
37. Vue 的父组件和子组件生命周期钩子函数执行程序?
Vue 的父组件和子组件生命周期钩子函数执行程序能够归类为以下 4 局部:
- 加载渲染过程 :
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted - 子组件更新过程 :
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated - 父组件更新过程 :
父 beforeUpdate -> 父 updated - 销毁过程 :
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
38. 父组件能够监听到子组件的生命周期吗?
比方有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑解决,能够通过以下写法实现:
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {this.$emit("mounted");
}
以上须要手动通过 $emit 触发父组件的事件,更简略的形式能够在父组件援用子组件时通过 @hook 来监听即可,如下所示:
// Parent.vue
<Child @hook:mounted="doSomething" ></Child>
doSomething() {console.log('父组件监听到 mounted 钩子函数 ...');
},
// Child.vue
mounted(){console.log('子组件触发 mounted 钩子函数 ...');
},
// 以上输入程序为:// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ...
当然 @hook 办法不仅仅是能够监听 mounted,其它的生命周期事件,例如:created,updated 等都能够监听。
39. v-model 的原理?
咱们在 vue 我的项目中次要应用 v-model 指令在表单 input、textarea、select 等元素上创立双向数据绑定,咱们晓得 v-model 实质上不过是语法糖,v-model 在外部为不同的输出元素应用不同的属性并抛出不同的事件:
- text 和 textarea 元素应用 value 属性和 input 事件;
- checkbox 和 radio 应用 checked 属性和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
40. 虚构 DOM 的优缺点?
长处:
- 保障性能上限:框架的虚构 DOM 须要适配任何下层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;然而比起粗犷的 DOM 操作性能要好很多,因而框架的虚构 DOM 至多能够保障在你不须要手动优化的状况下,仍然能够提供还不错的性能,即保障性能的上限;
- 无需手动操作 DOM:咱们不再须要手动去操作 DOM,只须要写好 View-Model 的代码逻辑,框架会依据虚构 DOM 和 数据双向绑定,帮咱们以可预期的形式更新视图,极大进步咱们的开发效率;
- 跨平台:虚构 DOM 实质上是 JavaScript 对象, 而 DOM 与平台强相干,相比之下虚构 DOM 能够进行更不便地跨平台操作,例如服务器渲染、weex 开发等等。
毛病:
- 无奈进行极致优化:尽管虚构 DOM + 正当的优化,足以应答绝大部分利用的性能需求,但在一些性能要求极高的利用中虚构 DOM 无奈进行针对性的极致优化。
41. 虚构 DOM 实现原理?
虚构 DOM 的实现原理次要包含以下 3 局部:
- 用 JavaScript 对象模仿实在 DOM 树,对实在 DOM 进行形象;
- diff 算法 — 比拟两棵虚构 DOM 树的差别;
- pach 算法 — 将两个虚构 DOM 对象的差别利用到真正的 DOM 树。