乐趣区

关于前端:问的多查的多的vue面试题整理不容错过快看有没有你被问到的题目

生命周期钩子函数

Vue 实例有一个残缺的生命周期,也就是从开始创立、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,咱们称这是 Vue 的生命周期

  • Vue 中组件生命周期调用程序
生命周期 形容
beforeCreate 组件实例被创立之初,组件的属性失效之前
created 组件实例曾经齐全创立,属性也绑定,但实在 dom 还没有生成,$el 还不可用
beforeMount 在挂载开始之前被调用:相干的 render 函数首次被调用
mounted el 被新创建的 vm.$el 替换,并挂载到实例下来之后调用该钩子
beforeUpdate 组件数据更新之前调用,产生在虚构 DOM 打补丁之前
update 组件数据更新之后
activited keep-alive 专属,组件被激活时调用
deadctivated keep-alive 专属,组件被销毁时调用
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用

虚构 dom

  • 因为 dom 操作耗时非常长,且 dom 对象的体积很大,单个 div 的 dom 属性就有 294 个之多;
  • Virtual DOM 就是用一个原生的 JS 对象去形容一个 DOM 节点,所以它比创立一个 DOM 的代价要小很多。
  • VNode 是对实在 DOM 的一种形象形容,它的外围定义无非就几个要害属性,标签名、数据、子节点、键值等,其它属性都是用来扩大 VNode 的灵活性以及实现一些非凡 feature 的。因为 VNode 只是用来映射到实在 DOM 的渲染,不须要蕴含操作 DOM 的办法,因而它是十分轻量和简略的。
  • Virtual DOM 到实在的 dom 须要通过以下过程:VNode 的 create、diff、patch

v-model 双向数据绑定原理

vue 双向数据绑定是通过 数据劫持 联合 公布订阅模式 的形式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变动,视图变动,数据也随之产生扭转;外围:Object.defineProperty() 办法。

v-model实质上是语法糖,v-model 在外部为不同的输出元素应用不同的属性并抛出不同的事件

  • text 和 textarea 元素应用 value 属性和 input 事件
  • checkbox 和 radio 应用 checked 属性和 change 事件
  • select 字段将 value 作为 prop 并将 change 作为事件
<input v-model="sth" /><!-- 二者等价 -->
<input :value="sth" @input="sth = $event.target.value" />
复制代码

computed 和 watch 区别

vue 插槽

设置在自组件外部的 插槽 像一个盒子,地位由子组件决定,放什么内容由父组件决定。

实现了内容散发,进步了组件自定义的水平,让组件变的更加灵便

  1. 默认插槽:

无需 name 属性,取子组件肚子里第一个元素节点作为默认插槽。

<!-- 子组件,组件名:child-component -->
<div class="child-page">
    <h1> 子页面 </h1>
    <slot></slot> <!-- 替换为 <p>hello,world!</p> -->
</div>

<!-- 父组件 -->
<div class="parent-page">
    <child-component>
        <p>hello,world!</p>
    </child-component>
</div>

<!-- 渲染后果 -->
<div class="parent-page">
    <div class="child-page">
        <h1> 子页面 </h1>
        <p>hello,world!</p>
    </div>
</div>
复制代码
  1. 具名插槽:

在多个插槽的状况下应用,利用 name 标识插槽。

<!-- 子组件,组件名:child-component -->
<div class="child-page">
    <h1> 子页面 </h1>
    <slot name="header"></slot>
    <slot></slot>  <!-- 等价于 <slot name="default"></slot> -->
    <slot name="footer"></slot>
</div>

<!-- 父组件 -->
<div class="parent-page">
    <child-component>
        <template v-slot:header>
          <p> 头部 </p>  
        </template>
        <template v-slot:footer>
          <p> 脚部 </p>
        </template>
        <p> 身材 </p>
    </child-component>
</div>

<!-- 渲染后果 -->
<div class="parent-page">
    <div class="child-page">
        <h1> 子页面 </h1>
        <p> 头部 </p>
        <p> 身材 </p>
        <p> 脚部 </p>
    </div>
</div>
复制代码
  1. 作用域插槽:

子组件给父组件传递数据。

<!-- 子组件,组件名:child-component -->
<div class="child-page">
    <h1> 子页面 </h1>
    <slot name="header" data="data from child-component."></slot>
</div>

<!-- 父组件 -->
<div class="parent-page">
    <child-component>
        <template v-slot:header="slotProps">
          <p> 头部: {{slotProps.data}}</p>
        </template>
    </child-component>
</div>

<!-- 渲染后果 -->
<div class="parent-page">
    <div class="child-page">
        <h1> 子页面 </h1>
        <p> 头部: data from child-component.</p>
    </div>
</div>
复制代码

Vue 与 Angular 以及 React 的区别?

Vue 与 AngularJS 的区别

  • Angular 采纳 TypeScript 开发, 而 Vue 能够应用 javascript 也能够应用 TypeScript
  • AngularJS 依赖对数据做脏查看,所以 Watcher 越多越慢;Vue.js 应用基于 依赖追踪 的察看并且应用 异步队列 更新,所有的数据都是独立触发的。
  • AngularJS社区欠缺 , Vue 的 学习老本较小

Vue 与 React 的区别

  • vue 组件分为全局注册和部分注册,在 react 中都是通过 import 相应组件,而后模版中援用;
  • props是能够动态变化的,子组件也实时更新,在 react 中官网倡议 props 要像纯函数那样,输入输出统一对应,而且不太倡议通过 props 来更改视图;
  • 子组件个别要显示地调用 props 选项来申明它期待取得的数据。而在 react 中不必须,另两者都有 props 校验机制;
  • 每个 Vue 实例都实现了事件接口,不便父子组件通信,小型我的项目中不须要引入状态管理机制,而 react 必须本人实现;
  • vue 应用 插槽 散发内容,使得能够混合父组件的内容与子组件本人的模板;
  • vue 多了 指令系统,让模版能够实现更丰盛的性能,而 React 只能应用 JSX 语法;
  • Vue 减少的语法糖 computedwatch,而在 React 中须要本人写一套逻辑来实现;
  • react 的思路是all in js,通过 js 来生成 html,所以设计了 jsx,还有通过 js 来操作 css,社区的 styled-component、jss 等;而 vue 是把 html,css,js 组合到一起,用各自的解决形式,vue 有单文件组件,能够把 html、css、js 写到一个文件中,html 提供了模板引擎来解决。
  • react 做的事件很少,很多都交给 社区 去做,vue 很多货色都是 内置 的,写起来的确不便一些,比方 reduxcombineReducer 就对应 vuexmodules,比方 reselect 就对应 vuex 的 getter 和 vue 组件的 computed,vuex 的 mutation 是间接扭转的原始数据,而 redux 的 reducer 是返回一个全新的 state,所以 redux 联合 immutable 来优化性能,vue 不须要。
  • react 是整体的思路的就是函数式,所以推崇 纯组件 ,数据不可变, 单向数据流,当然须要双向的中央也能够做到,比方联合redux-form,组件的横向拆分个别是通过高阶组件。而 vue 是数据可变的,双向绑定,申明式的写法,vue 组件的横向拆分很多状况下用mixin

$route$router 的区别

  • $route 是 路由信息对象,包含 path,params,hash,query,fullPath,matched,name 等路由信息参数。
  • 而 $router 是 路由实例 对象包含了路由的跳转办法,钩子函数等。

Vue 的 SPA 如何优化加载速度

  • 缩小入口文件体积
  • 动态资源本地缓存
  • 开启 Gzip 压缩
  • 应用 SSR,nuxt.js

vue 我的项目中的优化

编码阶段

  • 不要在模板外面写过多表达式
  • 尽量减少 data 中的数据,data中的数据都会减少 gettersetter,会收集对应的watcher
  • v-ifv-for 不能连用
  • 如果须要应用 v-for 给每项元素绑定事件时应用事件代理
  • SPA 页面采纳 keep-alive 缓存组件
  • 频繁切换的应用 v -show,不频繁切换的应用 v -if
  • 循环调用子组件时增加 key,key保障惟一
  • 应用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动静加载
  • 图片懒加载

SEO 优化

  • 预渲染
  • 服务端渲染SSRnuxt.js

打包优化

  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • 应用 cdn 加载第三方模块
  • 多线程打包happypack
  • splitChunks抽离公共文件
  • sourceMap优化

用户体验

  • 骨架屏
  • PWA渐进式 Web 利用,应用多种技术来加强 web app 的性能,让网页利用出现和原生利用类似的体验。

还能够应用缓存 (客户端缓存、服务端缓存) 优化、服务端开启 gzip 压缩等。

vue 有了数据响应式,为何还要 diff?

外围起因:粒度

  • React通过 setState 晓得有变动了,但不晓得哪里变动了,所以须要通过 diff 找出变动的中央并更新 dom。
  • Vue曾经能够通过响应式零碎晓得哪里产生了变动,然而所有变动都通过响应式会创立大量 Watcher,极其耗费性能,因而 vue 采纳的形式是通过响应式零碎晓得哪个组件产生了变动,而后在组件外部应用diff。这样的 中粒度 策略,即不会产生大量的 Watcher,也使 diff 的节点缩小了,两全其美。

vue 模版编译

编译的外围是把 template 模板编译成 render 函数,次要分为如下三个步骤:

  • 生成 AST 树
  • 优化
  • codegen

MVVM

MVVMModel-View-ViewModel 缩写,也就是把 MVC 中的 Controller 演变成 ViewModelModel 层代表数据模型,View代表 UI 组件,ViewModel 是 View 和 Model 层的 桥梁,数据会绑定到 viewModel 层并主动将数据渲染到页面中,视图变动的时候会告诉 viewModel 层更新数据。

响应式数据原理(Vue2.x & Vue3.0)

Vue2.x在初始化数据时,会应用 Object.defineProperty 从新定义 data 中的所有属性,当页面应用对应属性时,首先会进行 依赖收集 (收集以后组件的 watcher),如果属性发生变化会告诉相干依赖进行 派发更细(公布订阅模式)。

vue3.0采纳 es6 中的 proxy 代替 Object.defineProperty 做数据监听。

Proxy 与 Object.defineProperty 的优劣比照?

Proxy 的劣势 如下:

  • Proxy 能够间接监听对象而非属性
  • Proxy 能够间接监听数组的变动
  • Proxy 有多达 13 种拦挡办法, 不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的
  • Proxy 返回的是一个新对象, 咱们能够只操作新的对象达到目标, 而 Object.defineProperty 只能遍历对象属性间接批改
  • Proxy 作为新规范将受到浏览器厂商重点继续的性能优化,也就是传说中的新规范的性能红利

Object.defineProperty 的劣势 如下:

  • 兼容性好, 反对 IE9

vue 的$nextTick

在下次 DOM 更新循环完结之后执行提早回调。nextTick次要应用了宏工作和微工作。依据执行环境别离尝试采纳

  • Promise
  • MutationObserver
  • setImmediate
  • 如果以上都不行则采纳 setTimeout

定义了一个异步办法,屡次调用 nextTick 会将办法存入队列中,通过这个异步办法清空以后队列。

vue 组件中 data 为什么必须是一个函数

复用组件的时候,都会返回一份新的 data,相当于每个组件实例都有本人公有的数据空间,不会共享同一个 data 对象。

vue 中组件通信的形式

  1. 父传子:props
  2. 子传父:$emitref
  3. 兄弟:EventBus

vue-router

vue-router是 vue 的官网插件,次要用来治理前端路由。对于 Vue 这类渐进式前端开发框架,为了构建 SPA(单页面利用),须要引入前端路由零碎,这也就是 Vue-Router 存在的意义。前端路由的外围,就在于:扭转视图的同时不会向后端发出请求

性能有:

  • 扭转 URL 且不让浏览器向服务器发出请求
  • 检测 URL 的扭转
  • 记录以后页面的状态
  • 能够应用浏览器的后退后退性能
  • URL 门路决定页面如何显示

history 和 hash 模式的区别

1. 实现原理

hash 模式和 history 模式都属于浏览器本身的个性,Vue-Router 只是利用了这两个个性(通过调用浏览器提供的接口)来实现前端路由。

2. 比照表格

区别 \ mode hash history
监听事件 hashChange popstate
毛病 # 号不难看 子路由刷新 404、ie9 及以下不兼容
push 操作 window.location.assign window.history.pushState
replace 操作 window.location.replace window.history.replaceState
拜访操作 window.history.go window.history.go
后退操作 window.history.go(-1) window.history.go(-1)
向前操作 window.history.go(1) window.history.go(1)

3. 对于 popstate 事件监听路由的局限 history 对象的 back(), forward() 和 go() 三个等操作会被动触发 popstate 事件,然而 pushState 和 replaceState 不会触发 popstate 事件,这时咱们须要手动触发页面跳转(渲染)。

4. 对于子路由刷新的解决形式

history模式子路由刷新会 404,因而须要后端配合,将未匹配到的路由默认指向 html 文件

5. 浏览器(环境)兼容解决

history 模式中 pushStatereplaceStateHTML5的新个性,在 IE9 下会强行降级应用 hash 模式,非浏览器环境转换成abstract 模式。

6. router-link router-link点击相当于调用 $router.push 办法去批改url

<router-link> 比起写死的 <a href="..."> 会好一些,理由如下:

  1. 无论是 HTML5 history 模式还是 hash 模式,它的体现行为统一,所以,当你要切换路由模式,或者在 IE9 降级应用 hash 模式,毋庸作任何变动。
  2. 在 HTML5 history 模式下,router-link 会守卫点击事件,让浏览器不再从新加载页面。
  3. 当你在 HTML5 history 模式下应用 base 选项之后,所有的 to 属性都不须要写(基门路)了。

vue-router 路由懒加载

像 vue 这种单页面利用,如果没有路由懒加载,使用 webpack 打包后的文件将会很大,造成进入首页时,须要加载的内容过多,呈现较长时间的白屏,使用路由懒加载则能够将页面进行划分,须要的时候才加载页面,能够无效的分担首页所承当的加载压力,缩小首页加载用时。

vue 路由懒加载有以下三种形式:

  1. vue 异步组件
  2. ES6 的 import()
  3. webpack 的 require.ensure()

1. vue 异步组件 这种办法次要是应用了 resolve 的异步机制,用 require 代替了 import 实现按需加载

export default new Router({
  routes: [
    {
      path: '/home',',
      component: (resolve) => require(['@/components/home'], resolve),
    },
    {
      path: '/about',',
      component: (resolve) => require(['@/components/about'], resolve),
    },
  ],
})
复制代码

2. ES6 的 import() vue-router 在官网提供了一种办法,能够了解也是为通过 Promise 的 resolve 机制。因为 Promise 函数返回的 Promise 为 resolve 组件自身,而咱们又能够应用 import 来导入组件。

export default new Router({
  routes: [
    {
      path: '/home',
      component: () => import('@/components/home'),
    },
    {
      path: '/about',
      component: () => import('@/components/home'),
    },
  ],
})
复制代码

1. webpack 的 require.ensure() 这种模式能够通过参数中的 webpackChunkName 将 js 离开打包。

export default new Router({
  routes: [
    {
      path: '/home',
      component: (resolve) => require.ensure([], () => resolve(require('@/components/home')), 'home'),
    },
    {
      path: '/about',
      component: (resolve) => require.ensure([], () => resolve(require('@/components/about')), 'about'),
    },
  ],
})
复制代码


篇幅无限,还有没有收回来的题目都前端面试题材料里,须要残缺 PDF 材料的小伙伴只须要点击这里就能够收费获取!

有被问到题目的小伙伴们评论区能够聊聊你是怎么答复的哦,没有被问到的更要多看熟记,说不定就会碰到啦~ 这篇文章对你有帮忙请评论点赞反对一波,谢谢!

退出移动版