vue基础知识点

说说你对MVVM的理解

  • Model-View-ViewModel的缩写,Model代表数据模型,View代表UI组件,ViewModel将Model和View关联起来。

  • 数据会绑定到viewModel 层并自动将数据渲染到页面中,视图变化时候会通知viewModel层更新数据。

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,从而使他关联的组件重新渲染。vue基础知识点_第1张图片

  • 深入理解:

    • 监听器 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 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

    • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

    • 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化

    • 主要包括以下几个模块:

      • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。

      • Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。

      • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。

      • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

      • Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

什么情况下使用 Vuex?

  • 如果应用够简单,最好不要使用 Vuex,一个简单的 store 模式即可

  • 需要构建一个中大型单页应用时,使用Vuex能更好地在组件外部管理状态

组件中的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 不能检测以下数组的变动:

  1. 第一类问题

// 法一:

Vue.set Vue.set(vm.items, indexOfItem, newValue)

// 法二:

Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue) 复制代码

   2. 第二类问题,可使用 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 对象来获取对应节点,比遍历方式更快

你的接口请求一般放在哪个生命周期中?

  • 可以在钩子函数 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-router 导航守卫有哪些

  • 全局前置/钩子:beforeEach、beforeResolve、afterEach

  • 路由独享的守卫:beforeEnter

  • 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

说说你对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 上其有着天然的弱势。

你可能感兴趣的:(vue)