vue面经

1. 单页面应用

单页应用程序 (SPA) 是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。单页面应用的框架有angular、react、vue(vue是通过vue-router来实现的)。SPA不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用 JavaScript 动态的变换HTML的内容,从而实现UI与用户的交互。由于避免了页面的重新加载,SPA 可以提供较为流畅的用户体验。
优点

  • 异步获取数据,页面转换流畅,不刷新,不会闪烁屏幕
  • 减轻服务器压力,后端只管数据,展示逻辑和页面合成由客户端完成

缺点

  • 首屏加载更慢,需要在第一次加载所有组件,并向服务器请求数据
  • 不利于SEO(Search Engine Optimization)

2. MVVM(Model–view–viewmodel)

模型是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。
视图就像在MVC和MVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观(UI)。
视图模型
【解释一】是暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器之间进行通信。
【解释二】将View与Model统一管理,自动同步修改(在Vue中相当于new Vue()这个对象)
ViewModel包含两大子系统:
1、响应系统,实现双向数据绑定
2、虚拟DOM树,创建vue时,通过扫描DOM树仅提取了可能变化的元素和属性,组成的一棵极其精简的虚拟DOM树。(封装了重复性的DOM增删改查操作?)
在响应系统收到数据变化时,通知虚拟DOM树,受到影响的元素进行更新然后重新渲染到视图

3. Vue2的响应式原理

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过**Object.defineProperty()**来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

第一步:需要observe的data对象进行递归遍历,包括子属性对象的属性,利用Object.defineProperty()都加上 setter和getter。这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者Watcher,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
双向绑定原理

4. vue组件中data为什么是函数

因为组件是可以复用的,如果data是对象的话,会造成(同一组件a的复用a1,a2)一个组件a1中数据变化,另一个组件a2中数据也会随之变化,所以在组件中数据作为一个函数返回一个对象,可以隔离组件的数据

5. v-model的原理

第3点

6. v-if v-show的区别

v-if:动态的向DOM树内添加或者删除DOM元素
v-show:是否显示该元素(display属性的none、visibility的切换)

7. computed、watch、method使用方法和区别

这三者在一些情况中都能实现相同的效果

  • methods中的方法,需要绑定事件,函数的方式funcName()调用,每次调用都会重新计算所有数据(data中的所有属性),消耗较大,性能较差
  • computed中的方法,自动监测数据变化,自动更新,以属性的方式funcName引用,在多个数据影响一个数据的时候使用,如果计算结果没有变化,直接引用之前的缓存
  • watch中的方法,当依赖的 data 的数据变化,执行回调,以数据中心的属性名作为函数方法名。在方法中会传入 newVal 和 oldVal。如果你需要在某个数据变化时做一些事情,使用watch。
methods:{
	funcName(){
		return "123"
	}
}
computed:{
//以属性的方式调用,就像data中的属性一样使用
	computeFullName(){
		return this.firstName+this.lastName
	}
}
watch:{
//以data中的属性名作为方法名,在该属性发生变化时,完成一些事
	firstName(newVal,oldVal){
		console.log(newVal,olVal);
	}
}

8. vue的生命周期

这篇文章说的比较详细-vue实例化过程
初始化部分:

  1. berforeCreate:已经完成属性合并、生命周期方法、组件事件系统等。
  2. created:已完成数据观测、属性方法的运算,watch、event事件回调,$el属性还不可见
  3. beforeMount:挂载之前,已完成指令、模板等编译为html以及相关渲染函数首次被调用
  4. mounted:挂载成功之后,根容器内容被替换为被编译之后的html
    更新部分:
  5. beforeUpdate:已完成数据更新,但还未更新视图
  6. updated:Dom组件已更新完毕
    销毁部分:
  7. beforeDestroy:vm.$destroy()被调用
  8. destroyed:拆除子组件和事件监听

9. 父子组件生命周期顺序

创建过程:
父组件先创建,子组件创建挂载,父组件挂载
所以在父组件mounted中请求数据,子组件是拿不到的
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
更新过程:
父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

10. Vue组件之间的通信方式

  1. props/$emit(父子)
    父传子,父组件中给子组件v-on要传递的数据,子组件中props接收
    子传父,父组件中给子组件@methodName=“func”,并在父组件中定义func方法,子组件中用this.$emit(“methodName”,parameter)调用

  2. $children/$parent

  3. privode/reject(祖先子孙)
    祖先组件中通过provide来提供变量, 然后再子孙组件中通过inject来注入变量。

//父组件中添加
provide: {
      for: "demo"//要传的数据
    },
// 子组件中添加
inject: ['for'],//要接受的数据
  1. ref、$refs(父子)
    父组件中调用子组件的属性、方法
//子组件中定义方法methodName
//父组件中
<component-a ref="comA"></component-a>
//调用这个子组件中的方法
this.$refs.comA.methodName(parameter);
//或者
//this.$refs["comA"].methodName(parameter);

  1. eventBus事件总线
    传值给eventBus用:
    eventBus.$emit(“b-msg”, this.b);
    接收B组件的数据:
eventBus.$on("b-msg", function (b) {
     this.b = b;
}.bind(this));
  1. vuex
  2. localStorage/sessionStorage
  3. $attrs/$listeners(父子)
    $attrs:获取父组件中的属性且未在子组件props中声明
    $listeners:获取父组件中的方法且未在父组件中使用.native声明
  4. 插槽slot(父子)
    $attrs 里存放的是父组件中绑定的非 Props 属性,$listeners里存放的是父组件中绑定的非原生事件。

11. Vue单向数据流

单向数据流
v-model是通过definedProperty来实现从视图到模型的更新的,vue本身是单向数据流

12. Keep-alive组件级缓存

跳转到详情页面时,需要保持列表页的滚动条的深度,等返回的时候依然在这个位置,这样可以提高用户体验。对于这种“页面缓存”的需求,我们可以使用keep-alive组件来解决这个需求。详见官网

keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

使用方法

<keep-alive include='include_components' exclude='exclude_components'>
  <component>
    <!-- 该组件是否缓存取决于include和exclude属性 -->
  </component>
</keep-alive>

参数解释
include - 字符串或正则表达式,只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存
include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。

使用示例

方式一(基本用法)
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
<keep-alive>


<!-- 逗号分隔字符串,只有组件a与b被缓存。 -->
<keep-alive include="a,b">
  <component></component>
</keep-alive>

<!-- 正则表达式 (需要使用 v-bind,符合匹配规则的都会被缓存) -->
<keep-alive :include="/a|b/">
  <component></component>
</keep-alive>

<!-- Array (需要使用 v-bind,被包含的都会被缓存) -->
<keep-alive :include="['a', 'b']">
  <component></component>
</keep-alive>

其他示例
  <!--传入include数组,include属性表示要缓存的组件名(即组件定义时的name属性),可以存在vuex中-->
  <keep-alive :include="keepAliveComponents">
    <router-view></router-view>
  </keep-alive>

13. Slot插槽

相当于一种父组件传值给子组件的一种方式,可以给插槽取名字,传递多个插槽

父组件中加入子组件
<child>
这里是要传递给子组件的内容,可以使一段html代码或数据
<p slot=""slotName">带名字的插槽</p>
</child>
====================
子组件中用slot显示传过来的数据
<slot>(这里可以放默认值,没有传参的时候显示默认值)<slot>
相当于下面这段传进来的参数
这里是要传递给子组件的内容,可以使一段html代码或数据
===================
<slot name="slotName"></slot>
相当于
<p>带名字的插槽</p>


vue2.6更新后使用v-slot
详见官网
直接在父组件引用子组件的地方使用

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

14. Vue2检测数组或对象的变化

详见官网
1、vue能够监听数组变化的场景
【1】通过赋值的形式改变正在被监听的数组;
【2】通过数组的push、pop、splice(index,num,val)、shift、unshift的形式改变正在被监听的数组;

2、vue无法监听的数组变化的场景
【1】通过数组索引改变数组元素的值;
【2】改变数组的长度;

3、VUE解决无法监听数组变化的方法
【1】this.$set(arr, index, newVal);
【2】通过splice(index,num,val),push(num),pop(),shift(),unshift(val)修改数组
【3】使用临时变量作为中转,重新赋值数组;

二、vue监听对象的变化
1、vue能够监听到对象变化的场景
【1】通过直接赋值的场景。eg:watchObj = {name:“zyk”}

2、vue无法监听到对象变化的场景
【1】对象的增加、删除、修改无法被vue监听到

3、VUE解决无法监听对象变化的方法
【1】使用 this.$set(object, key, value)(vue 无法监听 this.set 修改原有属性)
【2】使用Object.assign(),直接赋值的原理;(推荐使用)Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

注意:vue3中双向绑定已经不是使用Object.defineProperty来实现,而是改为Proxy代理对象来实现,修复了数组、对象中属性双向绑定的一些问题

15. 虚拟DOM原理、优缺点、diff算法

参考
缺点:首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

React虚拟DOM
利用js的对象模拟dom树。当state中的值的时候,React会去调用render()方法来重新渲染整个组件的UI,但是如果我们真的去操作这么大量的dom,性能堪忧。所以react实现了一个virtural dom,组件的真实dom结构与virtural dom结构有一个映射关系,虚拟dom应用了diff算法,当render()去重新渲染组件的时候,diff算法会找到需要变更的dom,然后再把修改更新到浏览器上的真实dom上,所以react并不是渲染了整个DOM树,虚拟DOM就是js的对象,所以比直接操作DOM快

16. Vue中key的作用

参考1
参考2
key是vue中vnode的唯一标志,可以让diff算法更准确更快速。vue的diff算法可以概括为:oldCh和newCh各有两个头尾的变量 oldStartIndex、oldEndIndex、newStartIndex、newEndIndex,会将新节点和旧节点进行两两比较,一共有四种比较方式,如果四种比较都没有匹配且设置了key就会用key进行比较,遍历过程中会往中间靠,一旦startIndex>endIndex,表明old和newCh中至少有一个已经遍历完成,遍历结束
更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,源码如下:

    function createKeyToOldIdx (children, beginIdx, endIdx) {  
      let i, key  const map = {}  
      for (i = beginIdx; i <= endIdx; ++i) {
        key = children[i].key    
        if (isDef(key)) map[key] = i
      }  
      return map
    }

17. nextTick的原理

它可以在DOM更新完毕之后执行一个回调,确保我们操作的是更新后的DOM。

Vue.nextTick(function () {
// DOM 更新了
})
  • vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
  • microtask因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
  • 因为兼容性问题,vue不得不做了microtask向macrotask的降级方案

18. Vuex

state:存储的一些状态
getters: store 的计算属性,获取state中的属性
mutations:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
actions:异步的操作方法
modules

dispatch和commit的区别:
dispatch:异步操作,this.store.$dispatch(‘mutation方法名’,value)
commit:同步操作,this.store.$commit(‘mutation的方法名’,value)

19. vue-router的两种模式

hash:(带#)利用“hashchange”事件监听,监听#后面的字符串(window.loaction.hash)的改变,每次hash改变,都会在浏览器访问记录中增加一个记录
history:利用h5的方法window.history.pushState(stateObject,title,url)和window.history.replaceState(stateObject.title,url)这两个方法,修改历史栈之后,虽然url改变了,但是浏览器不会立即发送请求

20. vue-router中的导航钩子

全局导航守卫:

router.beforeEach((to,from,next)=>{})
router.beforeResolve((to,from,next)=>{})
router.beforeAfter((to,from)=>{})

组件内的守卫:

beforeRouteEnter((to,from,next)=>{})
beforeRouteUpdate((to,from,next)=>{})
beforeRouteLeave((to,from,next)=>{})

21. MutationObserver

MutationObserver是HTML5新增的属性,用于监听DOM修改事件,能够监听到节点的属性、文本内容、子节点等的改动

22. 对Vue.js的template编译的理解

通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)

23. vue生态

vuex 是核心
vue-router 单页面应用中,是路径之间的切换,也就是组件的切换
vue-devtools 基于Chrome的调试工具
webpack 完成资源的合并和打包
vue-cli 脚手架
iview、element 等组件库

vue全家桶

Vue+Vue-router+Vuex+axios

24. vuex(vuex是什么?怎么使用?哪种功能场景使用它?)

vuex教程
vuex是vue生态系统中的状态管理。在main.js引入store,注入,新建一个目录store,…… export 等,常用的场景有:单页应用中,组件之间的状态,音乐播放、登录状态、加入购物车等等。
1、state,驱动应用的数据源;
2、view,以声明方式将 state 映射到视图;
3、actions,响应在 view 上的用户输入导致的状态变化。
vuex核心:
state
getters
mutations
actions
modules
要知道每一个的作用和使用

在模块中getter和mutation和action中怎么访问全局的state和getter

getter通过rootState, rootGetters
mutation不能访问全局的state和getter
action中context有context.rootState context.rootGetters

RESTful API

是一个api的标准,无状态请求。请求的路由地址是固定的,如果是tp5则先路由配置中把资源路由配置好。标准方法有:.get、.post、 .put、.delete。

vue ssr服务器端渲染

vue ssr指南
将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。

vue.cli项目中src中每个目录的含义

assets文件夹是放静态资源;components是放组件;router是定义路由相关的配置;view视图;app.vue是一个应用主组件;main.js是入口文件等等
脚手架中文件目录结构

25. Vue中key的作用

用于唯一表示vnode,可以更高效的更新虚拟DOM,可以使diff算法更加高效和准确

26. 为什么Vue组件中的data中用return 返回所有数据

27. diff算法

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值