前端面试题汇总(理论篇二) --vue

 vue的优势有哪些?

1)轻量级框架:只关注视图层,是一个构建数据的视图集合。

2)双向数据绑定,数据操作方面更加简单

3)组件化:实现html封装和重用

4)视图、数据、结构分离:使数据更改更加简单,不需修改逻辑代码,只需操作数据

5)虚拟DOM:DOM的操作比较耗性能,不使用原生的DOM操作节点

ps:vue不利于SEO

Vue中watch和computed的区别

1、computed是计算属性;watch是监听,监听data中的数据变化。
2、computed支持缓存,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发生变化的时候,响应执行。
3、computed不支持异步,有异步操作时无法监听数据变化;watch支持异步操作。
4、computed第一次加载时就监听;watch默认第一次加载时不监听。

    immediate 组件创建时刻执行与否
    immediate: true,第一次加载时监听(默认为false)
    deep 深度监听 不推荐使用(非常的消耗性能)
    监听的属性是对象的话 不开启deep 对象子属性变化不会触发watch
    开启了deep 对象内部所有子属性变化 都会触发watch
5、computed中的函数必须调用return;watch不是。
6、使用场景:
computed:一个属性受到多个属性影响,如:购物车商品结算。
watch:一个数据影响多条数据,如:搜索数据。
数据变化响应,执行异步操作,或高性能消耗的操作,watch为最佳选择。

绑定 class 的数组用法

  • 对象方法 v-bind:class="{' orange': isRipe,'green': isNotRipe}"
  • 数组方法 V-bind:class="[class1,class2]"
  • 行内 v-bind:style="{color: color, fontSize: fontSize+'px'}"

开发中常用的指令有哪些

v-show v-if  v-html v-text v-model  v-on v-clock  v-bind

修饰符有哪些

事件修饰符

  • .stop 阻止事件继续传播
  • .prevent 阻止标签默认行为
  • .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
  • .self 只当在 event.target 是当前元素自身时触发处理函数
  • .once 事件将只会触发一次
  • .passive 告诉浏览器你不想阻止事件的默认行为

v-model 的修饰符

  • .lazy 通过这个修饰符,转变为在 change 事件再同步
  • .number 自动将用户的输入值转化为数值类型
  • .trim 自动过滤用户输入的首尾空格

vue的插槽(slot)主要分三种:

默认插槽,具名插槽,作用域插槽
vue中的插槽,指的是子组件中提供给父组件使用的一个占位符;
用标签表示,父组件可以在这个占位符中填充任何模板代码,比如HTML、组件等,填充的内容会替换掉子组件的标签(替换占位符)。

v-model 的原理

vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

text 和 textarea 元素使用 value 属性和 input 事件;

checkbox 和 radio 使用 checked 属性和 change 事件;

select 字段将 value 作为 prop 并将 change 作为事件;

以 input 表单元素为例:

<input v-model='something'>

相当于

<input v-bind:value="something" v-on:input= "something =Sevent.target.value">

如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input的事件,如下所示:

父组件:
<ModelChild v-model="message"></ModelChild>子组件:
<div>{
   
   {value}}</div>props:value:String
},
methods:{test1(){this.$emit('input','小红')},
},

Vue的生命周期

Vue实例创建到销毁的过程称为生命周期。从开始创建、初始化数据、编译模板、挂载DOM->渲染->更新->渲染、卸载等一系列过程称为vue的生命周期。

相关知识点:

1)vue生命周期总共8个阶段:创建前后、载入前后、更新前后、销毁前后

2)第一次触发会触发几个钩子:beforeCreate  created  beforeMount mounted

3)DOM渲染在哪个生命周期已经完成:mounted

4)vue中父子组件钩子的执行顺序:

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

更新:父beforeUpdate->子beforeUpdate->子updated->父updated

销毁:父beforeDestory->子beforeDestory->子destoryed->父destoryed

vue生命周期的作用

在控制整个vue实例过程中形成良好的逻辑。(生命周期中的多个事件钩子)

vue组件间的通信

1)vuex

2)eventBus

3)props/emit

4)$parent/$children

5)$attrs/$listeners

双向绑定数据的原理

Vue的数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式实现。通过Object.defineProperty()来劫持各个属性的getter/setter。修改触发了方法set方法赋值,获取触发了get方法取值,在数据发生变动时发送消息给订阅者,触发相应的回调并通过数据劫持发布消息

响应式是指组件data数据一旦发生变化,立即触发视图的更新。他是实现数据驱动视图的第一步。

vue响应式一个核心api是Object.defineProperty(). 利用Object.defineProperty重写get和set,将对象属性的赋值和获取变成函数,我们可以实现一个简单的双向绑定。

解释单向数据流和双向数据绑定

单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。要使 UI 发生变更就必须创建各种 action 来维护对应的 state

双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度。

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

因为JS本身特性带来的,如果data是一个对象,那么由于对象本身属于引用类型,当我们改变其中一个属性时,会影响到vue实例的数据。如果data作为一个函数返回一个对象,那么每个实例的data都是独立的,不会互相影响。

真实DOM和虚拟DOM

 假如一次操作中有10次更新DOM的动作,当你用传统的源生api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程;
 但是虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,通知浏览器去执行绘制工作,再进行后续操作,避免大量无谓的计算量。

Vue中key的作用

vue 中 key 值的作用可以分为两种情况来考虑:

  • 第一种情况是 v-if 中使用 key。由于 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此当使用 v-if 来实现元素切换的时候,如果切换前后含有相同类型的元素,那么这个元素就会被复用。如果是相同的 input 元素,那么切换前后用户的输入不会被清除掉,这样是不符合需求的。因此可以通过使用 key 来唯一的标识一个元素,这个情况下,使用 key 的元素不会被复用。这个时候 key 的作用是用来标识一个独立的元素。
  • 第二种情况是 v-for 中使用 key。用 v-for 更新已渲染过的元素列表时,它默认使用“就地复用”的策略。如果数据项的顺序发生了改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处的每个元素。因此通过为每个列表项提供一个 key 值,来以便 Vue 跟踪元素的身份,从而高效的实现复用。这个时候 key 的作用是为了高效的更新渲染虚拟 DOM。

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,diff 操作可以更准确、更快速

  • 更准确:因为带 key 就不是就地复用了,在 sameNode 函数a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。
  • 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快

v-for 为什么要加 key

如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速

更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。

更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快

hash和history

1. vue-router(前端路由)有两种模式,hash模式和history模式
1).hash 就是指 url 后面的 # 号以及后面的字符,history没有带#,外观上比hash 模式好看些
2).原理的区别(原理)
3). hash 能兼容到IE8, history 只能兼容到 IE10;
4).由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件(hashchange只能改变 # 后面的url片段);虽然hash路径出现在URL中,但是不会出现在HTTP请求中,对后端完全没有影响,因此改变hash值不会重新加载页面,基本都是使用 hash 来实现前端路由的。

2.原理:
1).hash通过监听浏览器的onhashchange()事件变化,查找对应的路由规则

2).history原理: 利用H5的 history中新增的两个API pushState() 和 replaceState() 和一个事件onpopstate监听URL变化

   history模式URL就要和后端进行一致,所以要改为history也需要后端的配合,否则会报错。
所以hash模式在每次刷新页面时是直接更改“#”后的东西,history每次刷新会重新像后端请求整个网址,也就是重新请求服务器。如果后端没有及时响应,就会报错404!。history的好处是可以进行修改历史记录,并且不会立刻像后端发起请求。不过如果对于项目没有硬性标准要求,我们可以直接使用hash模式开发。

(1)hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’:
https://www.word.com#search
hash 路由模式的实现主要是基于下面几个特性:

  • URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
  • hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
  • 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
  • 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。

(2)history 模式的实现原理HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。 **唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:** window.history.pushState(null, null, path); window.history.replaceState(null, null, path);

  • history 路由模式的实现主要基于存在下面几个特性:
  • pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
  • 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
  • history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。

vue初始化页面闪动问题

使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{ {message}}的字样,虽然一般情况下这个时间很短暂,但是还是有必要让解决这个问题的。

首先:在css里加上以下代码:v-cloak] { display: none;}

如果没有彻底解决问题,则在根元素加上style="display: none;" :style="{display: 'block'}

Vue怎么动态增加对象属性

1.this.$set(this.obj,key,value)

2.this.obj=Object.assign({},this.obj,{a:1,b:2});

路由守卫的生命周期

1.全局路由守卫的生命周期:

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

生效时机:导航触发时

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

生效时机:导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后

(3)router.afterEach((to,from)=>{  })

2.局部路由守卫的生命周期:

(1)beforRouteEnter(to,from,next){  }

注意:在渲染改组件对应的路由被加载进界面前调用,不能使用'this'获取组件实例,因为守卫执行前,组件实例还被没被创建

(2)beforeRouteUpdate(to,from,next){ }

注意:当前路由发生改变时调用,可以使用'this'访问组件实例

(3)beforeRouterLeave(to,from,next){  }

注意:导航离开该组件对应的路由时调用,可以使用'this'访问组件实例

route和router 的区别

route 是用来获取路由信息的,router是用来操作路由的。

Vue-Router

vue-router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:

  • 嵌套的路由
  • 模块化的、基于组件的路由配置
  • 路由参数、查询、通配符
  • 基于 Vue.js 过度系统的视图过渡效果
  • 细颗粒度的导航控制
  • 带有自动激活的 CSS class 的连接
  • history模式或 hash 模式,在 IE9 中自动降级
  • 自定义的滚动条行为

vue-router 组件:

  • < router-link to=""> 路由的路径
  • < router-link :to="{name:’‘l路由名’}"> 命名路由
  • < router-view> 路由的显示

vue-router 有哪几种导航钩子

1.全局导航钩子

    1)前置钩子:

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

    2)后置钩子

router.afterEach((to,from) => {  })

2.单独路由独享钩子

{
    path: '/home',
    name: 'home',
    component: Home,
    beforeEnter(to, from, next) {
        if (window.localStorage.getItem("id")) {
            next()
        } else {
            next({ name: "login" })
        }
    }
}

3.组件内的钩子

beforeRouteEnter(to, from, next) {
    // do someting
    // 在渲染该组件的对应路由被 confirm 前调用
},
beforeRouteUpdate(to, from, next) {
    // do someting
    // 在当前路由改变,但是依然渲染该组件是调用
},
beforeRouteLeave(to, from ,next) {
    // do someting
    // 导航离开该组件的对应路由时被调用
}

全局解析守卫

router.beforeResolve 注册一个全局守卫,和 router.beforeEach 类似

Vite打包优势

1)快速冷启动

2)打包编译速度

3)热模块更新

说说VUEX

  • state:放状态的地方,vuex的基本数据,用来存储变量
  • Mutation:提交更新数据的方法,同步的
  • getter:从基本数据state派生的数据,相当于state的计算属性
  • action:和Mutation功能大致相同,不同在于,action提交的是mutation,而不是直接更改状态。action可以包含任意异步操作。
  • modules:模块化VUEX,可以让每个模块都有自己的state mutation action getter

Vue2和Vue3的区别

1. 响应式系统的重构,使用proxy替换Object.defineProperty属性,优势:

    - Proxy可直接监听 对象`添加/删除`属性;

    - Proxy直接监听 数组的变化

    - Proxy监听的目标是对象本身,不需要像Object.defineProperty那样遍历每个属性,有一定的性能提升

2. 新增`组合式API`(Composition API),更好的逻辑重用和代码组织:

    - setup配置

    - ref与reactive

    - watch与watchEffect

    - provide与inject

3. 重构虚拟 DOM, diff算法

4. 生命周期更名

    - beforeDestroy改名为 beforeUnmount

    - destroyed改名为 unmounted

// Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

vue3:onBeforeMounted=>onMounted=>onBeforeUpdate=>onUpdated=>onBeforeUnmount

beforeCreate ===> setup()

created      ===> setup()

beforeMount  ===> onBeforeMount

mounted      ===> onMounted

beforeUpdate ===> onBeforeUpdate

updated      ===> onUpdated

beforeUnmount===> onBeforeUnmount

unmounted    ===> onUnmounted

4. 新的内置组件:

    - Fragment

    - Teleport

    - Suspense

5. 移除的部分:

    - 移除v-on.keyCode修饰符,同时也不再支持config.keyCodes

    - 移除v-on.native修饰符,

    - 移除过滤器(filter)

    - `不`再建议使用mixins, 组合式函数本身就是更好的mixin代替品

6.数据和方法的定义

vue2: data() { return {}; }, methods:{ }

vue3:据和⽅法都定义在setup中,并统⼀进⾏

return{}

watch和watcheffect

计算属性 computed 和事件 methods 有什么区别

我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的。

不同点:

  • computed:计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值。

  • method:只要发生重新渲染, method 调用总会执行该函数。

管理多个页面数据模块解耦合(vuex)

Vue 的核心是什么

数据驱动、组件系统。

Vue中$nextTick()的作用和原理

Vue在更新Dom时是异步执行的,在修改数据后,视图不会立即更新,而是在等同一时间就循环中的所有变化完成后,再统一对视图进行更新。所以我们在修改完数据,立即在方法中获取DOM,获取的仍是未修改的DOM。

$nextTick是下次DOM更新循环结束之后的延迟回调。DOM更新后再自动执行

里面的函数。

$nextTick作用:该方法中的代码会在渲染完成后执行,解决了异步渲染获取不到最新DOM的问题

应用场景:在钩子函数created()里面想要获取操作DOM,把操作DOM的方法放于$nextTick里面

MVC解释

MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

几乎所有的App都只干这么一件事:将数据展示给用户看,并处理用户对界面的操作。
MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。

MVVM

MVVM:Model、View、ViewModel。

你会下意识地把它和MVC来对比,你会发现,MVVM多了一个ViewModel而少了Controller。

首先说一下多出来的ViewModel(VM,不是显存)。
VM的意义,和Model一样,在于数据。
Model负责对数据进行取和存,然而我们对数据的操作除了取和存以外,还有一个非常重要的操作:解析。
 

MVVM模式

MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。(视图{页面}-模型{数据}-模型视图{桥梁视图与数据之间的转换处理})

1)MVVM 实现了数据与页面的双向绑定

2)MVVM 实现了页面业务逻辑和渲染之间的解耦,也实现了数据与视图的解耦,并且可以组件化开发。

3)VUE是如何体现MVVM思想的:胡子语法,实现了数据与视图的绑定;v-on 事件绑定,通过事件操作数据时,v-model 会发生相应的变化。

MVC解释

 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。

几乎所有的App都只干这么一件事:将数据展示给用户看,并处理用户对界面的操作。
MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。

MVVM

什么是MVVM
MVVM:Model、View、ViewModel。

你会下意识地把它和MVC来对比,你会发现,MVVM多了一个ViewModel而少了Controller。

首先说一下多出来的ViewModel(VM,不是显存)。
VM的意义,和Model一样,在于数据。
Model负责对数据进行取和存,然而我们对数据的操作除了取和存以外,还有一个非常重要的操作:解析。
 

猜你喜欢

转载自blog.csdn.net/Holly31/article/details/130740881