Vue基础
# 1. Vue最核心的两个功能是?
查看答案
数据驱动和组件化
# 2. Vue单向的数据流程要素有哪些?
查看答案
- state:数据源
- view:视图
- actions:行为,用户和视图交互改变状态的方式
# 3. Vue组件间通信方式有哪些?
查看答案
# 父子组件传值
- 父组件给子组件通过相应属性传值,子组件用props接收
- 子组件通过自定义时间,触发emit携带参数给父组件传值,父组件通过on注册子组件内部触发的事件,并接收传递的数据
$refs
$parent/$children
$root
- provide/inject
# 不相关组件传值
# eventBus
- 创建一个公共的Vue实例,这个实例的作用是作为事件总线,或者事件中心。
- 触发事件的组件通过$emit触发并传递参数
- 注册时间的组件通过$on注册事件并接收参数
# Vuex
- 集中状态管理工具
# 4. 在 Vue 中,子组件为何不可以修改父组件传递的 Prop?
查看答案
如果修改了,Vue 是如何监控到属性的修改并给出警告的。
1、子组件为何不可以修改父组件传递的 Prop 单向数据流,易于监测数据的流动,出现了错误可以更加迅速的定位到错误发生的位置。 2、如果修改了,Vue 是如何监控到属性的修改并给出警告的。
在 initProps 的时候,在 defineReactive 时通过判断是否在开发环境,如果是开发环境,会在触发 set 的时候判断是否此 key 是否处于 updatingChildren 中被修改,如果不是,说明此修改来自子组件,触发 warning 提示。
需要特别注意的是,当你从子组件修改的 prop 属于基础类型时会触发提示。这种情况下,你是无法修改父组件的数据源的, 因为基础类型赋值时是值拷贝。
你直接将另一个非基础类型(Object, array)赋值到此 key 时也会触发提示(但实际上不会影响父组件的数据源), 当你修改 object 的属性时不会触发提示,并且会修改父组件数据源的数据。
# 5. Vue 的父组件和子组件生命周期钩子执行顺序是什么
查看答案
# 创建
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
# 更新
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
# 销毁
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
# 6. vue 在 v-for 时给每项元素绑定事件需要用事件代理吗?
查看答案
vue中并没有给元素添加事件代理。
事件代理主要有什么作用是?
- 事件代理能够避免我们逐个的去给元素新增和删除事件。
- 事件代理比每一个元素都绑定一个事件性能要更好。
从vue的角度上来看:
- 在v-for中,我们直接用一个for循环就能在模板中将每个元素都绑定上事件,并且当组件销毁时,vue也会自动给我们将所有的事件处理器都移除掉。所以事件代理能做到的第一点vue已经给我们做到了
- 在v-for中,给元素绑定的都是相同的事件,所以除非上千行的元素需要加上事件,其实和使用事件代理的性能差别不大,所以也没必要用事件代理。
如果我们自己在非 vue 中需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。
# 7. v-for和v-if的优先级谁高? TODO
# 8. Computed 和 Watch 的区别
查看答案
对于Computed:
- 它支持缓存,只有依赖的数据发生了变化,才会重新计算。computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
- 不支持异步,当Computed中有异步操作时,无法监听数据的变化
- 如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值;在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。
对于Watch:
- 它不支持缓存,数据变化时,它就会触发相应的操作,类似于某些数据的监听回调,监听数据必须是data中声明的或者父组件传递过来的props中的数据。
- 支持异步监听
- 监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
- 函数有两个的参数:
- immediate:组件加载立即触发回调函数
- deep:深度监听,例如数组中的对象发生变化。需要注意的是,deep为true,就可以监测到对象中每个属性的变化,它会一层层遍历,给这个对象的所有属性都加上这个监听器。 运用场景:
- 当需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时都要重新计算。
- 当需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许执行异步操作 ( 访问一个 API ),限制执行该操作的频率,并在得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
# 9. $nextTick 原理及作用
查看答案
Vue 的 nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JavaScript 方法来模拟对应的微/宏任务的实现,本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列。
nextTick 不仅是 Vue 内部的异步队列的调用方法,同时也允许开发者在实际项目中使用这个方法来满足实际应用中对 DOM 更新数据时机的后续逻辑处理。
nextTick 引入异步更新队列机制的原因∶
- 如果是同步更新,则多次对一个或多个属性赋值,会频繁触发 UI/DOM 的渲染,可以减少一些无用渲染
- 同时由于 VirtualDOM 的引入,每一次状态发生变化后,状态变化的信号会发送给组件,组件内部使用 VirtualDOM 进行计算得出需要更新的具体的 DOM 节点,然后对 DOM 进行更新操作,每次更新状态后的渲染过程需要更多的计算,而这种无用功也将浪费更多的性能,所以异步渲染变得更加至关重要。
Vue采用了数据驱动视图的思想,但是在一些情况下,仍然需要操作DOM。有时候,可能遇到这样的情况,DOM1的数据发生了变化,而DOM2需要从DOM1中获取数据,那这时就会发现DOM2的视图并没有更新,这时就需要用到了nextTick了。由于Vue的DOM操作是异步的,所以,在上面的情况中,就要将DOM2获取数据的操作写在$nextTick中。
所以,在以下情况下,会用到nextTick:
- 在数据变化后执行的某个操作,而这个操作需要使用随数据变化而变化的DOM结构的时候,这个操作就需要方法在nextTick()的回调函数中。
- 在vue生命周期中,如果在created()钩子进行DOM操作,也一定要放在nextTick()的回调函数中。因为在created()钩子函数中,页面的DOM还未渲染,这时候也没办法操作DOM,所以,此时如果想要操作DOM,必须将操作的代码放在nextTick()的回调函数中。