牛客网刷题总结【Vue、高频Vue面试题】

前言

一些自己的刷题笔记总结

目录

前言

1.什么是SPA

2.MVVM模型

3.计算属性和监听属性的区别

4.v-model、v-on、v-bind

5.v- for和v-if同时使用   有一个优先级的问题 造成浪费

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

7.Vue中的key有什么作用

8.关于Vue中的diff算法

9.Vue组件中data为什么必须是一个函数

10.Vue有哪几种通信方式

11.Vue中组件通信方式

13.关于路由模式,路由切换的原理是什么呢

14、路由守卫钩子函数

15、关于this.$router和this.$route

1.this.$router 

2.this.$route,通过this.$route获取参数

16.路由懒加载

17. 关于

18. VUE的生命周期

19. 父组件和子组件的生命周期执行顺序

20.子组件可以直接修改父组件的数据吗?会发生什么?有哪几种解决方案

21.Vue双向数据绑定

22.Vue3.x响应式数据原理

23.Webpack

23.1 webpack打包原理 

23.2 打包流程

23.3 less特性 23.4 webpack使用less怎么配置 

 24. babel是啥

 25.Vue自定义指令 钩子函数(指令名字,配置对象(属性,函数))

26、vuex 

27、Vue的异步渲染


1.什么是SPA

参考:vue 多页面项目开发指南 - 掘金

SPA就是web页面初始化时就加载相应的HTML、css和js。

一旦页面加载完成后不会因为用户的操作而频繁刷新界面,取而代之的是使用路由机制进行跳转。

Vue单页面:只有一个页面index.html,在里面切换不同的组件。不仅与页面交互无刷新,而且与页面跳转都无刷新,为了实现单页面应用,从而产生了前端路由。

单页面应用(SPA,single-page application:仅在Web页面初始化时加载相应的HTML、js和CSS。一旦页面加载完成,SPA不会因用户的操作而进行页面的重新加载或跳转;而是利用路由机制实现HTML内容的变换,UI与用户的交互。

优点

(1)良好的交互体验,内容的改变不需要重新加载整个页面。

(2)对服务器压力较小。

(3)前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理。

缺点:

(1)不利于seo(Search Engine Optimization)。

(2)导航不可用,单页面不能用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理。

(3)首屏加载缓慢

首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容

首屏加载可以说是用户体验中最重要的环节

 

多页面(MPA),就是指一个应用中有多个页面,页面跳转时是整页刷新。

2.MVVM模型

  • MVC

M:model 负责保存应用数据,与后端数据进行同步

V:view负责视图展示,将model中的数据可视化出来

C:  controller负责业务逻辑,根据用户行为对model数据进行修改

单向通信

  • MVVM

M: model  负责保存应用数据,与后端数据进行同步

V: view 

VM :view-model 

  1. VM通过实现一套数据响应式机制自动响应Model中的数据变化
  2. VM会实现一套更新策略自动将数据变化转换为视图更新
  3. 通过事件监听响应V中用户交互修改M中的数据
  4. 这样VM中就减少了大量DOM操作代码
  5. MVVM在保持V和M松耦合的同时,还减少了维护她们关系的代码,使用户专注于业务逻辑,兼顾开发和可维护性

3.计算属性和监听属性的区别

  • computed是依赖已有的变量来计算一个目标变量,大多数情况都是多个变量凑在一起计算出一个变量,并且computed具有缓存机制,依赖值不变的情况下其会直接读取缓存进行复用;computed不能进行异步操作 
  • watch是监听某一个变量的变化,并执行相应的回调函数,通常是一个变量的变化决定多个变量的变化,watch可以进行异步操作 
  • 简单记就是:一般情况下computed是多对一,watch是一对多
  • computed能完成的功能,watch都可以完成

  • watch能完成的功能,computed不一定能完成。watch可以进行异步操作

4. v-bind、v-model、v-on、

  • v-bind是绑定属性, 绑定DOM, : 是指令 “v-bind”的缩写,绑定style和class
  • v-model 双向绑定数据     “.”是修饰符
  • v-on是绑定事件,“@”是指令“v-on”的缩写,语法糖

5.v- for和v-if同时使用   有一个优先级的问题 造成浪费

答案解析

  • v-for 和 v-if 不要在同一个标签中使用,因为解析时先解析 v-for 再解析 v-if(v-for 指令比 v-if 优先级高)。
  • v-for在Vue2中优先级更高
  • 思路分析:总分总模式

先给出结论

为什么是这样的

它们能放一起吗

如果不能,那应该怎样

总结

  • 回答范例:

  • 在 Vue 2 中,v-for 优先于 v-if 被解析;但在 Vue 3 中,则完全相反,v-if 的优先级高于 v-for

  • 我曾经做过实验,把它们放在一起,输出的渲染函数中可以看出会先执行循环再判断条件

  •  

     

  • 实践中也不应该把它们放一起,因为哪怕我们只渲染列表中一小部分元素,也得在每次渲染的时候遍历整个列表

  • 通常有两种情况下导致我们这样做:

    • 为了过滤列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。此时定义一个计算属性 (比如 activeUsers),让其返回过滤后的列表即可。

       

    • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。此时把 v-if 移动至容器元素上 (比如 ulol)即可。

    •  

  • 文档中明确指出永远不要把 v-if 和 v-for 同时用在同一个元素上,显然这是一个重要的注意事项。

  • 看过源码里面关于代码生成的部分,

  • 知其所以然:

    在 Vue 2 中做个测试,test.html 两者同级时,渲染函数如下:

    ƒ anonymous(
    ) {
    with(this){return _c('div',{attrs:{"id":"app"}},_l((items),function(item){return (item.isActive)?_c('div',{key:item.id},[_v("\n      "+_s(item.name)+"\n    ")]):_e()}),0)}
    }

    在 Vue 3 中做个测试,test-v3.html 两者同级时,渲染函数如下:

    (function anonymous(
    ) {
    const _Vue = Vue
    
    return function render(_ctx, _cache) {
      with (_ctx) {
        const { renderList: _renderList, Fragment: _Fragment, openBlock: _openBlock, createElementBlock: _createElementBlock, toDisplayString: _toDisplayString, createCommentVNode: _createCommentVNode } = _Vue
    
        return shouldShowUsers
          ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(items, (item) => {
              return (_openBlock(), _createElementBlock("div", { key: item.id }, _toDisplayString(item.name), 1 /* TEXT */))
            }), 128 /* KEYED_FRAGMENT */))
          : _createCommentVNode("v-if", true)
      }
    }
    })

    源码中找答案: Vue 2compiler/codegen/index.js Vue 3compiler-core/src/codegen.ts

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

  • v-show:display:none,不管什么状态,子组件都会被渲染,只是通过display:none进行显示上的切换  适用于需要频繁切换的场景
  •  v-if:  visibility:hidden,真正的创建或销毁对象,适用于运行时很少改变的场景

答案解析

  • v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。表达式通过的情况下将元素渲染到 DOM 中。
  • v-show 会被编译成指令,条件不满足时控制样式将对应节点隐藏 (display:none)。条件满足时基于 CSS display 属性来显示元素
  • v-if 支持 v-else 和 v-else-if 指令,而 v-show 不支持 else 指令。
  • v-if 有更高的切换开销,而 v-show 有更高的初始化渲染开销
  • v-if 支持 <template> 选项卡,但 v-show 不支持

 

使用场景

  • v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景
  • v-show 适用于需要非常频繁切换条件的场景

7.Vue中的key有什么作用

  1. 因为vue组件高度复用,增加key可以标识组件的唯一性,可以更好地区别各个组件。key的作用主要是为了高效的更新虚拟DOM
  2. 使用key,会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。也可以强制替换元素/组件而不是重复使用它。
  3. 当以数组的下标index作为key值时,其中一个元素通过增删改查发生了变化就有可能导致所有元素的key值发生改变。

答案解析

为了跟踪每个节点的特征,从而重用和重排存在的元素,你需要为每一个 v-for 迭代的项提供一个 key 属性。一个理想的 key 值是条目的唯一 id

<!--举个例子-->
<div v-for="item in items" :key="item.id">
    {{item.name}}
</div>

因此,只要有可能,总是建议给 v-for 提供一个 key 值,除非迭代的 DOM 内容很简单。
注:不应该使用非基本类型的值,如对象和数组作为 v-for 的 key,使用 String 或 Number 类型替代。

8.关于Vue中的diff算法

 

 

 

 

 

9.Vue组件中data为什么必须是一个函数

 Object是引用数据类型  如果不用function返回  每个组件的data都是内存的同一个地址  

 一个数据改变了其他也会改变   js中只有函数构成作用域  

 data是一个函数时  每个组件实例都有自己的作用域   每个实例相互独立   不会相互影响

10.Vue有哪几种通信方式

https://blog.csdn.net/qq_44810886/article/details/124191087?spm=1001.2014.3001.5501

11.Vue中组件通信方式

父子组件通信:父组件向子组件传递数据通过props,子组件向父组件传递事件通过$emit方法。祖先元素和后代元素通信:用父子组件通信只能一代一代传递,从而引出上下文的方式,把后代元素所需要的信息全部放在祖先元素上下文中。任意组件之间通信:用localStorage和Vuex。

  1. props / $emit适用父子组件通信。
  2. ref与$parent / $children适用父子组件通信。
  3. provide / inject适用于隔代组件通信:祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。跨级组件间建立了一种主动提供与依赖注入的关系。
  4. Vuex 适用于父子、隔代、兄弟组件通信。

13.关于路由模式,路由切换的原理是什么呢

vue-router有两种模式

  • history:如:http://localhost:8080/about,

原理:history通过H5提供的API history.pushState 和 history.replaceState实现跳转且不刷新页面,history模式需要后端进行配合

  • hash模式: 如:http://localhost/#/about,

原理:window对象提供了onhashchange事件来监听hash值的改变,一旦url中的hash值发生改变,便会触发该事件

本质上是改变window.location的href属性, Hash模式基于锚点(#),以及onhashchange事件 —— 通过锚点的值作为路由地址

window.onhashchange = function(){

// hash 值改变

// do you want

}

14、路由守卫钩子函数

1.全局路由守卫的钩子函数有

  • 全局前置守卫:router.beforeEach()
  • 全局解析守卫:router.beforeResolve()
  • 全局后置守卫:router:afterEach()

注意:名字中间没有“Route”,组件级路由守卫的钩子函数才有“Route”

2.路由独享守卫

beforeEnter:(to,from,next){

条件代码

}

3.组件内守卫

  • 组件内的前置守卫:beforeRouteEnter((to,from,next)=>{})
  • 组件内的后置守卫:beforeRouteLeave()
  • 组件内的更新守卫:beforeRouteUpdate()

15、关于this.$router和this.$route

1.this.$router 

  • this.$router是全局的路由对象,options.routes包括所有的路由路径 
  • this.$router.push() ,导航到不同的URL
  •  this.$router.go()

2.this.$route,通过this.$route获取参数

  • this.$route是本页面的路由对象, 可以获取name,path,query,params
  • this.$route.params
  • this.$route.query

this.$route是路由参数对象,包括path,params,hash,query,fullPath,matched,name等路由信息参数

this.$router是一个路由导航对象,包括路由的跳转方法,构造函数,可使用JS代码,实现路由的前进、后退(go)、跳转到新的URL地址。四种方式:

最简单的:this.$router.push("/home/goodsinfo/"+id)。

传递对象:this.$router.push({ path: "/home/goodsinfo/" + id })。

传递命名的路由:this.$router.push({ name: "goodsinfo" , params: { id }})。

带查询参数 /home/goodsinfo?plan=private:

this.$router.push({ path: "/home/goodsinfo/",query:{plan:'private'} })

16.路由懒加载

整个网页默认是刚打开就去加载所有页面,路由懒加载就是只加载你当前点击的那个模块。

按需去加载路由对应的资源,提高首屏加载速度(tip:首页不用设置懒加载,而且一个页面加载过后再次访问不会重复加载)。

实现原理:将路由相关的组件,不再直接导入了,而是改写成异步组件的写法,只有当函数被调用的时候,才去加载对应的组件内容。
 

  • 结合Vue的异步组件和Webpack的代码分析

const Home = resolve => { require. ensure(['. . /components/Home.vue' ], ( ) => { resolve(require('. ./ components/Home.vue')) )};

  • AMD写法

const About = resolve => require(['. ./ components/ About.vue'], resolve);

  • 在ES6中,我们可以有更加简单的写法来组织Vue异步组件和Webpack的代码分割.

const Home = () => import('. ./ components/Home. vue' )

路由传递参数有哪几种方式

路由怎么嵌套子路由

17. 关于<keep-alive>

< keep-alive >是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

keep-alive的作用:缓存组件,重新返回某个页面的时候不会重新发送http请求, 在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在组件的父组件链中。
当组件在 <keep-alive> 内被切换时,它的 mounted 和 unmounted 生命周期钩子不会被调用,取而代之的是 activated 和 deactivated。(这会运用在 <keep-alive> 的直接子节点及其所有子孙节点。)
对于被 <keep-alive> 包裹的组件:
第一次进入:created ==> mounted ==> activated
离开:deactivated
再一次进入:activated

18. VUE的生命周期

Vue的生命周期(11个钩子函数)

  • beforeCreate(创建前):在此生命周期函数执行的时候,data和methods中的数据都还没有初始化。
  • created(创建后):在此生命周期函数中,data和methods都已经被初始化好了,如果要调用 methods中的方法,或者操作data中的数据,最早只能在created中操作。
  • beforeMount(载入前):在此生命周期函数执行的时候,模板已经在内存中编译好了,但是尚未挂载到页面中去,此时页面还是旧的。
  • mounted(载入后):此时页面和内存中都是最新的数据,这个钩子函数是最早可以操作dom节点的方法。
  • beforeUpdate(更新前):此时页面中显示的数据还是旧的,但是data中的数据是最新的,且页面并未和最新的数据同步。
  • Updated(更新后):此时页面显示数据和最新的data数据同步。
  • beforeDestroy(销毁前):当执行该生命周期函数的时候,实例身上所有的data,所有的methods以及过滤器…等都处于可用状态,并没有真正执行销毁。
  • destroyed(销毁后):此时组件以及被完全销毁,实例中的所有的数据、方法、属性、过滤器…等都已经不可用了。
  • //下面两个钩子函数一般配合使用
  • activated(组件激活时):和上面的beforeDestroy和destroyed用法差不多,但是如果我们需要一个实例,在销毁后再次出现的话,用beforeDestroy和destroyed的话,就太浪费性能了。实例被激活时使用,用于重复激活一个实例的时候
  • deactivated(组件未激活时):实例没有被激活时。
  • errorCaptured(错误调用):当捕获一个来自后代组件的错误时被调用\

19. 父组件和子组件的生命周期执行顺序

1、加载渲染过程

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

2、子组件更新过程

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

3、父组件更新过程

父 beforeUpdate -> 父 updated

4、销毁过程

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

20.子组件可以直接修改父组件的数据吗?会发生什么?有哪几种解决方案

21.Vue双向数据绑定

 

 

 Vue 对数组原型链上的几个方法进行劫持,对于会导致元素新增的3个方法 push 、 pop 、 unshift 会在内部获取新增的元素,执行响应式的处理。如果需要为数字元素重新赋值,可以使用 vm.$set(arr, indexOfItem, newValue) 方法,这里展示一下 $set 的具体实现:
 

22.Vue3.x响应式数据原理


Vue3.x改用Proxy替代Object.defineProperty。
因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化。
Proxy只会代理对象的第一层,Vue3是怎样处理这个问题的呢?
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger

①Vue3中Template支持多个根标签,Vue2不支持【跟标签】
②Vue3中的生命周期的挂载钩子是onMounted,需要引入才能使用【钩子的名字变了】
③Vue3引入了tree-shaking,以模块的方式引入api,减小打包体积【更小】
④引入setup
ou what is setup??
是什么:组合式 API(name)

23.Webpack

webpack是js中的模块打包工具。其工作原理:

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。

23.1 webpack打包原理 

把一切都视为模块:不管是 css、JS、Image 还是 html 都可以互相引用,通过定义 entry.js,对所有依赖的文件进行跟踪,将各个模块通过 loader 和 plugins 处理,然后打包在一起。处理模块化之间的依赖关系。
按需加载:打包过程中 Webpack 通过 Code Splitting 功能将文件分为多个 chunks,还可以将重复的部分单独提取出来作为 commonChunk,从而实现按需加载。

把所有依赖打包成一个 bundle.js 文件,通过代码分割成单元片段并按需加载

23.2 打包流程

六种常见的前端构建工具: npm script , grunt, gulp, fis3, webpack, rollup(专注于es6)!

grunt的核心是Task,

  1. entry:配置入口文件。
  2. output:指定输出文件。
  3. module:决定如何处理模块,使用各种loader处理CSS、JS、image等资源,并将它们编译与打包成浏览器可以解析的内容等。
  4. plugins:扩展插件,在webpack构建流程中特定时机注入扩展逻辑来改变构建结果。

    5.devServer:启动一个HTTP代理服务器用于网页请求,同时启动webpack并接收webpack发出的文件变更信号。

23.3 less特性 
23.4 webpack使用less怎么配置 

 24. babel是啥

将ES6的语法转换为ES5,也是一个loader

常用的loader

  • css-loader读取合并css文件
  • style-loader把css内容注入到Javascript里
  • sass-loader解析sass文件(安装sass-loader,node-sass)
  • postcss-loader自动添加浏览器兼容前缀(postcss.config配置)
  • url-loader将文件转换为base64 URL
  • vue-loader处理vue文件

 25.Vue自定义指令 钩子函数(指令名字,配置对象(属性,函数))


①属性
•el: 指令绑定的元素。 •vm: 拥有该指令的上下文 ViewModel。 •expression: 指令的表达式,不包括参数和过滤器。 •arg: 指令的参数。 •name: 指令的名字,不包含前缀。 •modifiers: 一个对象,包含指令的修饰符。 •descriptor: 一个对象,包含指令的解析结果
②函数
•bind:只调用一次,在指令第一次绑定到元素上时调用。 •update: 在 bind 之后立即以初始值为参数第一次调用,之后每当绑定值变化时调用,参数为新值与旧值。 •unbind:只调用一次,在指令从元素上解绑时调用

26、vuex 

vuex可保存组件间共享的数据。

data存放组件内部私有的数据。props存放父组件传递给子组件的数据。什么样数据需要放在vuex中 ? 首先这个数据被多个组件频繁用到。

场景:单页面应用中组件之间的状态,音乐播放、登录状态、加入购物车等。

如何操作vuex中数据:

const store = new Vuex.Store({

state: {  },//基本数据(数据源存放地).

mutations: {    },//同步更改state数据方法集合, 不能写ajax等一部请求

getters: {  },//从基本数据派生出来的数据

actions: {  }, //负责获取、处理数据(如果有异步操作必须在actions处理,再提交到mutation同步更新)

modules: //模块化Vuex,将状态树分隔成不同的模块,每个模块拥有自己的state,getters,mutations,actions;而且允许每个module里面嵌套子module

})

  1. state中的数据,不能直接修改,若需要修改,必须通过mutations提供的方法,需通过this.$store.commit(‘方法的名称’, [参数数组])。
  2. 若组件想要从state上获取数据,需要this.$store.state.变量名
  3. 如果store中state数据,在对外提供的时候,需要一层包装,则使用getters,this.$store.getters.方法名
  4.  getters中方法和组件中过滤器类似,都没有修改数据,只是给数据一层包装后提供给调用者。getters也和computed比较像,只要state中数据改变了,若getters正好引用这个数据,那么就会触发getters中方法重新求值。

页面刷新了之后vuex中的数据消失怎么解决?

vuex数据位于内存中,页面刷新重置会导致数据消失,本地持久化可以解决这个问题,sesstionStorage或者localStorage。

实施方案: state的持久化,也就是分别在state数据初始化、更新的时候进行读取和设置本地存储。

27、Vue的异步渲染

Vue实现响应式并不是数据发生变化之后DOM立即变化,而是在同步任务执行完成之后才执行渲染任务,简单说Vue的渲染是异步的 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值