组件中data必须用函数返回一个对象?、
- data是一个函数时,每
复用一次组件
,就会返回一份新的data数据,每个组件实例都有自己的作用域
,每个实例相互独立,互不影响。 - 如果是对象形式,
object是引用数据类型,每个组件的data都是内存的同一个地址
,就会使用组件实例共用一份data数据
,一个数据改变,其他的也会改变。
Vue中key属性的作用
key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。
- 如果不
使用 key
,Vue 会使用一种最大限度减少动态元素
并且尽可能的尝试修复/再利用相同类型元素的算法。
使用 key
,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
key值的存在保证了唯一性,可以用于dom的重新渲染或是就地复用。
vue在执行时,会对节点进行检查,如果没有key值,那么,vue检查到这里有dom节点,则会对内容进行清空,并且赋予新值;如果有key值的存在,那么vue会对oldnode和newnode进行对比,发现两者key值是否相同,进行调换位置或是删除操作。
key值的作用是:
更精准-->在虚拟dom节点中赋予key值,会更加快速的拿到需要的目标节点,不会造成就地复用的情况,对于节点的把控更加精准。
使用key给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,为了高效的更新虚拟DOM。
vue中为啥不用index作为key?
- 最好的处理方式,使用插件shortid
-应该如何处理:
- 用组件唯一的ID(后端返回)作为它的key,没有情况下,可以在获取到列表的时候通过某种规则为他们创建一个key,并保证这个key在组件整个生命周期中都保持稳定
- 不用index作为key,因为不管数组的顺序怎么颠倒,index都是0,1,2这样的排列,导致vue会复用错误的旧子节点,做额外的工作
- 不用使用随机数作为key,不然旧节点会被全部删除,新节点重新创建。
computed和watch的区别和运用场景?
- computed:
计算属性,依赖其它属性值
,并且computed的值有缓存
,只有它依赖的属性值发生改变,下一次获取computed的值才会重新计算computed的值 - watch:更多的是[观察]的作用,
类似于某些数据的监听回调
,每当监听的数据变化时都会执行回调进行后续操作
computed运用场景:
当需要进行数值计算时,并且依赖其它数据时,应该用computed
,因为可以利用computed的缓存特性
,避免每次获取值时,都要重新计算。
- 数组的过滤器(对返回的数据进行处理)
- 计算总价格
watch运用场景
需要在数据变化
时执行异步
或开销较大的操作时,应该用watch
,使用watch选项允许我们执行异步操作。
- 监听路由的变化
- 监控自身属性的变化
- 搜索框
vue是如何对数组数据进行监听的
数组的方法(push/pop/shift/unshift/splice/sort/reverse)重写
- 获取原生Array的原型方法,
- 对Array的原型方法使用Object.defineProperty进行拦截
- 需要把拦截的Array类型的数据原型指向改造后的原型
为啥可以用$set检测数组变动
- 因为set函数中,如果target是一个数组且索引有效,就设置length的属性
- 通过splice方法把value设置到target数组指定位置
- 设置时,vue会拦截到target发生变化,会把新增的value变成响应式
- 最后返回value
nextTick与$nextTick的区别
nextTick(callback):当数据发生变化,更新后执行的回调。
在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM$nextTick(callback):当dom发生变化,更新后执行的回调。
将回调延迟到下次DOM更新循环之后执行。在修改数据之后立即使用,等待DOM更新。 区别:nextTick(callback)是全局方法
$nextTick(callback)是回调的this自动绑定到调用它的实例上。
keep-alive的理解
keep-alive是vue内置的一个组件
:它本身不会渲染一个DOM元素,也不会出现在父组件链中;使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
有以下特性:
一般结合路由和动态组件使用,用于缓存组件;
- 提供
include
和exclude
属性 - 对应两个钩子函数
activated
和deactivated
,当组件被激活时,触发钩子函数activated
,组件移除时,触发钩子函数deactivated
。 原理解析: - 在created中创建缓存列表和缓存组件的key列表
- destroyed销毁时会做一个循环销毁清空所有的缓存和key
- mounted会监控include和exclude属性,进行组件的缓存处理
- render渲染函数,会默认拿插槽,只缓存第一个组件,取出组件的名字,判断是否在缓存中,在就缓存,不在就return掉。
slot的理解
插槽
- 创建组件虚拟节点时,会将组件儿子虚拟节点保存起来。当初始化组件时,通过插槽属性将儿子进行分类
- 渲染组件时会拿对应的slot属性的节点进行替换操作(插槽的作用域为父组件) 作用域插槽
- 作用域插槽在解析的时候不会作为作为组件的孩子节点。会解析成函数,当子组件渲染时,会调用此函数进行渲染
- 普通插槽渲染的作用域是父组件,作用域插槽的渲染作用域是当前子组件
mixin
功能:抽离公共的业务逻辑
原理类似“对象的继承”
当组件初始化时会调用mergeOptions方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行合并
写过自定义指令么?原理是什么?
指令本质是装饰器,是vue对HTML元素的扩展,给Html元素增加自定义功能。
自定义指令有五个生命周期:
-
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
-
inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
-
update
:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
-
componentUpdated
:被绑定元素所在模板完成一次更新周期时调用。
-
unbind
:只调用一次,指令与元素解绑时调用。
created mounted请求数据的区别
- created:vue实例的数据对象data有了,el模版还没有创建
- mounted:vue实例挂在挂载已经完成
总结:
- 对于作为子组件被调用的组件里,异步请求应当在
mounted
里调用,因为这个时候子组件可能需要涉及到对dom的操作; - 对于页面级组件,当我们需要使用
ssr
(服务端渲染)的时候,只有created
是可用的,所以这个时候请求数据只能用它; - 对于页面级组件, 当我们做异步操作时,涉及到要访问dom的操作,我们仍旧只能使用
mounted
; - 对于一般情况,
created
和mounted
都是可以的;
vue3是如何处理vue2中的mixins
组件之间共享相同的属性时,可以将公共属性提取到一个单独的模块中,使用mixins
mixins的缺点
- 命名冲突 mixin在运行时合并两个对象,本地会覆盖mixin选项