虚构DOM的优劣如何?
长处:
- 保障性能上限: 虚构DOM能够通过diff找出最小差别,而后批量进行patch,这种操作尽管比不上手动优化,然而比起粗犷的DOM操作性能要好很多,因而虚构DOM能够保障性能上限
- 无需手动操作DOM: 虚构DOM的diff和patch都是在一次更新中主动进行的,咱们无需手动操作DOM,极大进步开发效率
- 跨平台: 虚构DOM实质上是JavaScript对象,而DOM与平台强相干,相比之下虚构DOM能够进行更不便地跨平台操作,例如服务器渲染、挪动端开发等等
毛病:
- 无奈进行极致优化: 在一些性能要求极高的利用中虚构DOM无奈进行针对性的极致优化,比方VScode采纳间接手动操作DOM的形式进行极其的性能优化
如果让你从零开始写一个vue路由,说说你的思路
思路剖析:
首先思考vue
路由要解决的问题:用户点击跳转链接内容切换,页面不刷新。
- 借助
hash
或者history api
实现url
跳转页面不刷新 - 同时监听
hashchange
事件或者popstate
事件处理跳转 - 依据
hash
值或者state
值从routes
表中匹配对应component
并渲染
答复范例:
一个SPA
利用的路由须要解决的问题是 页面跳转内容扭转同时不刷新 ,同时路由还须要以插件模式存在,所以:
- 首先我会定义一个
createRouter
函数,返回路由器实例,实例外部做几件事 - 保留用户传入的配置项
- 监听
hash
或者popstate
事件 - 回调里依据
path
匹配对应路由 - 将
router
定义成一个Vue
插件,即实现install
办法,外部做两件事 - 实现两个全局组件:
router-link
和router-view
,别离实现页面跳转和内容显示 - 定义两个全局变量:
$route
和$router
,组件内能够拜访以后路由和路由器实例
你有对 Vue 我的项目进行哪些优化?
(1)代码层面的优化
- v-if 和 v-show 辨别应用场景
- computed 和 watch 辨别应用场景
- v-for 遍历必须为 item 增加 key,且防止同时应用 v-if
- 长列表性能优化
- 事件的销毁
- 图片资源懒加载
- 路由懒加载
- 第三方插件的按需引入
- 优化有限列表性能
- 服务端渲染 SSR or 预渲染
(2)Webpack 层面的优化
- Webpack 对图片进行压缩
- 缩小 ES6 转为 ES5 的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的 CSS
- 优化 SourceMap
- 构建后果输入剖析
- Vue 我的项目的编译优化
(3)根底的 Web 技术的优化
- 开启 gzip 压缩
- 浏览器缓存
- CDN 的应用
- 应用 Chrome Performance 查找性能瓶颈
写过自定义指令吗 原理是什么
指令实质上是装璜器,是 vue 对 HTML 元素的扩大,给 HTML 元素减少自定义性能。vue 编译 DOM 时,会找到指令对象,执行指令的相干办法。
自定义指令有五个生命周期(也叫钩子函数),别离是 bind、inserted、update、componentUpdated、unbind
1. bind:只调用一次,指令第一次绑定到元素时调用。在这里能够进行一次性的初始化设置。2. inserted:被绑定元素插入父节点时调用 (仅保障父节点存在,但不肯定已被插入文档中)。3. update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变动。通过比拟更新前后的绑定值,能够疏忽不必要的模板更新。4. componentUpdated:被绑定元素所在模板实现一次更新周期时调用。5. unbind:只调用一次,指令与元素解绑时调用。
原理
1.在生成 ast 语法树时,遇到指令会给以后元素增加 directives 属性
2.通过 genDirectives 生成指令代码
3.在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子
4.当执行指令对应钩子函数时,调用对应指令定义的办法
created和mounted的区别
- created:在模板渲染成html前调用,即通常初始化某些属性值,而后再渲染成视图。
- mounted:在模板渲染成html后调用,通常是初始化页面实现后,再对html的dom节点进行一些须要的操作。
说说你对 proxy 的了解,Proxy 相比于 defineProperty 的劣势
Object.defineProperty()
的问题次要有三个:
- 不能监听数组的变动 :无奈监控到数组下标的变动,导致通过数组下标增加元素,不能实时响应
- 必须遍历对象的每个属性 :只能劫持对象的属性,从而须要对每个对象,每个属性进行遍历,如果属性值是对象,还须要深度遍历。
Proxy
能够劫持整个对象,并返回一个新的对象 - 必须深层遍历嵌套的对象
Proxy的劣势如下:
- 针对对象: 针对整个对象,而不是对象的某个属性 ,所以也就不须要对
keys
进行遍历 - 反对数组:
Proxy
不须要对数组的办法进行重载,省去了泛滥 hack,缩小代码量等于缩小了保护老本,而且规范的就是最好的 Proxy
的第二个参数能够有13
种拦挡方:不限于apply
、ownKeys
、deleteProperty
、has
等等是Object.defineProperty
不具备的Proxy
返回的是一个新对象,咱们能够只操作新的对象达到目标,而Object.defineProperty
只能遍历对象属性间接批改Proxy
作为新规范将受到浏览器厂商重点继续的性能优化,也就是传说中的新规范的性能红利
proxy具体应用点击查看(opens new window)
Object.defineProperty的劣势如下:
兼容性好,反对IE9
,而Proxy
的存在浏览器兼容性问题,而且无奈用polyfill
磨平
defineProperty的属性值有哪些
Object.defineProperty(obj, prop, descriptor)// obj 要定义属性的对象// prop 要定义或批改的属性的名称// descriptor 要定义或批改的属性描述符Object.defineProperty(obj,"name",{ value:"poetry", // 初始值 writable:true, // 该属性是否可写入 enumerable:true, // 该属性是否可被遍历失去(for...in, Object.keys等) configurable:true, // 定该属性是否可被删除,且除writable外的其余描述符是否可被批改 get: function() {}, set: function(newVal) {}})
相干代码如下
import { mutableHandlers } from "./baseHandlers"; // 代理相干逻辑import { isObject } from "./util"; // 工具办法export function reactive(target) { // 依据不同参数创立不同响应式对象 return createReactiveObject(target, mutableHandlers);}function createReactiveObject(target, baseHandler) { if (!isObject(target)) { return target; } const observed = new Proxy(target, baseHandler); return observed;}const get = createGetter();const set = createSetter();function createGetter() { return function get(target, key, receiver) { // 对获取的值进行喷射 const res = Reflect.get(target, key, receiver); console.log("属性获取", key); if (isObject(res)) { // 如果获取的值是对象类型,则返回以后对象的代理对象 return reactive(res); } return res; };}function createSetter() { return function set(target, key, value, receiver) { const oldValue = target[key]; const hadKey = hasOwn(target, key); const result = Reflect.set(target, key, value, receiver); if (!hadKey) { console.log("属性新增", key, value); } else if (hasChanged(value, oldValue)) { console.log("属性值被批改", key, value); } return result; };}export const mutableHandlers = { get, // 当获取属性时调用此办法 set, // 当批改属性时调用此办法};
Proxy
只会代理对象的第一层,那么Vue3
又是怎么解决这个问题的呢?
判断以后Reflect.get的
返回值是否为Object
,如果是则再通过reactive
办法做代理, 这样就实现了深度观测。
监测数组的时候可能触发屡次get/set,那么如何避免触发屡次呢?
咱们能够判断key
是否为以后被代理对象target
本身属性,也能够判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger
参考 前端进阶面试题具体解答
简述 mixin、extends 的笼罩逻辑
(1)mixin 和 extends mixin 和 extends均是用于合并、拓展组件的,两者均通过 mergeOptions 办法实现合并。
- mixins 接管一个混入对象的数组,其中混入对象能够像失常的实例对象一样蕴含实例选项,这些选项会被合并到最终的选项中。Mixin 钩子依照传入程序顺次调用,并在调用组件本身的钩子之前被调用。
extends 次要是为了便于扩大单文件组件,接管一个对象或构造函数。
(2)mergeOptions 的执行过程
- 规范化选项(normalizeProps、normalizelnject、normalizeDirectives)
- 对未合并的选项,进行判断
if (!child._base) { if (child.extends) { parent = mergeOptions(parent, child.extends, vm); } if (child.mixins) { for (let i = 0, l = child.mixins.length; i < l; i++) { parent = mergeOptions(parent, child.mixins[i], vm); } }}
- 合并解决。依据一个通用 Vue 实例所蕴含的选项进行分类逐个判断合并,如 props、data、 methods、watch、computed、生命周期等,将合并后果存储在新定义的 options 对象里。
- 返回合并后果 options。
MVC 和 MVVM 区别
MVC
MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计榜样
- Model(模型):是应用程序中用于解决应用程序数据逻辑的局部。通常模型对象负责在数据库中存取数据
- View(视图):是应用程序中解决数据显示的局部。通常视图是根据模型数据创立的
- Controller(控制器):是应用程序中解决用户交互的局部。通常控制器负责从视图读取数据,管制用户输出,并向模型发送数据
MVC 的思维:一句话形容就是 Controller 负责将 Model 的数据用 View 显示进去,换句话说就是在 Controller 外面把 Model 的数据赋值给 View。
MVVM
MVVM 新增了 VM 类
- ViewModel 层:做了两件事达到了数据的双向绑定 一是将【模型】转化成【视图】,行将后端传递的数据转化成所看到的页面。实现的形式是:数据绑定。二是将【视图】转化成【模型】,行将所看到的页面转化成后端的数据。实现的形式是:DOM 事件监听。
MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的主动同步,也就是当 Model 的属性扭转时,咱们不必再本人手动操作 Dom 元素,来扭转 View 的显示,而是扭转属性后该属性对应 View 层显示会主动扭转(对应Vue数据驱动的思维)
整体看来,MVVM 比 MVC 精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不必再用选择器操作 DOM 元素。因为在 MVVM 中,View 不晓得 Model 的存在,Model 和 ViewModel 也察看不到 View,这种低耦合模式进步代码的可重用性
留神:Vue 并没有齐全遵循 MVVM 的思维 这一点官网本人也有阐明
那么问题来了 为什么官网要说 Vue 没有齐全遵循 MVVM 思维呢?
- 严格的 MVVM 要求 View 不能和 Model 间接通信,而 Vue 提供了$refs 这个属性,让 Model 能够间接操作 View,违反了这一规定,所以说 Vue 没有齐全遵循 MVVM。
Vue 中 computed 和 watch 有什么区别?
计算属性 computed:
(1)**反对缓存**,只有依赖数据发生变化时,才会从新进行计算函数; (2)计算属性内**不反对异步操作**; (3)计算属性的函数中**都有一个 get**(默认具备,获取计算属性)**和 set**(手动增加,设置计算属性)办法; (4)计算属性是主动监听依赖值的变动,从而动静返回内容。
侦听属性 watch:
(1)**不反对缓存**,只有数据发生变化,就会执行侦听函数; (2)侦听属性内**反对异步操作**; (3)侦听属性的值**能够是一个对象,接管 handler 回调,deep,immediate 三个属性**; (3)监听是一个过程,在监听的值变动时,能够触发一个回调,并**做一些其余事件**。
assets和static的区别
相同点: assets
和 static
两个都是寄存动态资源文件。我的项目中所须要的资源文件图片,字体图标,款式文件等都能够放在这两个文件下,这是相同点
不相同点:assets
中寄存的动态资源文件在我的项目打包时,也就是运行 npm run build
时会将 assets
中搁置的动态资源文件进行打包上传,所谓打包简略点能够了解为压缩体积,代码格式化。而压缩后的动态资源文件最终也都会搁置在 static
文件中跟着 index.html
一起上传至服务器。static
中搁置的动态资源文件就不会要走打包压缩格式化等流程,而是间接进入打包好的目录,间接上传至服务器。因为防止了压缩间接进行上传,在打包时会进步肯定的效率,然而 static
中的资源文件因为没有进行压缩等操作,所以文件的体积也就绝对于 assets
中打包后的文件提交较大点。在服务器中就会占据更大的空间。
倡议: 将我的项目中 template
须要的款式文件js文件等都能够搁置在 assets
中,走打包这一流程。缩小体积。而我的项目中引入的第三方的资源文件如iconfoont.css
等文件能够搁置在 static
中,因为这些引入的第三方文件曾经通过解决,不再须要解决,间接上传。
用VNode来形容一个DOM构造
虚构节点就是用一个对象来形容一个实在的DOM元素。首先将 template
(实在DOM)先转成 ast
, ast
树通过 codegen
生成 render
函数, render
函数里的 _c
办法将它转为虚构dom
Vue的性能优化有哪些
(1)编码阶段
- 尽量减少data中的数据,data中的数据都会减少getter和setter,会收集对应的watcher
- v-if和v-for不能连用
- 如果须要应用v-for给每项元素绑定事件时应用事件代理
- SPA 页面采纳keep-alive缓存组件
- 在更多的状况下,应用v-if代替v-show
- key保障惟一
- 应用路由懒加载、异步组件
- 防抖、节流
- 第三方模块按需导入
- 长列表滚动到可视区域动静加载
- 图片懒加载
(2)SEO优化
- 预渲染
- 服务端渲染SSR
(3)打包优化
- 压缩代码
- Tree Shaking/Scope Hoisting
- 应用cdn加载第三方模块
- 多线程打包happypack
- splitChunks抽离公共文件
- sourceMap优化
(4)用户体验
- 骨架屏
- PWA
- 还能够应用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
Vue.extend 作用和原理
官网解释:Vue.extend 应用根底 Vue 结构器,创立一个“子类”。参数是一个蕴含组件选项的对象。
其实就是一个子类结构器 是 Vue 组件的外围 api 实现思路就是应用原型继承的办法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并
相干代码如下
export default function initExtend(Vue) { let cid = 0; //组件的惟一标识 // 创立子类继承Vue父类 便于属性扩大 Vue.extend = function (extendOptions) { // 创立子类的构造函数 并且调用初始化办法 const Sub = function VueComponent(options) { this._init(options); //调用Vue初始化办法 }; Sub.cid = cid++; Sub.prototype = Object.create(this.prototype); // 子类原型指向父类 Sub.prototype.constructor = Sub; //constructor指向本人 Sub.options = mergeOptions(this.options, extendOptions); //合并本人的options和父类的options return Sub; };}
常见的事件修饰符及其作用
.stop
:等同于 JavaScript 中的event.stopPropagation()
,避免事件冒泡;.prevent
:等同于 JavaScript 中的event.preventDefault()
,避免执行预设的行为(如果事件可勾销,则勾销该事件,而不进行事件的进一步流传);.capture
:与事件冒泡的方向相同,事件捕捉由外到内;.self
:只会触发本人范畴内的事件,不蕴含子元素;.once
:只会触发一次。
Vue.js的template编译
简而言之,就是先转化成AST树,再失去的render函数返回VNode(Vue的虚构DOM节点),具体步骤如下:
首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的形象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创立编译器的。另外compile还负责合并option。
而后,AST会通过generate(将AST语法树转化成render funtion字符串的过程)失去render函数,render的返回值是VNode,VNode是Vue的虚构DOM节点,外面有(标签名、子节点、文本等等)
vue3中 watch、watchEffect区别
watch
是惰性执行,也就是只有监听的值发生变化的时候才会执行,然而watchEffect
不同,每次代码加载watchEffect
都会执行(疏忽watch
第三个参数的配置,如果批改配置项也能够实现立刻执行)watch
须要传递监听的对象,watchEffect
不须要watch
只能监听响应式数据:ref
定义的属性和reactive
定义的对象,如果间接监听reactive
定义对象中的属性是不容许的(会报正告),除非应用函数转换一下。其实就是官网上说的监听一个getter
watchEffect
如果监听reactive
定义的对象是不起作用的,只能监听对象中的属性
看一下watchEffect
的代码
<template><div> 请输出firstName: <input type="text" v-model="firstName"></div><div> 请输出lastName: <input type="text" v-model="lastName"></div><div> 请输出obj.text: <input type="text" v-model="obj.text"></div> <div> 【obj.text】 {{obj.text}} </div></template><script>import {ref, reactive, watch, watchEffect} from 'vue'export default { name: "HelloWorld", props: { msg: String, }, setup(props,content){ let firstName = ref('') let lastName = ref('') let obj= reactive({ text:'hello' }) watchEffect(()=>{ console.log('触发了watchEffect'); console.log(`组合后的名称为:${firstName.value}${lastName.value}`) }) return{ obj, firstName, lastName } }};</script>
革新一下代码
watchEffect(()=>{ console.log('触发了watchEffect'); // 这里咱们不应用firstName.value/lastName.value ,相当于是监控整个ref,对应第四点下面的论断 console.log(`组合后的名称为:${firstName}${lastName}`)})
watchEffect(()=>{ console.log('触发了watchEffect'); console.log(obj);})
略微革新一下
let obj = reactive({ text:'hello'})watchEffect(()=>{ console.log('触发了watchEffect'); console.log(obj.text);})
再看一下watch的代码,验证一下
let obj= reactive({ text:'hello'})// watch是惰性执行, 默认初始化之后不会执行,只有值有变动才会触发,可通过配置参数实现默认执行watch(obj, (newValue, oldValue) => { // 回调函数 console.log('触发监控更新了new', newValue); console.log('触发监控更新了old', oldValue);},{ // 配置immediate参数,立刻执行,以及深层次监听 immediate: true, deep: true})
- 监控整个
reactive
对象,从下面的图能够看到deep
理论默认是开启的,就算咱们设置为false
也还是有效。而且旧值获取不到。 - 要获取旧值则须要监控对象的属性,也就是监听一个
getter
,看下图
总结
- 如果定义了
reactive
的数据,想去应用watch
监听数据扭转,则无奈正确获取旧值,并且deep
属性配置有效,主动强制开启了深层次监听。 - 如果应用
ref
初始化一个对象或者数组类型的数据,会被主动转成reactive
的实现形式,生成proxy
代理对象。也会变得无奈正确取旧值。 - 用任何形式生成的数据,如果接管的变量是一个
proxy
代理对象,就都会导致watch
这个对象时,watch
回调里无奈正确获取旧值。 - 所以当大家应用
watch
监听对象时,如果在不须要应用旧值的状况,能够失常监听对象没关系;然而如果当监听扭转函数外面须要用到旧值时,只能监听 对象.xxx`属性 的形式才行
watch和watchEffect异同总结
体验
watchEffect
立刻运行一个函数,而后被动地追踪它的依赖,当这些依赖扭转时从新执行该函数
const count = ref(0)watchEffect(() => console.log(count.value))// -> logs 0count.value++// -> logs 1
watch
侦测一个或多个响应式数据源并在数据源变动时调用一个回调函数
const state = reactive({ count: 0 })watch( () => state.count, (count, prevCount) => { /* ... */ })
答复范例
watchEffect
立刻运行一个函数,而后被动地追踪它的依赖,当这些依赖扭转时从新执行该函数。watch
侦测一个或多个响应式数据源并在数据源变动时调用一个回调函数watchEffect(effect)
是一种非凡watch
,传入的函数既是依赖收集的数据源,也是回调函数。如果咱们不关怀响应式数据变动前后的值,只是想拿这些数据做些事件,那么watchEffect
就是咱们须要的。watch
更底层,能够接管多种数据源,包含用于依赖收集的getter
函数,因而它齐全能够实现watchEffect
的性能,同时因为能够指定getter
函数,依赖能够管制的更准确,还能获取数据变动前后的值,因而如果须要这些时咱们会应用watch
watchEffect
在应用时,传入的函数会立即执行一次。watch
默认状况下并不会执行回调函数,除非咱们手动设置immediate
选项- 从实现上来说,
watchEffect(fn)
相当于watch(fn,fn,{immediate:true})
watchEffect
定义如下
export function watchEffect( effect: WatchEffect, options?: WatchOptionsBase): WatchStopHandle { return doWatch(effect, null, options)}
watch
定义如下
export function watch<T = any, Immediate extends Readonly<boolean> = false>( source: T | WatchSource<T>, cb: any, options?: WatchOptions<Immediate>): WatchStopHandle { return doWatch(source as any, cb, options)}
很显著watchEffect
就是一种非凡的watch
实现。
Vue中的key到底有什么用?
key
是为Vue中的vnode标记的惟一id,通过这个key,咱们的diff操作能够更精确、更疾速
diff算法的过程中,先会进行新旧节点的首尾穿插比照,当无奈匹配的时候会用新节点的key
与旧节点进行比对,而后超出差别.
diff程能够概括为:oldCh和newCh各有两个头尾的变量StartIdx和EndIdx,它们的2个变量互相比拟,一共有4种比拟形式。如果4种比拟都没匹配,如果设置了key,就会用key进行比拟,在比拟的过程中,变量会往两头靠,一旦StartIdx>EndIdx表明oldCh和newCh至多有一个曾经遍历完了,就会完结比拟,这四种比拟形式就是首、尾、旧尾新头、旧头新尾.
- 精确: 如果不加
key
,那么vue会抉择复用节点(Vue的就地更新策略),导致之前节点的状态被保留下来,会产生一系列的bug. - 疾速: key的唯一性能够被Map数据结构充分利用,相比于遍历查找的工夫复杂度O(n),Map的工夫复杂度仅仅为O(1).
Vue data 中某一个属性的值产生扭转后,视图会立刻同步执行从新渲染吗?
不会立刻同步执行从新渲染。Vue 实现响应式并不是数据发生变化之后 DOM 立刻变动,而是按肯定的策略进行 DOM 的更新。Vue 在更新 DOM 时是异步执行的。只有侦听到数据变动, Vue 将开启一个队列,并缓冲在同一事件循环中产生的所有数据变更。
如果同一个watcher被屡次触发,只会被推入到队列中一次。这种在缓冲时去除反复数据对于防止不必要的计算和 DOM 操作是十分重要的。而后,在下一个的事件循环tick中,Vue 刷新队列并执行理论(已去重的)工作。
vue和react的区别
=> 相同点:
1. 数据驱动页面,提供响应式的试图组件2. 都有virtual DOM,组件化的开发,通过props参数进行父子之间组件传递数据,都实现了webComponents标准3. 数据流动单向,都反对服务器的渲染SSR4. 都有反对native的办法,react有React native, vue有wexx
=> 不同点:
1.数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的 2.数据渲染:大规模的数据渲染,react更快 3.应用场景:React配合Redux架构适宜大规模多人合作简单我的项目,Vue适宜小快的我的项目 4.开发格调:react举荐做法jsx + inline style把html和css都写在js了 vue是采纳webpack + vue-loader单文件组件格局,html, js, css同一个文件
Vue 的生命周期办法有哪些 个别在哪一步发申请
beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在以后阶段 data、methods、computed 以及 watch 上的数据和办法都不能被拜访
created 实例曾经创立实现之后被调用。在这一步,实例已实现以下的配置:数据观测(data observer),属性和办法的运算, watch/event 事件回调。这里没有$el,如果非要想与 Dom 进行交互,能够通过 vm.$nextTick 来拜访 Dom
beforeMount 在挂载开始之前被调用:相干的 render 函数首次被调用。
mounted 在挂载实现后产生,在以后阶段,实在的 Dom 挂载结束,数据实现双向绑定,能够拜访到 Dom 节点
beforeUpdate 数据更新时调用,产生在虚构 DOM 从新渲染和打补丁(patch)之前。能够在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程
updated 产生在更新实现之后,以后阶段组件 Dom 已实现更新。要留神的是防止在此期间更改数据,因为这可能会导致有限循环的更新,该钩子在服务器端渲染期间不被调用。
beforeDestroy 实例销毁之前调用。在这一步,实例依然齐全可用。咱们能够在这时进行善后收尾工作,比方革除计时器。
destroyed Vue 实例销毁后调用。调用后,Vue 实例批示的所有货色都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
activated keep-alive 专属,组件被激活时调用
deactivated keep-alive 专属,组件被销毁时调用
异步申请在哪一步发动?
能够在钩子函数 created、beforeMount、mounted 中进行异步申请,因为在这三个钩子函数中,data 曾经创立,能够将服务端端返回的数据进行赋值。
如果异步申请不须要依赖 Dom 举荐在 created 钩子函数中调用异步申请,因为在 created 钩子函数中调用异步申请有以下长处:
- 能更快获取到服务端数据,缩小页面 loading 工夫;
- ssr 不反对 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;