乐趣区

关于vue.js:腾讯前端常考vue面试题必备

虚构 DOM 的优劣如何?

长处:

  • 保障性能上限: 虚构 DOM 能够通过 diff 找出最小差别, 而后批量进行 patch, 这种操作尽管比不上手动优化, 然而比起粗犷的 DOM 操作性能要好很多, 因而虚构 DOM 能够保障性能上限
  • 无需手动操作 DOM: 虚构 DOM 的 diff 和 patch 都是在一次更新中主动进行的, 咱们无需手动操作 DOM, 极大进步开发效率
  • 跨平台: 虚构 DOM 实质上是 JavaScript 对象, 而 DOM 与平台强相干, 相比之下虚构 DOM 能够进行更不便地跨平台操作, 例如服务器渲染、挪动端开发等等

毛病:

  • 无奈进行极致优化: 在一些性能要求极高的利用中虚构 DOM 无奈进行针对性的极致优化, 比方 VScode 采纳间接手动操作 DOM 的形式进行极其的性能优化

如果让你从零开始写一个 vue 路由,说说你的思路

思路剖析:

首先思考 vue 路由要解决的问题:用户点击跳转链接内容切换,页面不刷新。

  • 借助 hash 或者 h istory api实现 url 跳转页面不刷新
  • 同时监听 hashchange 事件或者 popstate 事件处理跳转
  • 依据 hash 值或者 state 值从 routes 表中匹配对应 component 并渲染

答复范例:

一个 SPA 利用的路由须要解决的问题是 页面跳转内容扭转同时不刷新,同时路由还须要以插件模式存在,所以:

  1. 首先我会定义一个 createRouter 函数,返回路由器实例,实例外部做几件事
  2. 保留用户传入的配置项
  3. 监听 hash 或者 popstate 事件
  4. 回调里依据 path 匹配对应路由
  5. router 定义成一个 Vue 插件,即实现 install 办法,外部做两件事
  6. 实现两个全局组件:router-linkrouter-view,别离实现页面跳转和内容显示
  7. 定义两个全局变量:$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 种拦挡方:不限于 applyownKeysdeletePropertyhas 等等是 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 的区别

相同点: assetsstatic 两个都是寄存动态资源文件。我的项目中所须要的资源文件图片,字体图标,款式文件等都能够放在这两个文件下,这是相同点

不相同点: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 0
​
count.value++
// -> logs 1

watch侦测一个或多个响应式数据源并在数据源变动时调用一个回调函数

const state = reactive({count: 0})
watch(() => state.count,
  (count, prevCount) => {/* ... */}
)

答复范例

  1. watchEffect立刻运行一个函数,而后被动地追踪它的依赖,当这些依赖扭转时从新执行该函数。watch侦测一个或多个响应式数据源并在数据源变动时调用一个回调函数
  2. watchEffect(effect)是一种非凡 watch,传入的函数既是依赖收集的数据源,也是回调函数。如果咱们不关怀响应式数据变动前后的值,只是想拿这些数据做些事件,那么watchEffect 就是咱们须要的。watch更底层,能够接管多种数据源,包含用于依赖收集的 getter 函数,因而它齐全能够实现 watchEffect 的性能,同时因为能够指定 getter 函数,依赖能够管制的更准确,还能获取数据变动前后的值,因而如果须要这些时咱们会应用watch
  3. watchEffect在应用时,传入的函数会立即执行一次。watch默认状况下并不会执行回调函数,除非咱们手动设置 immediate 选项
  4. 从实现上来说,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. 数据流动单向,都反对服务器的渲染 SSR
4. 都有反对 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 中有助于一致性;
退出移动版