乐趣区

关于前端:vue最全知识点基础到进阶覆盖vue30建议收藏

说说你对 MVVM 的了解
  • Model-View-ViewModel 的缩写,Model 代表数据模型,View 代表 UI 组件,ViewModel 将 Model 和 View 关联起来
  • 数据会绑定到 viewModel 层并主动将数据渲染到页面中,视图变动的时候会告诉 viewModel 层更新数据

理解 mvc/mvp/mvvm 的区别

Vue2.x 响应式数据 / 双向绑定原理
  • Vue 数据双向绑定次要是指:数据变动更新视图,视图变动更新数据 。其中,View 变动更新 Data,能够通过事件监听的形式来实现,所以 Vue 数据双向绑定的工作次要是如何 依据 Data 变动更新 View
  • 简述
  • 当你把一个一般的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并应用 Object.defineProperty 把这些 property 全副转为 getter/setter。
  • 这些 getter/setter 对用户来说是不可见的,然而在外部它们让 Vue 可能追踪依赖,在 property 被拜访和批改时告诉变更。
  • 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会告诉 watcher,从而使它关联的组件从新渲染。

  • 深刻了解:
  • 监听器 Observer:对数据对象进行遍历,包含子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变动。
  • 解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者,一旦数据有变动,收到告诉,调用更新函数进行数据更新。
  • 订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,次要的工作是订阅 Observer 中的属性值变动的音讯,当收到属性值变动的音讯时,触发解析器 Compile 中对应的更新函数。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会告诉 watcher 从新计算,从而以致它关联的组件得以更新——这是一个典型的观察者模式
  • 订阅器 Dep:订阅器采纳 公布 - 订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行对立治理。
你晓得 Vue3.x 响应式数据原理吗?
  • Vue3.x 改用 Proxy 代替 Object.defineProperty
  • 因为 Proxy 能够间接监听对象和数组的变动,并且有多达 13 种拦挡办法。并且作为新规范将受到浏览器厂商重点继续的性能优化。
  • Proxy 只会代理对象的第一层,Vue3 是怎么解决这个问题的呢?
  • 判断以后 Reflect.get 的返回值是否为 Object,如果是则再通过 reactive 办法做代理,这样就实现了深度观测。
  • 监测数组的时候可能触发屡次 get/set,那么如何避免触发屡次呢?咱们能够判断 key 是否为以后被代理对象 target 本身属性,也能够判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger。
Proxy 与 Object.defineProperty 优劣比照
  • Proxy 的劣势如下:
  • Proxy 能够间接监听对象而非属性;
  • Proxy 能够间接监听数组的变动;
  • Proxy 有多达 13 种拦挡办法, 不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
  • Proxy 返回的是一个新对象, 咱们能够只操作新的对象达到目标, 而 Object.defineProperty 只能遍历对象属性间接批改;
  • Proxy 作为新规范将受到浏览器厂商重点继续的性能优化,也就是传说中的新规范的性能红利;
  • Object.defineProperty 的劣势如下:
  • 兼容性好,反对 IE9,而 Proxy 的存在浏览器兼容性问题, 而且无奈用 polyfill 磨平,因而 Vue 的作者才申明须要等到下个大版本 (3.0) 能力用 Proxy 重写。

VUEX 篇

Vuex 是什么?

使用到了 js 设计模式中的单例模式,单例模式想要做到的是,不论咱们尝试去创立多少次,它都只给你返回第一次所创立的那惟一的一个实例。

  • Vuex 是一个专为 Vue.js 利用程序开发的状态管理模式。每一个 Vuex 利用的外围就是 store(仓库)。“store”基本上就是一个容器,它蕴含着你的利用中大部分的状态 (state)。
  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。
  • 扭转 store 中的状态的惟一路径就是显式地提交 (commit) mutation。这样使得咱们能够不便地跟踪每一个状态的变动。

Vuex 应用繁多状态树,用一个对象就蕴含了全副的利用层级状态。至此它便作为一个“惟一数据源 (SSOT)”而存在。这也意味着,每个利用将仅仅蕴含一个 store 实例。繁多状态树让咱们可能间接地定位任一特定的状态片段,在调试的过程中也能轻易地获得整个以后利用状态的快照。——Vuex 官网文档

  • 次要包含以下几个模块:
  • State:定义了利用状态的数据结构,能够在这里设置默认的初始状态。
  • Getter:容许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到部分计算属性。
  • Mutation:是惟一更改 store 中状态的办法,且必须是同步函数。
  • Action:用于提交 mutation,而不是间接变更状态,能够蕴含任意异步操作。
  • Module:容许将繁多的 Store 拆分为多个 store 且同时保留在繁多的状态树中。
什么状况下应用 Vuex?
  • 如果利用够简略,最好不要应用 Vuex,一个简略的 store 模式即可
  • 须要构建一个中大型单页利用时,应用 Vuex 能更好地在组件内部治理状态
Vuex 和单纯的全局对象有什么区别?
  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。
  • 不能间接扭转 store 中的状态。扭转 store 中的状态的惟一路径就是显式地提交 (commit) mutation。这样使得咱们能够不便地跟踪每一个状态的变动,从而让咱们可能实现一些工具帮忙咱们更好地理解咱们的利用。
为什么 Vuex 的 mutation 中不能做异步操作?
  • Vuex 中所有的状态更新的惟一路径都是 mutation,异步操作通过 Action 来提交 mutation 实现,这样使得咱们能够不便地跟踪每一个状态的变动,从而让咱们可能实现一些工具帮忙咱们更好地理解咱们的利用。
  • 每个 mutation 执行实现后都会对应到一个新的状态变更,这样 devtools 就能够打个快照存下来,而后就能够实现 time-travel 了。如果 mutation 反对异步操作,就没有方法晓得状态是何时更新的,无奈很好的进行状态的追踪,给调试带来艰难。
新增:vuex 的 action 有返回值吗?返回的是什么?
  • store.dispatch 能够解决被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
  • Action 通常是异步的,要晓得 action 什么时候完结或者组合多个 action 以解决更加简单的异步流程,能够通过定义 action 时返回一个 promise 对象,就能够在派发 action 的时候就能够通过解决返回的 Promise 解决异步流程

一个 store.dispatch 在不同模块中能够触发多个 action 函数。在这种状况下,只有当所有触发函数实现后,返回的 Promise 才会执行。

新增:为什么不间接散发 mutation, 而要通过散发 action 之后提交 mutation 变更状态
  • mutation 必须同步执行,咱们能够在 action 外部执行异步操作
  • 能够进行一系列的异步操作,并且通过提交 mutation 来记录 action 产生的副作用(即状态变更)

惯例篇

computed 和 watch 的区别和使用的场景?
  • computed:是计算属性,依赖其它属性值,并且 computed 的值有 缓存 ,只有它 依赖的属性值 产生扭转,下一次获取 computed 的值时才会从新计算 computed 的值;
  • watch:没有缓存性,更多的是「察看」的作用,相似于某些数据的监听回调,每当监听的数据变动时都会执行回调进行后续操作;当咱们须要深度监听对象中的属性时,能够关上 deep:true 选项,这样便会对对象中的每一项进行监听
  • 使用场景
  • 当咱们须要进行数值计算,并且依赖于其它数据时,应该应用 computed,因为能够利用 computed 的缓存个性,防止每次获取值时,都要从新计算;
  • 当咱们须要在数据变动时执行异步或开销较大的操作时,应该应用 watch,应用 watch 选项容许咱们执行异步操作 (拜访一个 API),限度咱们执行该操作的频率,并在咱们失去最终后果前,设置中间状态。这些都是计算属性无奈做到的。
Vue2.x 组件通信有哪些形式?
  • 父子组件通信
  • 事件机制(** 父 -> 子 props, 子 -> 父 $on、$emit)
  • 获取父子组件实例 $parent、$children
  • Ref 获取实例的形式调用组件的属性或者办法
  • Provide、inject (不举荐应用,组件库时很罕用)
  • 兄弟组件通信

    Vue.prototype.$bus = new Vue

  • Vuex
  • eventBus 这种办法通过 一个空的 Vue 实例作为地方事件总线(事件核心),用它来触发事件和监听事件,从而实现任何组件间的通信,包含父子、隔代、兄弟组件
  • 跨级组件通信
  • Vuex
  • $attrs、$listeners
  • Provide、inject
说一下 v -if 和 v -show 的区别
  • 当条件不成立时,v-if 不会渲染 DOM 元素,v-show 操作的是款式(display),切换以后 DOM 的显示和暗藏。
  • v-if 实用于在运行时很少扭转条件,不须要频繁切换条件的场景;
  • v-show 则实用于须要十分频繁切换条件的场景。
为什么 v-for 和 v-if 不倡议用在一起
  • 当 v-for 和 v-if 处于同一个节点时,v-for 的优先级比 v-if 更高,这意味着 v-if 将别离反复运行于每个 v-for 循环中。如果要遍历的数组很大,而真正要展现的数据很少时,这将造成很大的性能节约
  • 这种场景倡议应用 computed,先对数据进行过滤
组件中的 data 为什么是一个函数?
  • 一个组件被复用屡次的话,也就会创立多个实例。实质上,这些实例用的都是同一个构造函数。
  • 如果 data 是对象的话,对象属于援用类型,会影响到所有的实例。所以为了保障组件不同的实例之间 data 不抵触,data 必须是一个函数。
子组件为什么不能够批改父组件传递的 Prop?/ 怎么了解 vue 的单向数据流?
  • Vue 提倡单向数据流, 即父级 props 的更新会流向子组件, 然而反过来则不行。
  • 这是为了避免意外的扭转父组件状态,使得利用的数据流变得难以了解。
  • 如果毁坏了单向数据流,当利用简单时,debug 的老本会十分高。
v-model 是如何实现双向绑定的?
  • v-model 是用来在表单控件或者组件上创立双向绑定的
  • 他的实质是 v -bind 和 v -on 的语法糖
  • 在一个组件上应用 v -model,默认会为组件绑定名为 value 的 prop 和名为 input 的事件
nextTick 的实现原理是什么?
  • 在下次 DOM 更新循环完结之后执行提早回调,在批改数据之后立刻应用 nextTick 来获取更新后的 DOM。
  • nextTick 次要应用了 宏工作 微工作
  • 依据执行环境别离尝试采纳 Promise、MutationObserver、setImmediate,如果以上都不行则采纳 setTimeout 定义了一个异步办法,屡次调用 nextTick 会将办法存入队列中,通过这个异步办法清空以后队列。
Vue 不能检测数组的哪些变动?Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题?
  • Vue 不能检测以下数组的变动:
  • 第一类问题
// 法一:Vue.set Vue.set(vm.items, indexOfItem, newValue) // 法二:Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
  • 第二类问题,可应用 splice:
vm.items.splice(newLength)
  • 当你利用索引间接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 当你批改数组的长度时,例如:vm.items.length = newLength
  • 解决办法:
  • vm.$set 的实现原理是:
  • 如果指标是数组,间接应用数组的 splice 办法触发相应式;
  • 如果指标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式解决,则是通过调用 defineReactive 办法进行响应式解决(defineReactive 办法就是 Vue 在初始化对象时,给对象属性采纳 Object.defineProperty 动静增加 getter 和 setter 的性能所调用的办法)
Vue 事件绑定原理是什么?
  • 原生事件绑定是通过 addEventListener 绑定给实在元素的,组件事件绑定是通过 Vue 自定义的 $on 实现的。
说一下虚构 Dom 以及 key 属性的作用
  • 因为在浏览器中操作 DOM 是很低廉的。频繁的操作 DOM,会产生肯定的性能问题。这就是虚构 Dom 的产生起因。
  • Virtual DOM 实质就是用一个 原生的 JS 对象去形容一个 DOM 节点。是对实在 DOM 的一层形象。(也就是源码中的 VNode 类,它定义在 src/core/vdom/vnode.js 中。)
  • 虚构 DOM 的实现原理次要包含以下 3 局部:
  • 用 JavaScript 对象模仿实在 DOM 树,对实在 DOM 进行形象;
  • diff 算法 — 比拟两棵虚构 DOM 树的差别;
  • pach 算法 — 将两个虚构 DOM 对象的差别利用到真正的 DOM 树。
  • key 是为 Vue 中 vnode 的惟一标记,通过这个 key,咱们的 diff 操作能够更精确、更疾速
  • 更精确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 比照中能够防止就地复用的状况。所以会更加精确。
  • 更疾速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历形式更快
为什么不倡议用 index 作为 key?
  • 不倡议 用 index 作为 key,和没写基本上没区别,因为不论你数组的程序怎么颠倒,index 都是 0, 1, 2 这样排列,导致 Vue 会复用谬误的旧子节点,做很多额定的工作

生命周期篇

说一下你对 Vue 的生命周期的了解
  • 简略答复
  • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
  • keep-alive 有本人独立的钩子函数 activated 和 deactivated。
  • 简单答复

| 生命周期

产生了什么

beforeCreate

created

beforeMount

mounted

beforeUpdate

updated

beforeDestroy

destroyed

activited keep-alive 专属

deactivated keep-alive 专属

Vue 中组件生命周期调用程序是什么样的?
  • 组件的调用程序都是先父后子, 渲染实现的程序是先子后父。
  • 组件的销毁操作是先父后子,销毁实现的程序是先子后父。
在什么阶段能力拜访操作 DOM?

在钩子函数 mounted 被调用前,Vue 曾经将编译好的模板挂载到页面上,所以在 mounted 中能够拜访操作 DOM。

你的接口申请个别放在哪个生命周期中?
  • 能够在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 曾经创立,能够将服务端端返回的数据进行赋值。
  • 然而举荐在 created 钩子函数中调用异步申请,因为在 created 钩子函数中调用异步申请有以下长处:
  • 能更快获取到服务端数据,缩小页面 loading 工夫;
  • ssr 不反对 beforeMount、mounted 钩子函数,所以放在 created 中有助于一致性;

路由篇

vue 路由 hash 模式和 history 模式实现原理别离是什么,他们的区别是什么?
  • hash 模式:
  • 前面 hash 值的变动,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面

  • 通过监听 hashchange 事件能够晓得 hash 产生了哪些变动,而后依据 hash 变动来实现更新页面局部内容的操作。
  • history 模式:
  • history 模式的实现,次要是 HTML5 规范公布的两个 API,pushState 和replaceState,这两个 API 能够在扭转 url,然而不会发送申请。这样就能够监听 url 变动来实现更新页面局部内容的操作
  • 区别
  • url 展现上,hash 模式有“#”,history 模式没有
  • 刷新页面时,hash 模式能够失常加载到 hash 值对应的页面,而 history 没有解决的话,会返回 404,个别须要后端将所有页面都配置重定向到首页路由
  • 兼容性,hash 能够反对低版本浏览器和 IE。
路由懒加载是什么意思?如何实现路由懒加载?
  • 路由懒加载的含意:把不同路由对应的组件宰割成不同的代码块,而后当路由被拜访的时候才加载对应组件
  • 实现:联合 Vue 的异步组件和 Webpack 的代码宰割性能
  • 能够将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件自身)
    
const Foo = () => Promise.resolve({ /* 组件定义对象 */})
  • 2. 在 Webpack 2 中,咱们能够应用动静 import 语法来定义代码分块点 (split point)
    
import('./Foo.vue') // 返回 Promise
  • 联合这两者,这就是如何定义一个可能被 Webpack 主动代码宰割的异步组件
const Foo = () => import('./Foo.vue') const router = new VueRouter({routes: [ { path: '/foo', component: Foo} ]})
  • 应用命名 chunk,和 webpack 中的魔法正文就能够把某个路由下的所有组件都打包在同个异步块 (chunk) 中
chunkconst Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
Vue-router 导航守卫有哪些
  • 全局前置 / 钩子:beforeEach、beforeResolve、afterEach
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
    • *

进阶篇

说说 vue 和 react 的异同
  • 应用 Virtual DOM
  • 提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。
  • 将注意力集中放弃在外围库,而将其余性能如路由和全局状态治理交给相干的库。
  • 在 React 利用中,当某个组件的状态发生变化时,它会以该组件为根,从新渲染整个组件子树(除非应用 PureComponent/shouldComponentUpdate),在 Vue 利用中,组件的依赖是在渲染过程中主动追踪的,所以零碎能准确通晓哪个组件的确须要被重渲染
  • 在 React 中,一切都是 JavaScript。不仅仅是 HTML 能够用 JSX 来表白,当初的潮流也越来越多地将 CSS 也纳入到 JavaScript 中来解决
  • Vue 的路由库和状态治理库都是由官网保护反对且与外围库同步更新的。React 则是抉择把这些问题交给社区保护,因而创立了一个更扩散的生态系统,所以有更丰盛的生态系统
  • Vue 提供了 CLI 脚手架,能让你通过交互式的脚手架疏导非常容易地构建我的项目。你甚至能够应用它疾速开发组件的原型。React 在这方面也提供了 create-react-app,然而当初还存在一些局限性
  • React Native 能使你用雷同的组件模型编写有本地渲染能力的 APP,Vue 和 Weex 会进行官网单干,Weex 是阿里巴巴发动的跨平台用户界面开发框架,同时也正在 Apache 基金会进行我的项目孵化,另一个抉择是 NativeScript-Vue,一个用 Vue.js 构建齐全原生利用的 NativeScript 插件
什么是 mixin?
  • Mixin 使咱们可能为 Vue 组件编写可插拔和可重用的性能。
  • 如果你心愿再多个组件之间重用一组组件选项,例如生命周期 hook、办法等,则能够将其编写为 mixin,并在组件中简略的援用它。
  • 而后将 mixin 的内容合并到组件中。如果你要在 mixin 中定义生命周期 hook,那么它在执行时将优化于组件自已的 hook。
在 Vue 实例中编写生命周期 hook 或其余 option/properties 时,为什么不应用箭头函数?
  • 箭头函数自已没有定义 this 上下文中。
  • 当你在 Vue 程序中应用箭头函数 (=>) 时,this 关键字病不会绑定到 Vue 实例,因而会引发谬误。所以强烈建议改用规范函数申明。
Vue 模版编译原理晓得吗,能简略说一下吗?

简略说,Vue 的编译过程就是将 template 转化为 render 函数的过程。会经验以下阶段(生成 AST 树 / 优化 /codegen):

  • 首先解析模版,生成 AST 语法树(一种用 JavaScript 对象的模式来形容整个模板)。应用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相干解决。
  • Vue 的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变动,对应的 DOM 也不会变动。那么优化过程就是深度遍历 AST 树,依照相干条件对树节点进行标记。这些被标记的节点 (动态节点) 咱们就能够跳过对它们的比对,对运行时的模板起到很大的优化作用。
  • 编译的最初一步是将优化后的 AST 树转换为可执行的代码。
diff 算法说一下
  • 同级比拟,再比拟子节点
  • 先判断一方有子节点一方没有子节点的状况(如果新的 children 没有子节点,将旧的子节点移除)
  • 比拟都有子节点的状况(外围 diff)
  • 递归比拟子节点
说说你对 keep-alive 组件的理解
  • keep-alive 是 Vue 内置的一个组件,能够使被蕴含的组件保留状态,防止从新渲染,其有以下个性:
  • 个别联合路由和动静组件一起应用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都反对字符串或正则表达式,include 示意只有名称匹配的组件会被缓存,exclude 示意任何名称匹配的组件都不会被缓存,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
说说你对 SSR 的理解
  • SSR 也就是服务端渲染,也就是将 Vue 在客户端把标签渲染成 HTML 的工作放在服务端实现,而后再把 html 间接返回给客户端
  • SSR 的劣势
  • 更好的 SEO
  • 首屏加载速度更快
  • SSR 的毛病
  • 开发条件会受到限制,服务器端渲染只反对 beforeCreate 和 created 两个钩子
  • 当咱们须要一些内部扩大库时须要非凡解决,服务端渲染应用程序也须要处于 Node.js 的运行环境
  • 更多的服务端负载
你都做过哪些 Vue 的性能优化?
  • 编码阶段
  • 尽量减少 data 中的数据,data 中的数据都会减少 getter 和 setter,会收集对应的 watcher
  • v-if 和 v -for 不能连用
  • 如果须要应用 v -for 给每项元素绑定事件时应用事件代理
  • SPA 页面采纳 keep-alive 缓存组件
  • 在更多的状况下,应用 v -if 代替 v -show
  • key 保障惟一
  • 应用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动静加载
  • 图片懒加载
  • SEO 优化
  • 预渲染
  • 服务端渲染 SSR
  • 打包优化
  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • 应用 cdn 加载第三方模块
  • 多线程打包 happypack
  • splitChunks 抽离公共文件
  • sourceMap 优化
  • 用户体验
  • 骨架屏
  • PWA
  • 还能够应用缓存 (客户端缓存、服务端缓存) 优化、服务端开启 gzip 压缩等。
vue2.x 中如何监测数组变动?
  • 应用了函数劫持的形式,重写了数组的办法,Vue 将 data 中的数组进行了原型链重写,指向了本人定义的数组原型办法,当调用数组 api 时,能够告诉依赖更新。
  • 如果数组中蕴含着援用类型,会对数组中的援用类型再次递归遍历进行监控。这样就实现了监测数组变动。
说说你对 SPA 单页面的了解,它的优缺点别离是什么?
  • SPA(single-page application)仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载实现,SPA 不会因为用户的操作而进行页面的从新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,防止页面的从新加载。
  • 长处:
  • 用户体验好、快,内容的扭转不须要从新加载整个页面,防止了不必要的跳转和反复渲染;
  • 基于下面一点,SPA 绝对对服务器压力小;
  • 前后端职责拆散,架构清晰,前端进行交互逻辑,后端负责数据处理;
  • 毛病:
  • 首次加载耗时多:为实现单页 Web 利用性能及显示成果,须要在加载页面的时候将 JavaScript、CSS 对立加载,局部页面按需加载;
  • 后退后退路由治理:因为单页利用在一个页面中显示所有的内容,所以不能应用浏览器的后退后退性能,所有的页面切换须要本人建设堆栈治理;
  • SEO 难度较大:因为所有的内容都在一个页面中动静替换显示,所以在 SEO 上其有着人造的弱势。
对于行将到来的 vue3.0 个性你有什么理解的吗?
  • 监测机制的扭转
  • 3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言笼罩的反馈性跟踪。
  • 打消了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限度:
  • 只能监测属性,不能监测对象
  • 检测属性的增加和删除;
  • 检测数组索引和长度的变更;
  • 反对 Map、Set、WeakMap 和 WeakSet。
  • 模板
  • 模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会从新渲染,而 3.0 把作用域插槽改成了函数的形式,这样只会影响子组件的从新渲染,晋升了渲染的性能。
  • 同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来不便习惯间接应用 api 来生成 vdom。
  • 对象式的组件申明形式
  • vue2.x 中的组件是通过申明的形式传入一系列 option,和 TypeScript 的联合须要通过一些装璜器的形式来做,尽管能实现性能,然而比拟麻烦。
  • 3.0 批改了组件的申明形式,改成了类式的写法,这样使得和 TypeScript 的联合变得很容易
  • 其它方面的更改
  • 反对自定义渲染器,从而使得 weex 能够通过自定义渲染器的形式来扩大,而不是间接 fork 源码来改的形式。
  • 反对 Fragment(多个根节点)和 Protal(在 dom 其余局部渲染组建内容)组件,针对一些非凡的场景做了解决。
  • 基于 tree shaking 优化,提供了更多的内置性能。#### 说说你对 MVVM 的了解
  • Model-View-ViewModel 的缩写,Model 代表数据模型,View 代表 UI 组件,ViewModel 将 Model 和 View 关联起来
  • 数据会绑定到 viewModel 层并主动将数据渲染到页面中,视图变动的时候会告诉 viewModel 层更新数据

理解 mvc/mvp/mvvm 的区别

Vue2.x 响应式数据 / 双向绑定原理
  • Vue 数据双向绑定次要是指:数据变动更新视图,视图变动更新数据 。其中,View 变动更新 Data,能够通过事件监听的形式来实现,所以 Vue 数据双向绑定的工作次要是如何 依据 Data 变动更新 View
  • 简述
  • 当你把一个一般的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并应用 Object.defineProperty 把这些 property 全副转为 getter/setter。
  • 这些 getter/setter 对用户来说是不可见的,然而在外部它们让 Vue 可能追踪依赖,在 property 被拜访和批改时告诉变更。
  • 每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会告诉 watcher,从而使它关联的组件从新渲染。

  • 深刻了解:
  • 监听器 Observer:对数据对象进行遍历,包含子属性对象的属性,利用 Object.defineProperty() 对属性都加上 setter 和 getter。这样的话,给这个对象的某个值赋值,就会触发 setter,那么就能监听到了数据变动。
  • 解析器 Compile:解析 Vue 模板指令,将模板中的变量都替换成数据,而后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,增加监听数据的订阅者,一旦数据有变动,收到告诉,调用更新函数进行数据更新。
  • 订阅者 Watcher:Watcher 订阅者是 Observer 和 Compile 之间通信的桥梁,次要的工作是订阅 Observer 中的属性值变动的音讯,当收到属性值变动的音讯时,触发解析器 Compile 中对应的更新函数。每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会告诉 watcher 从新计算,从而以致它关联的组件得以更新——这是一个典型的观察者模式
  • 订阅器 Dep:订阅器采纳 公布 - 订阅 设计模式,用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行对立治理。
你晓得 Vue3.x 响应式数据原理吗?
  • Vue3.x 改用 Proxy 代替 Object.defineProperty
  • 因为 Proxy 能够间接监听对象和数组的变动,并且有多达 13 种拦挡办法。并且作为新规范将受到浏览器厂商重点继续的性能优化。
  • Proxy 只会代理对象的第一层,Vue3 是怎么解决这个问题的呢?
  • 判断以后 Reflect.get 的返回值是否为 Object,如果是则再通过 reactive 办法做代理,这样就实现了深度观测。
  • 监测数组的时候可能触发屡次 get/set,那么如何避免触发屡次呢?咱们能够判断 key 是否为以后被代理对象 target 本身属性,也能够判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger。
Proxy 与 Object.defineProperty 优劣比照
  • Proxy 的劣势如下:
  • Proxy 能够间接监听对象而非属性;
  • Proxy 能够间接监听数组的变动;
  • Proxy 有多达 13 种拦挡办法, 不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
  • Proxy 返回的是一个新对象, 咱们能够只操作新的对象达到目标, 而 Object.defineProperty 只能遍历对象属性间接批改;
  • Proxy 作为新规范将受到浏览器厂商重点继续的性能优化,也就是传说中的新规范的性能红利;
  • Object.defineProperty 的劣势如下:
  • 兼容性好,反对 IE9,而 Proxy 的存在浏览器兼容性问题, 而且无奈用 polyfill 磨平,因而 Vue 的作者才申明须要等到下个大版本 (3.0) 能力用 Proxy 重写。

VUEX 篇

Vuex 是什么?

使用到了 js 设计模式中的单例模式,单例模式想要做到的是,不论咱们尝试去创立多少次,它都只给你返回第一次所创立的那惟一的一个实例。

  • Vuex 是一个专为 Vue.js 利用程序开发的状态管理模式。每一个 Vuex 利用的外围就是 store(仓库)。“store”基本上就是一个容器,它蕴含着你的利用中大部分的状态 (state)。
  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。
  • 扭转 store 中的状态的惟一路径就是显式地提交 (commit) mutation。这样使得咱们能够不便地跟踪每一个状态的变动。

Vuex 应用繁多状态树,用一个对象就蕴含了全副的利用层级状态。至此它便作为一个“惟一数据源 (SSOT)”而存在。这也意味着,每个利用将仅仅蕴含一个 store 实例。繁多状态树让咱们可能间接地定位任一特定的状态片段,在调试的过程中也能轻易地获得整个以后利用状态的快照。——Vuex 官网文档

  • 次要包含以下几个模块:
  • State:定义了利用状态的数据结构,能够在这里设置默认的初始状态。
  • Getter:容许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到部分计算属性。
  • Mutation:是惟一更改 store 中状态的办法,且必须是同步函数。
  • Action:用于提交 mutation,而不是间接变更状态,能够蕴含任意异步操作。
  • Module:容许将繁多的 Store 拆分为多个 store 且同时保留在繁多的状态树中。
什么状况下应用 Vuex?
  • 如果利用够简略,最好不要应用 Vuex,一个简略的 store 模式即可
  • 须要构建一个中大型单页利用时,应用 Vuex 能更好地在组件内部治理状态
Vuex 和单纯的全局对象有什么区别?
  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地失去高效更新。
  • 不能间接扭转 store 中的状态。扭转 store 中的状态的惟一路径就是显式地提交 (commit) mutation。这样使得咱们能够不便地跟踪每一个状态的变动,从而让咱们可能实现一些工具帮忙咱们更好地理解咱们的利用。
为什么 Vuex 的 mutation 中不能做异步操作?
  • Vuex 中所有的状态更新的惟一路径都是 mutation,异步操作通过 Action 来提交 mutation 实现,这样使得咱们能够不便地跟踪每一个状态的变动,从而让咱们可能实现一些工具帮忙咱们更好地理解咱们的利用。
  • 每个 mutation 执行实现后都会对应到一个新的状态变更,这样 devtools 就能够打个快照存下来,而后就能够实现 time-travel 了。如果 mutation 反对异步操作,就没有方法晓得状态是何时更新的,无奈很好的进行状态的追踪,给调试带来艰难。
新增:vuex 的 action 有返回值吗?返回的是什么?
  • store.dispatch 能够解决被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
  • Action 通常是异步的,要晓得 action 什么时候完结或者组合多个 action 以解决更加简单的异步流程,能够通过定义 action 时返回一个 promise 对象,就能够在派发 action 的时候就能够通过解决返回的 Promise 解决异步流程

一个 store.dispatch 在不同模块中能够触发多个 action 函数。在这种状况下,只有当所有触发函数实现后,返回的 Promise 才会执行。

新增:为什么不间接散发 mutation, 而要通过散发 action 之后提交 mutation 变更状态
  • mutation 必须同步执行,咱们能够在 action 外部执行异步操作
  • 能够进行一系列的异步操作,并且通过提交 mutation 来记录 action 产生的副作用(即状态变更)

惯例篇

computed 和 watch 的区别和使用的场景?
  • computed:是计算属性,依赖其它属性值,并且 computed 的值有 缓存 ,只有它 依赖的属性值 产生扭转,下一次获取 computed 的值时才会从新计算 computed 的值;
  • watch:没有缓存性,更多的是「察看」的作用,相似于某些数据的监听回调,每当监听的数据变动时都会执行回调进行后续操作;当咱们须要深度监听对象中的属性时,能够关上 deep:true 选项,这样便会对对象中的每一项进行监听
  • 使用场景
  • 当咱们须要进行数值计算,并且依赖于其它数据时,应该应用 computed,因为能够利用 computed 的缓存个性,防止每次获取值时,都要从新计算;
  • 当咱们须要在数据变动时执行异步或开销较大的操作时,应该应用 watch,应用 watch 选项容许咱们执行异步操作 (拜访一个 API),限度咱们执行该操作的频率,并在咱们失去最终后果前,设置中间状态。这些都是计算属性无奈做到的。
Vue2.x 组件通信有哪些形式?
  • 父子组件通信
  • 事件机制(** 父 -> 子 props, 子 -> 父 $on、$emit)
  • 获取父子组件实例 $parent、$children
  • Ref 获取实例的形式调用组件的属性或者办法
  • Provide、inject (不举荐应用,组件库时很罕用)
  • 兄弟组件通信

    Vue.prototype.$bus = new Vue

  • Vuex
  • eventBus 这种办法通过 一个空的 Vue 实例作为地方事件总线(事件核心),用它来触发事件和监听事件,从而实现任何组件间的通信,包含父子、隔代、兄弟组件
  • 跨级组件通信
  • Vuex
  • $attrs、$listeners
  • Provide、inject
说一下 v -if 和 v -show 的区别
  • 当条件不成立时,v-if 不会渲染 DOM 元素,v-show 操作的是款式(display),切换以后 DOM 的显示和暗藏。
  • v-if 实用于在运行时很少扭转条件,不须要频繁切换条件的场景;
  • v-show 则实用于须要十分频繁切换条件的场景。
为什么 v-for 和 v-if 不倡议用在一起
  • 当 v-for 和 v-if 处于同一个节点时,v-for 的优先级比 v-if 更高,这意味着 v-if 将别离反复运行于每个 v-for 循环中。如果要遍历的数组很大,而真正要展现的数据很少时,这将造成很大的性能节约
  • 这种场景倡议应用 computed,先对数据进行过滤
组件中的 data 为什么是一个函数?
  • 一个组件被复用屡次的话,也就会创立多个实例。实质上,这些实例用的都是同一个构造函数。
  • 如果 data 是对象的话,对象属于援用类型,会影响到所有的实例。所以为了保障组件不同的实例之间 data 不抵触,data 必须是一个函数。
子组件为什么不能够批改父组件传递的 Prop?/ 怎么了解 vue 的单向数据流?
  • Vue 提倡单向数据流, 即父级 props 的更新会流向子组件, 然而反过来则不行。
  • 这是为了避免意外的扭转父组件状态,使得利用的数据流变得难以了解。
  • 如果毁坏了单向数据流,当利用简单时,debug 的老本会十分高。
v-model 是如何实现双向绑定的?
  • v-model 是用来在表单控件或者组件上创立双向绑定的
  • 他的实质是 v -bind 和 v -on 的语法糖
  • 在一个组件上应用 v -model,默认会为组件绑定名为 value 的 prop 和名为 input 的事件
nextTick 的实现原理是什么?
  • 在下次 DOM 更新循环完结之后执行提早回调,在批改数据之后立刻应用 nextTick 来获取更新后的 DOM。
  • nextTick 次要应用了 宏工作 微工作
  • 依据执行环境别离尝试采纳 Promise、MutationObserver、setImmediate,如果以上都不行则采纳 setTimeout 定义了一个异步办法,屡次调用 nextTick 会将办法存入队列中,通过这个异步办法清空以后队列。
Vue 不能检测数组的哪些变动?Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题?
  • Vue 不能检测以下数组的变动:
  • 第一类问题
// 法一:Vue.set Vue.set(vm.items, indexOfItem, newValue) // 法二:Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
  • 第二类问题,可应用 splice:
vm.items.splice(newLength)
  • 当你利用索引间接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 当你批改数组的长度时,例如:vm.items.length = newLength
  • 解决办法:
  • vm.$set 的实现原理是:
  • 如果指标是数组,间接应用数组的 splice 办法触发相应式;
  • 如果指标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式解决,则是通过调用 defineReactive 办法进行响应式解决(defineReactive 办法就是 Vue 在初始化对象时,给对象属性采纳 Object.defineProperty 动静增加 getter 和 setter 的性能所调用的办法)
Vue 事件绑定原理是什么?
  • 原生事件绑定是通过 addEventListener 绑定给实在元素的,组件事件绑定是通过 Vue 自定义的 $on 实现的。
说一下虚构 Dom 以及 key 属性的作用
  • 因为在浏览器中操作 DOM 是很低廉的。频繁的操作 DOM,会产生肯定的性能问题。这就是虚构 Dom 的产生起因。
  • Virtual DOM 实质就是用一个 原生的 JS 对象去形容一个 DOM 节点。是对实在 DOM 的一层形象。(也就是源码中的 VNode 类,它定义在 src/core/vdom/vnode.js 中。)
  • 虚构 DOM 的实现原理次要包含以下 3 局部:
  • 用 JavaScript 对象模仿实在 DOM 树,对实在 DOM 进行形象;
  • diff 算法 — 比拟两棵虚构 DOM 树的差别;
  • pach 算法 — 将两个虚构 DOM 对象的差别利用到真正的 DOM 树。
  • key 是为 Vue 中 vnode 的惟一标记,通过这个 key,咱们的 diff 操作能够更精确、更疾速
  • 更精确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 比照中能够防止就地复用的状况。所以会更加精确。
  • 更疾速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历形式更快
为什么不倡议用 index 作为 key?
  • 不倡议 用 index 作为 key,和没写基本上没区别,因为不论你数组的程序怎么颠倒,index 都是 0, 1, 2 这样排列,导致 Vue 会复用谬误的旧子节点,做很多额定的工作

生命周期篇

说一下你对 Vue 的生命周期的了解
  • 简略答复
  • beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
  • keep-alive 有本人独立的钩子函数 activated 和 deactivated。
  • 简单答复

| 生命周期

产生了什么

beforeCreate

created

beforeMount

mounted

beforeUpdate

updated

beforeDestroy

destroyed

activited keep-alive 专属

deactivated keep-alive 专属

Vue 中组件生命周期调用程序是什么样的?
  • 组件的调用程序都是先父后子, 渲染实现的程序是先子后父。
  • 组件的销毁操作是先父后子,销毁实现的程序是先子后父。
在什么阶段能力拜访操作 DOM?

在钩子函数 mounted 被调用前,Vue 曾经将编译好的模板挂载到页面上,所以在 mounted 中能够拜访操作 DOM。

你的接口申请个别放在哪个生命周期中?
  • 能够在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 曾经创立,能够将服务端端返回的数据进行赋值。
  • 然而举荐在 created 钩子函数中调用异步申请,因为在 created 钩子函数中调用异步申请有以下长处:
  • 能更快获取到服务端数据,缩小页面 loading 工夫;
  • ssr 不反对 beforeMount、mounted 钩子函数,所以放在 created 中有助于一致性;

路由篇

vue 路由 hash 模式和 history 模式实现原理别离是什么,他们的区别是什么?
  • hash 模式:
  • 前面 hash 值的变动,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面

  • 通过监听 hashchange 事件能够晓得 hash 产生了哪些变动,而后依据 hash 变动来实现更新页面局部内容的操作。
  • history 模式:
  • history 模式的实现,次要是 HTML5 规范公布的两个 API,pushState 和replaceState,这两个 API 能够在扭转 url,然而不会发送申请。这样就能够监听 url 变动来实现更新页面局部内容的操作
  • 区别
  • url 展现上,hash 模式有“#”,history 模式没有
  • 刷新页面时,hash 模式能够失常加载到 hash 值对应的页面,而 history 没有解决的话,会返回 404,个别须要后端将所有页面都配置重定向到首页路由
  • 兼容性,hash 能够反对低版本浏览器和 IE。
路由懒加载是什么意思?如何实现路由懒加载?
  • 路由懒加载的含意:把不同路由对应的组件宰割成不同的代码块,而后当路由被拜访的时候才加载对应组件
  • 实现:联合 Vue 的异步组件和 Webpack 的代码宰割性能
  • 能够将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件自身)
    
const Foo = () => Promise.resolve({ /* 组件定义对象 */})
  • 2. 在 Webpack 2 中,咱们能够应用动静 import 语法来定义代码分块点 (split point)
    
import('./Foo.vue') // 返回 Promise
  • 联合这两者,这就是如何定义一个可能被 Webpack 主动代码宰割的异步组件
const Foo = () => import('./Foo.vue') const router = new VueRouter({routes: [ { path: '/foo', component: Foo} ]})
  • 应用命名 chunk,和 webpack 中的魔法正文就能够把某个路由下的所有组件都打包在同个异步块 (chunk) 中
chunkconst Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
Vue-router 导航守卫有哪些
  • 全局前置 / 钩子:beforeEach、beforeResolve、afterEach
  • 路由独享的守卫:beforeEnter
  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
    • *

进阶篇

说说 vue 和 react 的异同
  • 应用 Virtual DOM
  • 提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。
  • 将注意力集中放弃在外围库,而将其余性能如路由和全局状态治理交给相干的库。
  • 在 React 利用中,当某个组件的状态发生变化时,它会以该组件为根,从新渲染整个组件子树(除非应用 PureComponent/shouldComponentUpdate),在 Vue 利用中,组件的依赖是在渲染过程中主动追踪的,所以零碎能准确通晓哪个组件的确须要被重渲染
  • 在 React 中,一切都是 JavaScript。不仅仅是 HTML 能够用 JSX 来表白,当初的潮流也越来越多地将 CSS 也纳入到 JavaScript 中来解决
  • Vue 的路由库和状态治理库都是由官网保护反对且与外围库同步更新的。React 则是抉择把这些问题交给社区保护,因而创立了一个更扩散的生态系统,所以有更丰盛的生态系统
  • Vue 提供了 CLI 脚手架,能让你通过交互式的脚手架疏导非常容易地构建我的项目。你甚至能够应用它疾速开发组件的原型。React 在这方面也提供了 create-react-app,然而当初还存在一些局限性
  • React Native 能使你用雷同的组件模型编写有本地渲染能力的 APP,Vue 和 Weex 会进行官网单干,Weex 是阿里巴巴发动的跨平台用户界面开发框架,同时也正在 Apache 基金会进行我的项目孵化,另一个抉择是 NativeScript-Vue,一个用 Vue.js 构建齐全原生利用的 NativeScript 插件
什么是 mixin?
  • Mixin 使咱们可能为 Vue 组件编写可插拔和可重用的性能。
  • 如果你心愿再多个组件之间重用一组组件选项,例如生命周期 hook、办法等,则能够将其编写为 mixin,并在组件中简略的援用它。
  • 而后将 mixin 的内容合并到组件中。如果你要在 mixin 中定义生命周期 hook,那么它在执行时将优化于组件自已的 hook。
在 Vue 实例中编写生命周期 hook 或其余 option/properties 时,为什么不应用箭头函数?
  • 箭头函数自已没有定义 this 上下文中。
  • 当你在 Vue 程序中应用箭头函数 (=>) 时,this 关键字病不会绑定到 Vue 实例,因而会引发谬误。所以强烈建议改用规范函数申明。
Vue 模版编译原理晓得吗,能简略说一下吗?

简略说,Vue 的编译过程就是将 template 转化为 render 函数的过程。会经验以下阶段(生成 AST 树 / 优化 /codegen):

  • 首先解析模版,生成 AST 语法树(一种用 JavaScript 对象的模式来形容整个模板)。应用大量的正则表达式对模板进行解析,遇到标签、文本的时候都会执行对应的钩子进行相干解决。
  • Vue 的数据是响应式的,但其实模板中并不是所有的数据都是响应式的。有一些数据首次渲染后就不会再变动,对应的 DOM 也不会变动。那么优化过程就是深度遍历 AST 树,依照相干条件对树节点进行标记。这些被标记的节点 (动态节点) 咱们就能够跳过对它们的比对,对运行时的模板起到很大的优化作用。
  • 编译的最初一步是将优化后的 AST 树转换为可执行的代码。
diff 算法说一下
  • 同级比拟,再比拟子节点
  • 先判断一方有子节点一方没有子节点的状况(如果新的 children 没有子节点,将旧的子节点移除)
  • 比拟都有子节点的状况(外围 diff)
  • 递归比拟子节点
说说你对 keep-alive 组件的理解
  • keep-alive 是 Vue 内置的一个组件,能够使被蕴含的组件保留状态,防止从新渲染,其有以下个性:
  • 个别联合路由和动静组件一起应用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都反对字符串或正则表达式,include 示意只有名称匹配的组件会被缓存,exclude 示意任何名称匹配的组件都不会被缓存,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
说说你对 SSR 的理解
  • SSR 也就是服务端渲染,也就是将 Vue 在客户端把标签渲染成 HTML 的工作放在服务端实现,而后再把 html 间接返回给客户端
  • SSR 的劣势
  • 更好的 SEO
  • 首屏加载速度更快
  • SSR 的毛病
  • 开发条件会受到限制,服务器端渲染只反对 beforeCreate 和 created 两个钩子
  • 当咱们须要一些内部扩大库时须要非凡解决,服务端渲染应用程序也须要处于 Node.js 的运行环境
  • 更多的服务端负载
你都做过哪些 Vue 的性能优化?
  • 编码阶段
  • 尽量减少 data 中的数据,data 中的数据都会减少 getter 和 setter,会收集对应的 watcher
  • v-if 和 v -for 不能连用
  • 如果须要应用 v -for 给每项元素绑定事件时应用事件代理
  • SPA 页面采纳 keep-alive 缓存组件
  • 在更多的状况下,应用 v -if 代替 v -show
  • key 保障惟一
  • 应用路由懒加载、异步组件
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表滚动到可视区域动静加载
  • 图片懒加载
  • SEO 优化
  • 预渲染
  • 服务端渲染 SSR
  • 打包优化
  • 压缩代码
  • Tree Shaking/Scope Hoisting
  • 应用 cdn 加载第三方模块
  • 多线程打包 happypack
  • splitChunks 抽离公共文件
  • sourceMap 优化
  • 用户体验
  • 骨架屏
  • PWA
  • 还能够应用缓存 (客户端缓存、服务端缓存) 优化、服务端开启 gzip 压缩等。
vue2.x 中如何监测数组变动?
  • 应用了函数劫持的形式,重写了数组的办法,Vue 将 data 中的数组进行了原型链重写,指向了本人定义的数组原型办法,当调用数组 api 时,能够告诉依赖更新。
  • 如果数组中蕴含着援用类型,会对数组中的援用类型再次递归遍历进行监控。这样就实现了监测数组变动。
说说你对 SPA 单页面的了解,它的优缺点别离是什么?
  • SPA(single-page application)仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载实现,SPA 不会因为用户的操作而进行页面的从新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,防止页面的从新加载。
  • 长处:
  • 用户体验好、快,内容的扭转不须要从新加载整个页面,防止了不必要的跳转和反复渲染;
  • 基于下面一点,SPA 绝对对服务器压力小;
  • 前后端职责拆散,架构清晰,前端进行交互逻辑,后端负责数据处理;
  • 毛病:
  • 首次加载耗时多:为实现单页 Web 利用性能及显示成果,须要在加载页面的时候将 JavaScript、CSS 对立加载,局部页面按需加载;
  • 后退后退路由治理:因为单页利用在一个页面中显示所有的内容,所以不能应用浏览器的后退后退性能,所有的页面切换须要本人建设堆栈治理;
  • SEO 难度较大:因为所有的内容都在一个页面中动静替换显示,所以在 SEO 上其有着人造的弱势。
对于行将到来的 vue3.0 个性你有什么理解的吗?
  • 监测机制的扭转
  • 3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言笼罩的反馈性跟踪。
  • 打消了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限度:
  • 只能监测属性,不能监测对象
  • 检测属性的增加和删除;
  • 检测数组索引和长度的变更;
  • 反对 Map、Set、WeakMap 和 WeakSet。
  • 模板
  • 模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会从新渲染,而 3.0 把作用域插槽改成了函数的形式,这样只会影响子组件的从新渲染,晋升了渲染的性能。
  • 同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来不便习惯间接应用 api 来生成 vdom。
  • 对象式的组件申明形式
  • vue2.x 中的组件是通过申明的形式传入一系列 option,和 TypeScript 的联合须要通过一些装璜器的形式来做,尽管能实现性能,然而比拟麻烦。
  • 3.0 批改了组件的申明形式,改成了类式的写法,这样使得和 TypeScript 的联合变得很容易
  • 其它方面的更改
  • 反对自定义渲染器,从而使得 weex 能够通过自定义渲染器的形式来扩大,而不是间接 fork 源码来改的形式。
  • 反对 Fragment(多个根节点)和 Protal(在 dom 其余局部渲染组建内容)组件,针对一些非凡的场景做了解决。
  • 基于 tree shaking 优化,提供了更多的内置性能。
退出移动版