前端领域高频笔试面试—— Vue相关

Posted 前端小马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端领域高频笔试面试—— Vue相关相关的知识,希望对你有一定的参考价值。

目录

1.v-if 和 v-show 区别

2.vue常用的修饰符

3.vue中 key 值的作用

4.vue的单页面应用(SPA)的优缺点

5.Vue的生命周期

6.Vue组件间的参数传递

7.为什么vue中data必须是一个函数?

8.对MVVM模式的理解

9. vue-router 有哪几种导航钩子?

10.路由嵌套

11.axios的特点有哪些

12.页面刷新vuex被清空时的解决办法

13.vue中的 ref 是什么

14.Promise对象是什么

15.什么是js的冒泡?Vue中如何阻止冒泡事件

16.指令周期

17.如何优化SPA应用的首屏加载速度慢的问题?

18.解释一下vuex

19.说出至少4种vue当中的指令和它的用法?

20.vue.cli中怎样使用自定义组件?有遇到过哪些问题吗?

21.vuex有哪几种属性?

22.不用Vuex会带来什么问题?

23.Vue前端实现购物车

24.methods、computed、watch的区别

25.简述vuex的数据传递流程

26.组件中写 name 选项有什么作用?

27.的作用是什么?

28.mint-ui是什么?怎么使用?说出至少三个组件使用方法

29.为什么避免 v-if 和 v-for 用在一起?

30.怎样理解 Vue 的单向数据流?

31.Vue 的父组件和子组件生命周期钩子函数执行顺序?

32.在哪个生命周期内调用异步请求?

33.你有对 Vue 项目进行哪些优化?

34.虚拟 DOM 的优缺点

35.虚拟 DOM 实现原理

36.直接给一个数组项赋值,Vue 能检测到变化吗?

37.在Vue生命周期什么阶段才能访问操作DOM?

38.Vue-router 原理

39.router-link 和 $router.push 实现跳转的原理

40.promise 和 await/async 区别

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

42.什么是单页应用?

43.Vue的权限管理

44.vue 的 watch 是否可以监听数组

45.前端的优化方案


1.v-if 和 v-show 区别

(1)手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;

(2)编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;

(3)编译条件:v-if是惰性的,如果初始条件为假则什么也不做,只有在条件第一次变为真时才开始局部编译;v-show是在任何条件下都被编译,然后被缓存,而且DOM元素保留;

(4)性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;

(5)使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换。

2.vue常用的修饰符

.prevent: 提交事件不再重载页面;

.stop: 阻止单击事件冒泡;

.self: 当事件发生在该元素本身而不是子元素的时候会触发;

.capture: 事件侦听,事件发生的时候会调用。

3.vue中 key 值的作用

        当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,默认用“就地复用”策略,如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。

4.vue的单页面应用(SPA)的优缺点

        优点:Vue是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统;组件化开发、轻量、简洁、高效、快速、模块友好。

        缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

5.Vue的生命周期

(1)生命周期是什么?

        Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom 渲染 更新 渲染 卸载等一系列过程,我们称这是 Vue 的生命周期。

(2)生命周期的各个阶段作用

        beforeCreate(创建前)数据观测和初始化事件还未开始;

        created(创建后)完成数据观测,属性和方法的运算,初始化事件,$el属性还未显示出来;

        beforeMount(挂载前)在挂载开始之前被调用,相关的render函数首次被调用,实例已完成以下的配置:编译模板,把data里面的数据和模板生成html;注意此时还没有挂载html到页面上;

        mounted(挂载后)el被新创建的 vm.$el 替换,并挂载到实例上去调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。

        beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程;

        updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用;

        beforeDestroy(销毁前) 在实例销毁之前调用,实例仍然完全可用;

        destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

6.Vue组件间的参数传递

父子组件间传参   

        父给子传参(父:自定义属性传递变量;子:用Props['父元素自定义属性']接受)  

        子给父传参(子:this.$emit(父元素自定义事件,传递的值) ;父:自定义事件用参数去接收传递来 的值)   

兄弟间传参(除了以下方式也可直接用Vuex)

        通过给eventbus注册事件,别的组件触发事件,实现通信。

        ①创建一个eventbus对象,即创造一个vue对象,用作传递信息。

        ②接收信息的一方将事件通过vm.$on(“事件名”,事件处理函数)添加在eventbus对象上。

        ③发送数据的一方,通过vm.$emit(“事件名”,传递的数据)触发事件,将数据传递。

路由传参

a.通过params   

//需要在router的path后跟上参数
{
   path: "/two",
   name: "two",
   component: two
}

//跳转时
   this.$router.push({
      path: `/two` //直接把数据拼接在path后面
   })

//接收时
   this.$route.params

 b.通过query 

//跳转时
this.$router.push({
    path: `/two`,
    query: { id: this.message, data: 456 }
});    

//接收时            
    this.$route.query

        params 和 query 都是传递参数的,params不会在url上面出现,并且params参数是路由的一部分,是一定要存在的 , query是我们通常看到的url后面的跟在 ?后面的显示参数。

7.为什么vue中data必须是一个函数?

        对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。

8.对MVVM模式的理解

        MVVM 是 Model-View-ViewModel 的缩写;

        Model 代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;

        View 代表UI组件,负责将数据模型转化成UI展现出来;

        ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。

        在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。

        ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 统一管理。

9. vue-router 有哪几种导航钩子?

全局导航钩子

router.beforeEach(to, from, next),

router.beforeResolve(to, from, next),

router.afterEach(to, from ,next)

组件内钩子

beforeRouteEnter,

beforeRouteUpdate,

beforeRouteLeave

单独路由独享组件beforeEnter

10.路由嵌套

        路由嵌套会将其他组件渲染到该组件内,而不是进行整个页面跳转;

        router-view本身就是将组件渲染到该位置,想要进行页面跳转,就要将页面渲染到根组件,在起始配置路由时候写:

var App = Vue.extend({ root });

router.start(App,'#app');

11.axios的特点有哪些

(1)axios是一个基于promise的HTTP库,支持promise的所有API;

(2)它可以拦截请求和响应;

(3)它可以转换请求数据和响应数据,并对响应回来的内容自动转换为json类型的数据;

(4)它安全性更高,客户端支持防御XSRF。

12.页面刷新vuex被清空时的解决办法

(1)localStorage 存储到本地再回去;

(2)重新获取接口获取数据。

13.vue中的 ref 是什么

        ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上;如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。

14.Promise对象是什么

        Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,可以获取异步操作的消息;Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理;promise对象是一个构造函数,用来生成Promise实例;

        promise的特点是对象状态不受外界影响且一旦状态改变,就不会再变,任何时候都可以得到结果。Promise有三种状态:

        pending:初始状态,不是成功或失败状态。

        fulfilled:意味着操作成功完成。

        rejected:意味着操作失败。

        优点是将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,避免回调地狱。Promise 对象提供统一的接口,使得控制异步操作更加容易。

        缺点是无法取消 Promise,一旦新建它就会立即执行,无法中途取消,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。 当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

15.什么是js的冒泡?Vue中如何阻止冒泡事件

        js冒泡概念:当父元素内多级子元素绑定了同一个事件,js会依次从内往外或者从外往内执行每个元素的该事件,从而引发冒泡。

        js解决冒泡:event.stopPropagation();

        vue解决冒泡: 事件.stop,例如:@click.stop="" 、@mouseover.stop=""

16.指令周期

Bind

一次初始化调用  
inserted被绑定元素插入父节点调用
Update模板更新调用 
unbind指令与元素解绑时调用
Vue.nextTick在dom更新后执行,一般用于dom操作
Vue.$nextTick一直到真实的dom渲染结束后执行

17.如何优化SPA应用的首屏加载速度慢的问题?

        将公用的JS库通过script标签外部引入,减小app.bundel的大小,让浏览器并行下载资源文件,提高下载速度;

        在配置路由时,页面和组件使用懒加载的方式引入,进一步缩小 app.bundel 的体积,在调用某个组件时再加载对应的js文件;

        加一个首屏 loading 图,提升用户体验;

18.解释一下vuex

        vuex是用来做状态管理的,有五个常用属性state, getter, actions, mutations, modules;

        state是数据源,类似vue中的data,我们可以通过两种方式来获取它,mapStates, mapGerters。获取state必须放到computed中,这样才能保证state发生改变的时候该组件中用到state的地方都发生变化

        getters:相当于计算属性;

        mutation:同步操作, 修改数据;

        action:异步操作;

        modules:模块化

补充:如何获取vuex的state对象中的属性?

        方法1:直接从store实例中取值 this.$store.state.属性

        方法2:利用vuex的mapState方法来获取vuex的state对象中属性;

//先在组件中引入vuex的mapState方法
import { mapState } from 'vuex'

//在computed中
        computed:{
            ...mapState({
                count:state => state.count   //使用ES6的箭头函数来给count赋值
            })

        }
//在computed中也可写成数组格式
        computed:
            ...mapState(['count'])
        }

19.说出至少4种vue当中的指令和它的用法?

v-if

判断是否隐藏;
v-for连续生成一组结构相同,但是内容不同的HTML元素;
v-bind元素的属性值可能随程序自动变化,用v-bind绑定;
v-model实现双向绑定;
v-on为元素绑定事件,可简写为@;
v-html绑定一段HTML代码片段到页面上;

v-once

一个元素的内容,只会在首次加载时绑定一次,之后几乎不会改变时,都用v-once标记;

v-pre

正文中包含了不希望被vue编译的{{ }}时,采用v-pre保护。

补充:v-for为什么必须加:key

        a.为每个元素添加唯一标识;

        b.避免重建整个列表;

        c.提高修改的效率。

20.vue.cli中怎样使用自定义组件?有遇到过哪些问题吗?

        第一步:在components目录新建组件文件(smithButton.vue),在组件文件中的script代码中一定要用 export default 将组件导出;

        第二步:在需要用的页面(组件)中导入:import smithButton from ‘../components/smithButton.vue’;

        第三步:注入到vue的子组件的components属性上面,components:{smithButton};

        第四步:在template视图view中使用,<smith-button> </smith-button>

        问题:smithButton命名,使用的时候则smith-button(HTML不认识大写字母)。

21.vuex有哪几种属性?

        有五种,分别是 State、Getter、Mutation 、Action、Module;

        state为单一状态树,在state中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在vue.js的组件中才能获取定义对象的状态;

        getter类似vue.js的计算属性,当我们需要从store的state中派生出一些状态时,就需要使用getter,getter会接收state作为第一个参数,而且getter的返回值会根据它的依赖被缓存起来,只有getter中的依赖值(state中的某个需要派生状态的值)发生改变的时候才会被重新计算;

        更改store中state状态的唯一方法就是提交mutation,每个mutation都有一个字符串类型的事件类型和一个回调函数,我们需要改变state的值就要在回调函数中改变,要执行这个回调函数,就需要执行一个相应的调用方法:store.commit;

        action可以提交mutation,在action中可以执行store.commit,而且action中可以有任何的异步操作。在页面中如果我们要用这个action,就需要执行store.dispatch;

        当state中很复杂臃肿的时候,module可以将store分割成模块,每个模块中拥有自己的state、mutation、action和getter。

22.不用Vuex会带来什么问题?

(1)可维护性会下降,要想修改数据,得维护三个地方;

(2)可读性会下降,因为一个组件里的数据,看不出来是从哪来;

(3)增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。

23.Vue前端实现购物车

利用vuex + vant 实现购物车功能,概括有以下步骤:

(1)mock模拟数据;

(2)利用veux操作商品的选中状态;

(3)全选与取消全选;

(4)动态reduce计算价格;

(5)结算取出商品id;

(6)利用manageStatus判断管理状态,管理删除商品;

(7)未删除商品的状态存储。

24.methods、computed、watch的区别

        methods是个方法,执行的时候需要事件进行触发;

        computed是一个计算属性,是实时响应的,只要data中的属性发生了变化那么就会触发computed,计算属性是基于属性的依赖进行缓存的,methods调用的时候需要加(),而computed调用的时候不需要加();

        watch用来监听属性的变化,当值发生变化的时候来执行特定的函数,watch监听属性的时候会有2个参数newVal和oldVal一个新值一个旧值。

25.简述vuex的数据传递流程

        当组件进行数据修改的时候我们需要调用dispatch来触发actions里面的方法,actions里面的每个方法中都会 有一个commit方法,当方法执行的时候会通过commit来触发mutations里面的方法进行数据的修改,mutations里面的每个函数都会有一个state参数,这样就可以在mutations里面进行state的数据修改 ,当数据修改完毕后,会传导给页面,页面的数据也会发生改变。

26.组件中写 name 选项有什么作用?

(1)项目使用 keep-alive 时,可搭配组件 name 进行缓存过滤;

(2)DOM 做递归组件时需要调用自身 name;

(3)vue-devtools 调试工具里显示的组见名称是由vue中组件name决定的。

27.<keep-alive></keep-alive>的作用是什么?

        <keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。

28.mint-ui是什么?怎么使用?说出至少三个组件使用方法

        基于vue的前端组件库。先npm安装,然后import引入样式和js,vue.use(mintUi)全局引入。在单个组件局部引入:import {Toast} from ‘mint-ui’。

        组件一:Toast(‘登录成功’);

        组件二:mint-header;

        组件三:mint-swiper

29.为什么避免 v-if 和 v-for 用在一起?

        当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,通过v-if 移动到容器元素,不会再重复遍历列表中的每个值。取而代之的是,我们只检查它一次,且不会在 v-if 为否的时候运算 v-for。

30.怎样理解 Vue 的单向数据流?

        所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行;

        这样会防止从子组件意外改变父级组件的状态,从而导致应用的数据流向难以理解;

        除此之外,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值,

所以不应该在一个子组件内部改变 prop,如果你这样做了,Vue 会在浏览器的控制台中发出警告;

        子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件来修改。

31.Vue 的父组件和子组件生命周期钩子函数执行顺序?

Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:

加载渲染过程

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

子组件更新过程

父 beforeUpdate --> 子 beforeUpdate --> 子 updated --> 父 updated

父组件更新过程

父 beforeUpdate --> 父 updated

销毁过程

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

32.在哪个生命周期内调用异步请求?

        可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是更推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

        (1)能更快获取到服务端数据,减少页面 loading 时间;

        (2)ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

33.你有对 Vue 项目进行哪些优化?

(1)代码层面的优化

        v-if 和 v-show 区分使用场景;

        computed 和 watch 区分使用场景;

        v-for 遍历必须为 item 添加 key,且避免同时使用 v-if;

        长列表性能优化;

        事件的销毁;

        图片资源懒加载;

        路由懒加载;

        第三方插件的按需引入;

        优化无限列表性能;

        服务端渲染 SSR or 预渲染;

(2)Webpack 层面的优化

        Webpack 对图片进行压缩;

        减少 ES6 转为 ES5 的冗余代码;

        提取公共代码;

        模板预编译;

        提取组件的 CSS;

        优化 SourceMap;

        构建结果输出分析;

        Vue 项目的编译优化;

(3)基础的 Web 技术的优化

        开启 gzip 压缩;

        浏览器缓存;

        CDN 的使用;

        使用 Chrome Performance 查找性能瓶颈;

34.虚拟 DOM 的优缺点

优点:

        保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;

        无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;

        跨平台: 虚拟 DOM 本质上是 javascript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

        无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

35.虚拟 DOM 实现原理

虚拟 DOM 的实现原理主要包括以下 3 部分:

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

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

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

36.直接给一个数组项赋值,Vue 能检测到变化吗?

由于 JavaScript 的限制,Vue 不能检测到以下数组的变动:

(1)利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue

(2)当你修改数组的长度时,例如:vm.items.length = newLength

为了解决第一个问题,Vue 提供了以下操作方法:

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

// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)

// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

为了解决第二个问题,Vue 提供了以下操作方法:

// Array.prototype.splice
vm.items.splice(newLength)

37.在Vue生命周期什么阶段才能访问操作DOM?

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

38.Vue-router 原理

        vue-router通过hash与history两种方式实现前端路由;更新视图但不重新请求页面是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要有两种方式:

(1)hash:利用 URL 中的 hash. 形式上会多个# ;如下,

http://localhost:8080/#/login

        hash("#") 的作用是加载 URL 中指示网页中的位置; # 本身以及它后面的字符称之为 hash,可通过 window.location.hash 获取;

        hash 虽然出现在 url 中,但不会被包括在 http 请求中,它是用来指导浏览器动作的,对服务器端完全无用,因此改变 hash 不会重新加载页面, 每一次改变 hash(window.localtion.hash)都会在浏览器访问历史中增加一个记录。 利用 hash 的以上特点,就可以来实现前端路由"更新视图但不重新请求页面"的功能了。

(2)history:html5 中新增的方法,形式上比 hash更好看;如下,

http://localhost:8080/login

        History interface 是浏览器历史记录栈提供的接口,通过back()、forward()、go()等方法,可以读取浏览器历史记录栈的信息,进行各种跳转操作。

        从 HTML5开始,History interface 提供了2个新的方法:pushState()、replaceState() 使得我们 可以对浏览器历史记录栈进行修改,这2个方法有个共同的特点:当调用他们修改浏览器历史栈后,虽然当前url改变了,但浏览器不会立即发送请求该url,这就为单页应用前端路由,更新视图但不重新请求页面提供了基础。

前端领域高频笔试面试—— JavaScript相关

前端vue2面试题2023前端最新版vue模块,高频17问(上)

前端vue2面试题2023前端最新版vue模块,高频17问(上)

前端vue2面试题2023前端最新版vue模块,高频17问(上)

Vue面试高频考题解析

前端面试Vue 高频原理篇+详细解答,还有105道vue面试题集合