前端面试准备(Day5)

1. Vuex的使用方法。

  Vuex是一个专门为vue.js设计的集中式状态管理架构

Vuex的五个核心,gette:stater,mutations,actions,module

  1)state:定义我们所需要管理的数组、对象、字符串等等

  2)getter:可以对state中的成员加工后传递给外界

  3)mutations:mutations是操作state数据的方法的集合,比如对该数据的修改、增加、删除等等。  

4)action :由于直接在mutation方法中进行异步操作,将会引起数据失效。所以提供了Actions来专门进行异步操作,最终提交mutation方法。

  5)modules: 当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将 store 分割成模块(module)

    

2.mvc和mvvm区别是什么?

1)mvc:model-view-controller, 是一种设计模式,是一种业务逻辑。

      M:model(业务模型)

V:view(用户视图)

C:controller(控制器)

2)mvvm:Model–View–ViewModel

3)  区别:它实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变。

3.Vue双向绑定原理。

实现数据的双向绑定,,通过数据劫持和消息的订阅与发布来实现。首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专收集和通知订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析相关指令(如v-model,v-on),对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数。此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。

因此接下去我们执行以下3个步骤,实现数据的双向绑定

(1)实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

(2)实现一个订阅者Watcher,每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

(3)实现一个解析器Compile,可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。

数据劫持和消息的订阅和发布

1.通过observer对所有的属性进行数据劫持监听,核心 object.defineProperty(get、set),递归

2.HTML解析,替换DOM内数据。解析器Compile,

3.依赖-收集和通知订阅者

4.watcher

4.Vue组件间通信方式有哪些?

  总结:

父子关系的组件数据传递选择 props  与 $emit进行传递,也可选择ref

兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递

祖先与后代组件数据传递可选择attrs与listeners或者 Provide与 Inject

复杂关系的组件数据传递可以通过vuex存放共享的变量

  1)props:父->子

2)$emit 触发自定义事件:子->父

3)EventBus :$emit/$on:这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级

  this.$emit(事件名,数据);//发送数据

  this.$on(事件名,data => {});//接收数据

4)Vuex

5)使用 ref: 这两种方法的弊端是,无法在跨级或兄弟间通信。

6)$attrs (v-bind:$attrs)与 (v-on)$listeners: 祖先传递数据给子孙,(v-bind="$attrs" v-on="$listeners")

7)Provide 与 Inject: 在祖先组件定义provide属性,返回传递的值

在后代组件通过inject属性接收组件传递过来的值

8) this.$parent或this.$root: 祖先传递数据给子孙

5.computed和watch区别是什么?

计算属性computed:具有响应式的返回值

1)可以从组件数据中派生出新的数据,最常见的是设置一个函数,返回计算之后的结果

2)支持缓存,只有依赖数据发生改变,才会重新进行计算

3)不支持异步,当computed内有异步操作时无效,无法监听数据的变化

侦听属性watch:侦测变化,执行回调

1)不支持缓存,数据变,直接会触发相应的操作;

2)watch没有返回值,但支持异步

选择方案:看是否要派生新值,基本能用计算属性就用计算属性

6.v-for和v-if同时使用有问题吗?

v-for比v-if优先级高,所以使用的话,每次v-for都会执行v-if,造成不必要的计算,影响性能,尤其是当之需要渲染很小一部分的时候。

7.前端路由原理。

  前端不同页面的状态管理器,可以不向后台发送请求而直接通过前端技术实现多个页面的效果。URL 与 UI 之间的映射关系,这种映射是单向的

1)hash 实现

hash 是 URL 中 hash (#) 及后面的那部分,常用作锚点在页面内进行导航,改变 URL 中的 hash 部分不会引起页面刷新,通过 hashchange 事件监听 URL 的变化,改变 URL 的方式只有这几种:通过浏览器前进后退改变 URL、通过<a>标签改变 URL、通过window.location改变URL,这几种情况改变 URL 都会触发 hashchange 事件

2)history 实现

history 提供了 pushState 和 replaceState 两个方法,这两个方法改变 URL 的 path 部分不会引起页面刷新,history 提供类似 hashchange 事件的 popstate 事件,但 popstate 事件有些不同:通过浏览器前进后退改变 URL 时会触发 popstate 事件,通过pushState/replaceState或<a>标签改变 URL 不会触发 popstate 事件。好在我们可以拦截 pushState/replaceState的调用和<a>标签的点击事件来检测 URL 变化,所以监听 URL 变化可以实现,只是没有 hashchange 那么方便。

8.比较一下history和hash这两种路由。

1)history

1.地址干净,美观

2.兼容性比hash略差

3.应用部署会出现404问题,需要后端解决

      2)hash

     1.地址中带有#,不美观

     2.兼容性较好

     3.若将地址通过第三方手机app分享,若app校验严格,地址会被标记不合法

9. Vue diff算法。

(8条消息) vue核心面试题:diff算法_王三六的博客-CSDN博客_diff算法面试题

1)特点  

1.比较只会在同层级进行, 不会跨层级比较

2.在diff比较的过程中,循环从两边向中间比较

2)方式:递归+双指针

  1.判断是否是同一元素,不是同一个元素,直接替换

  2.是同一个元素

比对属性->比对儿子(老有儿子,新没有儿子;新的有儿子,老的没有儿子;都是文本;都有儿子)->双指针比较->对比查找进行复用

得分点 patch、patchVnode、updateChildren、vue优化时间复杂度为O(n)

标准回答 Diff算法比较过程

第一步:patch函数中对新老节点进行比较 如果新节点不存在就销毁老节点 如果老节点不存在,直接创建新的节点 当两个节点是相同节点的时候,进入 patctVnode 的过程,比较两个节点的内部

第二步:patchVnode函数比较两个虚拟节点内部 如果两个虚拟节点完全相同,返回 当前vnode 的children 不是textNode,再分成三种情况 - 有新children,没有旧children,创建新的 - 没有新children,有旧children,删除旧的 - 新children、旧children都有,执行`updateChildren`比较children的差异,这里就是diff算法的核心 当前vnode 的children 是textNode,直接更新text

第三步:updateChildren函数子节点进行比较。

第一步 头头比较。若相似,旧头新头指针后移(即 `oldStartIdx++` && `newStartIdx++`),真实dom不变,进入下一次循环;不相似,进入第二步。

第二步 尾尾比较。若相似,旧尾新尾指针前移(即 `oldEndIdx--` && `newEndIdx--`),真实dom不变,进入下一次循环;不相似,进入第三步。

 第三步 头尾比较。若相似,旧头指针后移,新尾指针前移(即 `oldStartIdx++` && `newEndIdx--`),未确认dom序列中的头移到尾,进入下一次循环;不相似,进入第四步。

第四步 尾头比较。若相似,旧尾指针前移,新头指针后移(即 `oldEndIdx--` && `newStartIdx++`),未确认dom序列中的尾移到头,进入下一次循环;不相似,进入第五步。               

第五步 若节点有key且在旧子节点数组中找到sameVnode(tag和key都一致),则将其dom移动到当前真实dom序列的头部,新头指针后移(即 `newStartIdx++`);否则,vnode对应的dom(`vnode[newStartIdx].elm`)插入当前真实dom序列的头部,新头指针后移(即 `newStartIdx++`)。

但结束循环后,有两种情况需要考虑: - 新的字节点数组(newCh)被遍历完(`newStartIdx > newEndIdx`)。那就需要把多余的旧dom(`oldStartIdx -> oldEndIdx`)都删除,上述例子中就是`c,d`; - 新的字节点数组(oldCh)被遍历完(`oldStartIdx > oldEndIdx`)。那就需要把多余的新dom(`newStartIdx -> newEndIdx`)都添加

10.Vue的虚拟DOM原理,优缺点是什么?

  1)原理:

     用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;

diff 算法 — 比较两棵虚拟 DOM 树的差异;

pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树

  2)好处:

1.具备跨平台的优势–由于 Virtual DOM 是以 JavaScript 对象为基础而不依赖真实平台环境,所以使它具有了跨平台的能力,比如说浏览器平台、Weex、Node 等。

2.操作 DOM 慢,js运行效率高。我们可以将DOM对比操作放在JS层,提高效率。运用patching算法来计算出真正需要更新的节点,最大限度地减少DOM操作,从而显著提高性能。Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。

3.提升渲染性能 Virtual DOM的优势不在于单次的操作,而是在大量、频繁的数据更新下,能够对视图进行合理、高效的更新

11.Vue的keep-alive使用及原理。

  keep-alive是vue.js的内置组件,它能够把不活动的组件的实例保存在内存中,而不是直接的销毁,它是一个抽象组件,不会被渲染到真实DOM中,也不会出现在父组件链中。 它提供了exclude和include两个属性,允许组件有条件的缓存。

  1)props

    include: patternTypes, // 缓存白名单

    exclude: patternTypes, // 缓存黑名单

2)created () {

     this.cache = Object.create(null) // 缓存组件

3)destroyed ()// 删除所有的缓存

4)mounted () {// 实时监听黑白名单的变动

5)render()

1.获取keep-alive包裹着的第一个子组件对象及其组件名;

2.根据设定的黑白名单(如果有)进行条件匹配,决定是否缓存。不匹配,直接返回组件实例(VNode),否则执行第三步;

    3.根据组件ID和tag生成缓存Key,并在缓存对象中查找是否已缓存过该组件实例。如果存在,直接取出缓存值并更新该key在this.keys中的位置(更新key的位置是实现LRU置换策略的关键),否则执行第四步;

    4.在this.cache对象中存储该组件实例并保存key值,之后检查缓存的实例数量是否超过max的设置值,超过则根据LRU置换策略删除最近最久未使用的实例(即是下标为0的那个key。

  5.将该组件实例的keepAlive属性值设置为true

12.Vue父子组件生命周期触发顺序是怎样的?

  加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

13.vue生命周期t

beforeCreate created

beforeMount mounted

beforeUpdate updated

beforeDestroy destroyed

keep-alive组件独有

activated deactivated

14.Vue.nextTick的实现?

  vue中的nextTick主要用于处理数据动态变化后,DOM还未及时更新的问题,用nextTick就可以获取数据更新后最新DOM的变化。

1)是什么:等待下一次DOM更新刷新的工具方法。在修改数据之后立即使用这个方法,获取更新后的 DOM

2)当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新。nextTick本质是为了利用 JavaScript 的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列。

3)使用场景

created()函数中想要用到DOM

  响应式数据变化后获取DOM更新后的状态,比如希望获取列表更新后的高度

15.v-if和v-show的区别

  (1)v-if和v-show用于视图层进行条件判断视图展示

 (2)v-if的原理是根据判断条件来动态的进行增删DOM元素,v-show是根据判断条件来动态的进行显示和隐藏元素,频繁的进行增删DOM操作会影响页面加载速度和性能,由此我们可以得出结论:当您的项目程序不是很大的时候,v-if和v-show都可以用来进行判断展示和隐藏(这种场景使用v-if只是影响不大,并不是没有影响);当您的项目程序比较大的时候,不推荐使用v-if来进行判断展示和隐藏,推荐使用v-show;

(3)只有v-if能和v-else连用进行分支判断,v-show是不能和v-else连用的,如果出现多种条件场景的情况下,可以使用v-if来进行判断

16.常用VUE内置指令

v-on v-if v-else v-show v-for v-bind v-model

  1)v-once

v-once仅渲染指定组件或元素一次,并跳过未来对其的更新。如果编译器发现元素或者组件上面有v-once时,就会将首次的计算结果存入缓存对象,组件再次渲染时从中获取。

2)v-pre

v-pre可以用来阻止预编译,有v-pre指令的标签内部的内容不会被编译,会原样输出。

3)v-cloak

   v-cloak来解决屏幕闪动的问题,当网络较慢,网页还在加载 Vue.js ,而导致 Vue 来不及渲染,这时页面就会显示出 Vue 源代码

17.data为什么是一个函数

   vue中的组件是被复用的,如果vue中的data是一个对象类型,对象类型的数据是按引用传值的,这就会导致所有组件的实例都共享同一份数据,这是不对的,我们要的是每个组件实例都是独立的。为了解决对象类型数据共享的问题,我们需要将 data 定义成一个函数,每个实例需要通过调用函数生成一个独立的数据对象

18.vue2和vue3的区别

1. Composition API

Vue2 是选项API(Options API),一个逻辑会散乱在文件不同位置(data、props、computed、watch、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。

Vue3 组合式API(Composition API)则很好地解决了这个问题,可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。

2.响应式原理

Vue2 响应式原理基础是 Object.defineProperty,监听某个属性的变化,无法监听对象或数组新增、删除的元素,针对常用数组原型方法push、pop、shift、unshift、splice、sort、reverse进行了重写处理;提供Vue.set监听对象/数组新增属性;Vue3 响应式原理基础是 Proxy,通过第2个参数 handler 拦截目标对象的行为。

3. 生命周期

对于生命周期来说,整体上变化不大,只是大部分生命周期钩子名称上 + “on”,功能上是类似的。在Vue3 组合式API中使用生命周期钩子时需要先引入,而 Vue2 在选项API(Options API)中可以直接调用生命周期钩子,

4.多根节点

vue2中在模板中如果使用多个根节点时会报错,,Vue3 支持多个根节点,也就是 fragment。多根节点的写法是被允许的。

5.异步组件(Suspense)

Vue3 提供 Suspense 组件,允许程序在等待异步组件加载完成前渲染兜底的内容,如 loading ,使用户的体验更平滑。使用它,需在模板中声明,并包括两个命名插槽:default 和 fallback。Suspense 确保加载完异步内容时显示默认插槽,并将 fallback 插槽用作加载状态。

6.Teleport

Vue3 提供 Teleport 组件可将部分 DOM 移动到 Vue app 之外的位置。比如项目中常见的 Dialog 弹窗。

7.diff算法的优化,打包优化等

19.使用v-for时要绑定索引的原因是什么

给元素绑定上索引后它就是元素的唯一标识符。key的作用主要就是为了高效的更新虚拟DOM,使用key值,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。它也可以用于强制替换元素/组件而不是重复的使用它。

为何不推荐index作为key值:

当以数组为下标的index作为key值时,其中一个元素(例如增删改查)发生了变化就有可能导致所有的元素的key值发生改变diff算法时比较同级之间的不同,以key来进行关联,当对数组进行下标的变换时,比如删除第一条数据,那么以后所有的index都会发生改变,那么key自然也跟着全部发生改变,所以index作为key值是不稳定的,而这种不稳定性有可能导致性能的浪费,导致diff无法关联起上一次一样的数据。因此,能不使用index作为key就不使用index。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值