key的作用主要是为了高效的更新虚拟dom。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换内部属性而不会触发过渡效果。
接口请求可以放在钩子函数created,beforeMount,mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。
但推荐在created钩子函数中调用异步请求,因为在created钩子函数中调用异步请求有以下几个优点
- 能够更快获取到服务器端数据,减少页面loading时间
- SSR不支持beforeMount,mounted钩子函数,所以放在created中有助于代码一致性
- created是在模板渲染成html调用,即通常初始化某些元素属性值,然后再渲染成视图。如果在mounted钩子函数中请求数据可能导致页面闪屏问题
首先从表现形式上面来看,computed和methods的区别大致有下面4点:
如果从底层来看的话,computed和methods在底层实现上面还有很大的区别。
vue对于methods的处理比较简单,只需要遍历methods配置中的每一个属性,将其对于的函数使用bind绑定当前组价实例后复制其引用到组件实例中即可
作用:vue更新DOM是异步更新的,数据变化,DOM的更新不会马上完成,nextTick的回调是在下次DOM更新循环结束之后执行的延迟回调。
实现原理:nextTick主要使用了宏任务和微任务。根据执行环境分别尝试采用
组件中的data写成一个函数,数据以函数返回值形式定义。这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用一份data,就会造成一个变了会导致全变的结果
Vue3.x改用了Proxy来替代Object.defineProperty
原因在于Object.defineProperty本身存在一些问题:
而相比于Object.defineProperty,Proxy的优点在于:
区别如下:
watch的参数:
computed的缓存原理:
computed本质是一个惰性的观察者,当计算数据存在于data或者是props里时挥别警告;
首先说一下什么场景下需要scoped样式穿透
在很多项目中,会出现这么一种情况,即:引用了第三方组件,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成的组件之间的样式污染。此时只能通过特殊的方式,穿透scoped。
有三种方式来实现样式穿透:
方法一:
使用::v-deep操作符(>>>的别名)
如果希望scoped样式中一个选择器能够作用更深,例如影响子组件,可以使用>>>操作符;
<style scoped>
.a >>> .b { /* ... */ }
</style>
上述代码将会编译成:
.a[data-v-f3f3eg9] .b { /* ... */ }
后面的类名没有data属性,所以能选到子组件里面的类名。
方法二:
定义一个含有scoped属性的style标签之外,在定义一个不含scoped属性的style标签,即在一个vue组件定义一个全局的style标签,一个含有作用域的style标签。
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
此时,我们只需要将修改的第三方样式的css写到第一个style标签里面即可、
第三个方法:
上面的方法一需要单独书写一个不含有 scoped 属性的 style 标签,可能会造成全局样式的污染。
更推荐的方式是在组件的外层 DOM 上添加唯一的 class 来区分不同组件,在书写样式时就可以正常针对针对这部分 DOM 书写样式。
简单说,Vue的编译过程就是将template转化为render函数的过程。会经历以下阶段:
首先解析模板,生成AST语法树(一种用JavaScript对象的形式来描述整个模板)。
使用大量的正则表达式对模板进行解析,遇到标签,文本的时候都会执行对于的钩子进行相关处理。
Vue的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有些数据首次渲染后就不会再变化。那么优化过程就是深度遍历AST树,按照相关条件对树节点进行标记。这些被标记的节点(静态节点)我们就可以跳过对他们的对比,对运行时的模板起到很大的优化作用。
编译的最后一步是将优化后的AST树转换为可执行的代码。
这是因为vue的Dom更新是一个异步操作,在数据更新后会首先被set钩子函数监听到,但是不会马上执行DOM更新,而是在下一轮循环中执行更新。
具体实现是vue中实现了一个queue队列用于存放本次事件循环中的所有watcher更新,并且同一个watcher的更新只会被推入队列一次,并在本轮事件循环的微任务执行结束后执行此更新,这就是DOM只会更新一次的原因。
这种在缓冲时去除重复数据对于避免不必要的计算和dom操作是非常重要的。然后,在下一个的事件循环“tick”中,vue刷新队列并执行实际工作。vue在内部对异步队列尝试使用原生Promise.then,MutationObserve和setImmediate,如果执行环境不支持,则会采用setTimeout(fn,0)代替