vue面试题总结

说一下对vue的理解?

web是World Wide Web的简称,我们把她划分成四个时代来讲解

石器时代:静态页面,可以理解为就是一张可以在网上浏览的报纸,没有数据库

文明时代:微软出现ASP和java,增强了web和服务端的交互的安全性,其实就是java+HTML,jsp有一个很大的缺点,就是不太灵活

工业革命时代:移动设备普及,SPA雏形,Backbone EmberJS AngularJS 这样一批前端框架随之出现,通过几年的飞速发展,节约了开发人员经历,降低了开发者和发展过程的门槛

百花齐放时代:各种前端框架不断出现

vue是什么?

 Vue.js(/vjuː/,或简称为Vue)是一个用于创建用户界面的开源JavaScript框架,也是一个创建单页应用的Web应用框架,vue关注的核心是MVC模式中的视图层,他方便的获取数据更新,通过组件内部特定的方法实现视图于模型的数据更新

vue的核心特性:

数据驱动(MVVM):MVVM表示的是 Model-View-ViewModel

  • Model:模型层,负责处理业务逻辑以及和服务器端进行交互
  • View:视图层:负责将数据模型转化为UI展示出来,可以简单的理解为HTML页面
  • ViewModel:视图模型层,用来连接Model和View,是Model和View之间的通信桥梁

组件化:

就是把图形、非图形的各种逻辑均抽象为一个统一的概念来实现开发的模式

降低整个系统的耦合度,在保持接口不变的情况下,可以替换不同的组件快速完成需求

调试方便,组件之间低耦合

提高可维护性,组件职责单一,组件在系统中是被复用的,所以对代码及逆行优化获得系统整体升级

常见的指令:

  • 条件渲染指令 v-if
  • 列表渲染指令v-for
  • 属性绑定指令v-bind
  • 事件绑定指令v-on
  • 双向数据绑定指令v-model

vue和传统开发的区别?

vue所有的界面事件,都是去操作数据的,jquery操作DOM

vue所有界面的变动,都是根据数据自动绑定出来的,jquery操作DOM

vue和react的对比

 相同点:

都有组件化思想

都支持服务器端渲染

都有虚拟dom

数据驱动视图

都是单项数据流

都有支持native的方案,vue的weex、React的react native

都有自己的构建工具:vue的vue-cli React的Create React App

区别:

  • 都是单项的数据流,只不过vue采用双向数据绑定(这是一个误区)
  • 数据变化的实现原理不同。react使用的是不可变数据,而Vue使用的是可变的数据
  • 组件化通信的不同。react中我们通过使用回调函数来进行通信的,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数
  • diff算法不同。react主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。Vue 使用双向指针,边对比,边更新DOM

 你对SPA单页面的理解,优缺点?如何实现SPA应用呢?

SPA翻译过来就是单页面应用,是一种网络应用程序或网站的模型,通过动态重写当前页面于用户交互,避免了页面之间切换打断用户体验在单页应用中,所有必要的代码都通过单个页面加载而检索

 SPA和MPA的区别?

MPA翻译过来就是多页面应用,每个页面都是一个主页面,都是独立的

单页面应用(SPA)多页面应用(MPA)
组成一个主页面和多个页面片段多个主页面
刷新方式局部刷新整页刷新
url模式哈希模式历史模式
SEO搜索引擎优化难实现,可使用SSR方式改善容易实现
数据传递容易通过url、cookie、localStorage等传递
页面切换速度快,用户体验良好切换加载资源,速度慢,用户体验差
维护成本相对容易相对复杂

 单页应用的优缺点:

优点:

具有桌面应用的即时性,网站的可移植和可访问性,

用户体验好,快,内容的改变不需要重新加载整个页面

良好的前后端分离,分工明确

缺点:

不利于搜索引擎的抓取

首次渲染速度相对于较慢

原理

  1. 监听地址栏中hash变化驱动界面变化
  2. pushsate记录浏览器的历史,驱动界面发送变化

 v-show和v-if有什么区别?使用场景?

共同点:

都是用来控制元素在页面显示隐藏

区别:

控制手段:v-show隐藏是为元素添加一个css display:none,dom元素依然存在,v-if显示隐藏是将dom元素整个添加或者删除

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

编译条件:v-if是真正的条件渲染,他会确保在切换过程中条件块内的事件监听器和子组件适当的被销毁和重建,只有渲染条件为假,并不做操作,直到为真才渲染

性能消耗:v-if有更高的切换消耗,v-show有更高的初始化渲染消耗

v-show原理:

不管初始条件是什么,元素总会被渲染

v-if原理

v-if在实现上比v-show要复杂的多,因为还有else-if等条件需要处理

使用场景

v-if和v-show都能控制dom元素在页面的显示

v-if相比v-show开销更大(直接操作dom节点增加与删除)

如果我们非常频繁的切换,则使用v-show较好

如果在运行条件很少改变,则使用v-if较好

vue实例挂载的过程

  • new Vue的时候调用会调用_init方法

    • 定义 $set$get 、$delete$watch 等方法
    • 定义 $on$off$emit$off等事件
    • 定义 _update$forceUpdate$destroy生命周期
  • 调用$mount进行页面的挂载

  • 挂载的时候主要是通过mountComponent方法

  • 定义updateComponent更新函数

  • 执行render生成虚拟DOM

  • _update将虚拟DOM生成真实DOM结构,并且渲染到页面中

说一下你对vue生命周期的理解?在create和mounted这两个生命周期中请求数据有什么区别?

生命周期(Life Cycle)的概念应用很广泛,特别是在政治、经济、环境、技术、社会等诸多领域经常出现,其基本涵义可以通俗地理解为“从摇篮到坟墓”整个过程在Vue中实例从创建到销毁的过程就是生命周期,即指从创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程

Vue生命周期总共可以分为8个阶段:创建前后, 载入前后,更新前后,销毁前销毁后,以及一些特殊场景的生命周期

生命周期描述
beforeCreate组件实例被创建之初
created组件实例已经完全创建
beforeMount组件挂载之前
mounted组件挂载到实例上去之后
beforeUpdate组件数据发生变化,更新之前
updated组件数据更新之后
beforeDestroy组件实例销毁之前
destroyed组件实例销毁之后
activatedkeep-alive 缓存的组件激活时
deactivatedkeep-alive 缓存的组件停用时调用
errorCaptured捕获一个来自子孙组件的错误时被调用

具体分析

beforeCreate -> created

  • 初始化vue实例,进行数据观测

created

  • 完成数据观测,属性与方法的运算,watchevent事件回调的配置
  • 可调用methods中的方法,访问和修改data数据触发响应式渲染dom,可通过computedwatch完成数据计算
  • 此时vm.$el 并没有被创建

created -> beforeMount

  • 判断是否存在el选项,若不存在则停止编译,直到调用vm.$mount(el)才会继续编译
  • 优先级:render > template > outerHTML
  • vm.el获取到的是挂载DOM

beforeMount

  • 在此阶段可获取到vm.el
  • 此阶段vm.el虽已完成DOM初始化,但并未挂载在el选项上

beforeMount -> mounted

  • 此阶段vm.el完成挂载,vm.$el生成的DOM替换了el选项所对应的DOM

mounted

  • vm.el已完成DOM的挂载与渲染,此刻打印vm.$el,发现之前的挂载点及内容已被替换成新的DOM

beforeUpdate

  • 更新的数据必须是被渲染在模板上的(eltemplaterender之一)
  • 此时view层还未更新
  • 若在beforeUpdate中再次修改数据,不会再次触发更新方法

updated

  • 完成view层的更新
  • 若在updated中再次修改数据,会再次触发更新方法(beforeUpdateupdated

beforeDestroy

  • 实例被销毁前调用,此时实例属性与方法仍可访问

destroyed

  • 完全销毁一个实例。可清理它与其它实例的连接,解绑它的全部指令及事件监听器
  • 并不能清除DOM,仅仅销毁实例

使用场景

生命周期描述
beforeCreate执行时组件实例还未创建,通常用于插件开发中执行一些初始化任务
created组件初始化完毕,各种数据可以使用,常用于异步数据获取
beforeMount未执行渲染、更新,dom未创建
mounted初始化结束,dom已创建,可用于获取访问数据和dom元素
beforeUpdate更新前,可用于获取更新前各种状态
updated更新后,所有状态已是最新
beforeDestroy销毁前,可用于一些定时器或订阅的取消
destroyed组件已销毁,作用同上

数据请求在created和mouted的区别

created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成;mounted是在页面dom节点渲染完毕之后就立刻执行的。触发时机上created是比mounted要更早的,两者的相同点:都能拿到实例对象的属性和方法。 讨论这个问题本质就是触发的时机,放在mounted中的请求有可能导致页面闪动(因为此时页面dom结构已经生成),但如果在页面加载前完成请求,则不会出现此情况。建议对页面内容的改动放在created生命周期当中

为什么vue中的v-if和v-for不建议一起使用?

 v-if指令用于条件性的渲染一块内容,这块内容只会在指令的表达式返回为true值时候被渲染

v-for指令基于一个数组来渲染一个列表,v-for指令需要使用item in items形式的特殊语法,其中 items 是源数据数组或者对象,而 item 则是被迭代的数组元素的别名

在 v-for 的时候,建议设置key值,并且保证每个key值是独一无二的,这便于diff算法进行优化

优先级:

v-if与v-for都是vue模板系统中的指令,在vue模板编译的时候,会将指令系统转换成可执行的render函数

v-for的优先级高于v-if

注意事项:

永远不要把v-if和v-for同时 用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)

如果避免出现这种情况,则在外层嵌套template(页面渲染不生成dom节点),在这一层进行v-if判断,然后在内部进行v-for循环

如果条件出现在循环内部,可通过计算属性computed提前过滤掉那些不需要显示的项

SPA首屏加载速度慢怎么解决?

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

加载速度慢的原因?

  • 网络延时问题
  • 资源文件体积是否过大
  • 资源是否重复发送请求去加载了
  • 加载脚本的时候,渲染内容堵塞了

解决方案

减小入口文件体积:常用的就是路由懒加载

静态资源本地缓存:采用http缓存,采用Service Worker离线缓存,合理使用本地存储,前端合理利用localStorage

ui框架按需加载:elementui antd

图片资源的压缩:对图片进行适当压缩

组件重复打包:在webpackconfig文件中,修改CommonsChunkPlugin的配置

开启GZip压缩:拆包之后,在使用gzip做压缩

使用SSR:也就是服务端渲染,组件或页面通过服务器生成html字符串,再发送到浏览器

为什么data属性是一个函数而不是一个对象? 

 vue实例的时候定义data属性既可以是一个对象,也可以是一个函数

组件中定义data属性,只能是一个函数,如果直接定义为一个对象,会得到警告信息

  • 根实例对象data可以是对象也可以是函数(根实例是单例),不会产生数据污染情况
  • 组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数都会返回全新data对象

动态给vue的data添加一个新的属性时会发生什么?怎样解决?

数据更新了,但是页面没有进行更新操作

vue2是通过Object.defineProperty实现数据响应式,当我们访问foo属性或者设置foo值得时候能够触发setter和getter,但是当我们添加新属性时,无法触发事件属性的拦截,原因是后面添加的属性没有通过Object.defineProperty设置成响应式数据

解决方案

  • Vue.set():Vue.set( target, propertyName/index, value )通过Vue.set向响应式对象中添加一个property,并确保这个新 property同样是响应式的,且触发视图更新
  • Object.assign()直接使用Object.assign()添加到对象的新属性不会触发更新
  • $forcecUpdated() $forceUpdate迫使Vue 实例重新渲染

vue中组件和插件有什么区别?

组件:

 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式,在Vue中每一个.vue文件都可以视为一个组件

组件优势:

  • 降低整个系统的耦合度,在保持接口不变的情况下,我们可以替换不同的组件快速完成需求,例如输入框,可以替换为日历、时间、范围等组件作具体的实现

  • 调试方便,由于整个系统是通过组件组合起来的,在出现问题的时候,可以用排除法直接移除组件,或者根据报错的组件快速定位问题,之所以能够快速定位,是因为每个组件之间低耦合,职责单一,所以逻辑会比分析整个系统要简单

  • 提高可维护性,由于每个组件的职责单一,并且组件在系统中是被复用的,所以对代码进行优化可获得系统的整体升级

插件

插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制

  • 添加全局方法或者属性。如: vue-custom-element
  • 添加全局资源:指令/过滤器/过渡等。如 vue-touch
  • 通过全局混入来添加一些组件选项。如vue-router
  • 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
  • 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如vue-router

区别:

编写形式

编写组件:编写一个组件,可以有很多方式,vue单文件格式,template属性编写一个组件

编写插件:vue插件的实现应该暴露一个 install 方法。这个方法的第一个参数是 Vue 构造器,第二个参数是一个可选的选项对象

注册形式

vue组件注册主要分为全局注册与局部注册,全局注册通过Vue.component方法,第一个参数为组件的名称,第二个参数为传入的配置项

局部注册只需在用到的地方通过components属性注册一个组件

插件注册:插件的注册通过Vue.use()的方式进行注册(安装),第一个参数为插件的名字,第二个参数是可选择的配置项

注意:注册插件的时候,需要在调用 new Vue() 启动应用之前完成

使用场景

组件 (Component) 是用来构成你的 App 的业务模块,它的目标是 App.vue

插件 (Plugin) 是用来增强你的技术栈的功能模块,它的目标是 Vue 本身

vue组件之间通信方式有哪些?

 都知道组件是vue最强大的功能之一,vue中每一个.vue我们都可以视之为一个组件通信指的是发送者通过某种媒体以某种格式来传递信息到收信者以达到某个目的。广义上,任何信息的交通都是通信组件间通信即指组件(.vue)通过某种方式来传递信息以达到某个目的举个栗子我们在使用UI框架中的table组件,可能会往table组件中传入某些数据,这个本质就形成了组件之间的通信

组件通信解决了什么问题?

 组件间的数据是无法共享的但实际开发工作中我们常常需要让组件之间共享数据,这也是组件通信的目的要让它们互相之间能进行通讯,这样才能构成一个有机的完整系统

组件通信的分类 

  • 父子组件之间的通信
  • 兄弟组件之间的通信
  • 祖孙与后代组件之间的通信
  • 非关系组件间之间的通信

通信方案

通过 props 传递:父传子,子传父通信

  • 适用场景:父组件传递数据给子组件
  • 子组件设置props属性,定义接收父组件传递过来的参数
  • 父组件在使用子组件标签中通过字面量来传递值

通过 $emit 触发自定义事件:

  • 适用场景:子组件传递数据给父组件
  • 子组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
  • 父组件绑定监听器获取到子组件传递过来的参数

使用 ref

  • 父组件在使用子组件的时候设置ref
  • 父组件通过设置子组件ref来获取数据

EventBus

  • 使用场景:兄弟组件传值
  • 创建一个中央事件总线EventBus
  • 兄弟组件通过$emit触发自定义事件,$emit第二个参数为传递的数值
  • 另一个兄弟组件通过$on监听自定义事件

$parent 或$root

  • 通过共同祖辈$parent或者$root搭建通信桥连

兄弟组件

this.$parent.on('add',this.add)

另一个兄弟组件

this.$parent.emit('add')

attrs 与 listeners

  • 适用场景:祖先传递数据给子孙
  • 设置批量向下传属性$attrs和 $listeners
  • 包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。
  • 可以通过 v-bind="$attrs" 传⼊内部组件

Provide 与 Inject

  • 在祖先组件定义provide属性,返回传递的值
  • 在后代组件通过inject接收组件传递过来的值

Vuex

  • 适用场景: 复杂关系的组件数据传递

  • Vuex作用相当于一个用来存储共享变量的容器

  • state用来存放共享变量的地方

  • getter,可以增加一个getter派生状态,(相当于store中的计算属性),用来获得共享变量的值

  • mutations用来存放修改state的方法。

  • actions也是用来存放修改state的方法,不过action是在mutations的基础上进行。常用来做一些异步操作

双向数据绑定

 我们先从单向绑定切入单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新双向绑定就很容易联想到了,在单向绑定的基础上,用户更新了ViewModel的数据也自动被更新了

双向数据绑定的原理

双向数据绑定由三个部分构成:数据层,视图层,业务逻辑层

MVVM这里的控制层的核心功能便是 “数据双向绑定” 。自然,我们只需弄懂它是什么,便可以进一步了解数据绑定的原理

双向数据绑定的实现

先创建一个构造函数,执行初始化,对data执行响应化处理

vue中的$nextTick有什么作用?

 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

可以理解为,vue再更新DOM时是异步执行的,当数据发生变化时,vue将开启一个异步更新队列,视图需要等待队列中所有数据变化完成之后,再统一进行更新

为什么要有$nextTick?

如果没有 nextTick 更新机制,那么 num 每次更新值都会触发视图更新(上面这段代码也就是会更新10万次视图),有了nextTick机制,只需要更新一次,所以nextTick本质是一种优化策略

使用场景 

如果想要在修改数据后立即得到更新后的DOM结构,可以使用Vue.nextTick()

第一个参数是一个回调函数(可以获取最近的DOM结构)

第二个参数为:执行函数的上下文

实现原理

  1. 把回调函数放入callbacks等待执行
  2. 将执行函数放到微任务或者宏任务中
  3. 事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调

 对vue中mixin的理解?有什么场景

Mixin是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类

Mixin类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂

本质就是一个js对象,它可以包含我们组件中任意功能选项

vue中可以局部混入和全局混入

局部混入:

  •  定义一个mixin对象,有组件optionsdatamethods属性
  • 组件通过mixins属性调用mixin对象
  • 该组件在使用的时候,混合了mixin里面的方法,在自动执行created生命钩子,执行hello方法

全局混入

  • 通过Vue.mixin()进行全局的混入
  • 使用全局混入需要特别注意,因为它会影响到每一个组件实例(包括第三方组件)
  • PS:全局混入常用于插件的编写

注意事项:

当组件存在与mixin对象相同的选项的时候,进行递归合并的时候组件的选项会覆盖mixin的选项

但是如果相同选项为生命周期钩子的时候,会合并成一个数组,先执行mixin的钩子,再执行组件的钩子

使用场景

在开发中,我们经常会遇到在不同的组件中经常回需要用到一些相同或者相似的代码,这些代码的功能相对独立,我们就可以通过vue的mixin提取出来

 谈谈你对slot的理解

 Slot 艺名插槽,花名“占坑”,我们可以理解为solt在组件模板中占好了位置,当使用该组件标签时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置),作为承载分发内容的出口

使用场景

通过插槽可以让用户拓展组件,去更好的复用组件和做定制化处理

如果父组件在使用到一个复用组件时,获取这个组件在不同的地方有少量的更改,如果去重写组件是不明智的选择

这时我们就可以使用插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用

比如布局组件,表格列,下拉选项,弹框显示内容等

分类

默认插槽:

  • 子组件用<slot>标签来确定渲染的位置,标签里面可以放DOM结构,当父组件使用的时候没有往插槽传入内容,标签内DOM结构就会显示在页面
  • 父组件在使用的时候,直接在子组件的标签内写入内容即可

具名插槽

  • 子组件用name属性来表示插槽的名字,不传为默认插槽
  • 父组件中在使用时在默认插槽的基础上加上slot属性,值为子组件插槽name属性值

作用域插槽 

  • 子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件v-slot接受的对象上
  • 父组件中在使用时通过v-slot:(简写:#)获取子组件的信息,在内容中使用

总结 

  • v-slot属性只能在<template>上使用,但在只有默认插槽时可以在组件标签上使用
  • 默认插槽名为default,可以省略default直接写v-slot
  • 缩写为#时不能不写参数,写成#default
  • 可以通过解构获取v-slot={user},还可以重命名v-slot="{user: newName}"和定义默认值v-slot="{user = '默认值'}"

谈谈你对Observable的理解?

翻译过来就是可观察的

 Vue.observable,让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象

返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器

使用场景

在非父子组件通信时,可以使用通常的bus或者使用vuex,但是实现的功能不是太复杂,而使用上面两个又有点繁琐。这时,observable就是一个很好的选择

谈谈你对vue中key中的理解?

key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点

当我们在使用v-for时,需要给单元加上key

  • 如果不用key,Vue会采用就地复地原则:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。

  • 如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed

  • 当拥有新值的rerender作为key时,拥有了新key的Comp出现了,那么旧key Comp会被移除,新key Comp触发渲染

 设置key值一定能提高diff效率吗?

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

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升

说一下对keep-alive的理解?

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

keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁他们

keep-alive可以设置props属性:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存

  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存

  • max - 数字。最多可以缓存多少组件实例

  • 设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activateddeactivated):

  • 首次进入组件时:beforeRouteEnter > beforeCreate > createdmounted > activated > ... ... > beforeRouteLeave > deactivated

  • 再次进入组件时:beforeRouteEnter >activated > ... ... > beforeRouteLeave > deactivated

使用场景 

当我们在某些场景下不需要让页面重新加载时我们可以使用keep-alive

 当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive

在路由中设置keepAlive属性判断是否需要缓存

Vue中常用的修饰符有哪些?有什么作用?

在程序世界里,修饰符是用于限定类型以及类型成员的声明的一种符号

Vue中,修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理

vue的修饰符分为五种:

表单修饰符

在我们填写表单的时候用得最多的是input标签,指令用得最多的是v-model

  • lazy:在我们填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步
  • trim:自动过滤用户输入的首空格字符,而中间的空格不会过滤
  • number:自动将用户的输入值转为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值

事件修饰符

  • stop:阻止了事件冒泡,相当于调用了event.stopPropagation方法
  • prevent:阻止了事件的默认行为,相当于调用了event.preventDefault方法
  • self:只当在 event.target 是当前元素自身时触发处理函数
  • once:绑定了事件以后只能触发一次,第二次就不会触发
  • capture:使事件触发从包含这个元素的顶层开始往下触发
  • passive:在移动端,当我们在监听元素滚动事件的时候,会一直触发onscroll事件会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符
  • native:让组件变成像html内置标签那样监听根元素的原生事件,否则组件上使用 v-on 只会监听自定义事件

鼠标按键修饰符

  • left 左键点击
  • right 右键点击
  • middle 中键点击

键值修饰符

  • 普通键(enter、tab、delete、space、esc、up...)
  • 系统修饰键(ctrl、alt、meta、shift...)

v-bind修饰符 

  • async:能对props进行一个双向绑定

使用async需要注意以下两点:

  • 使用sync的时候,子组件传递的事件名格式必须为update:value,其中value必须与子组件中props中声明的名称完全一致

  • 注意带有 .sync 修饰符的 v-bind 不能和表达式一起使用

  • 将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的

  • prop:设置自定义标签属性,避免暴露数据,防止污染HTML结构
  • camel:将命名变为驼峰命名法,如将view-Box属性名转换为 viewBox

应用场景

  • .stop:阻止事件冒泡
  • .native:绑定原生事件
  • .once:事件只执行一次
  • .self :将事件绑定在自身身上,相当于阻止事件冒泡
  • .prevent:阻止默认事件
  • .caption:用于事件捕获
  • .once:只触发一次
  • .keyCode:监听特定键盘按下
  • .right:右键

自定义指令?自定义指令使用场景有哪些?

指令系统是计算机硬件的语言系统,也叫机器语言,它是系统程序员看到的计算机的主要属性。因此指令系统表征了计算机的基本功能决定了机器所要求的能力

vue中提供了一套为数据驱动视图更为方便的操作,这些操作被称为指令系统

v-开头的行内属性,都是指令,不同的指令用于完成不同的功能

//会实例化一个指令,但这个指令没有参数 
`v-xxx`

// -- 将值传到指令中
`v-xxx="value"`  

// -- 将字符串传入到指令中,如`v-html="'<p>内容</p>'"`
`v-xxx="'string'"` 

// -- 传参数(`arg`),如`v-bind:class="className"`
`v-xxx:arg="value"` 

// -- 使用修饰符(`modifier`)
`v-xxx:arg.modifier="value"` 

实现方式

 注册分为全局注册和局部注册

全局注册主要是通过Vue.directive方法进行注册

Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数

局部注册通过在组件options选项中设置directive属性

然后你可以在模板中任何元素上使用新的 v-focus property

应用场景

使用自定义指令可以满足我们日常一些场景,这里给出几个自定义指令的案例:

  • 表单防止重复提交
  • 图片懒加载
  • 一键 Copy的功能

谈谈对vue中过滤器的了解?应用场景有哪些?

过滤器就是把我们不想要或者是不必要的东西过滤掉

过滤器实质不改变原始数据,只是对数据进行加工处理后返回过滤后的数据再进行调用处理,可以理解为是一个纯函数

使用 

过滤器可以用在两个地方,双花括号插值和v-bind表达式,过滤器应该被添加在javascript表达式尾部,由管道符号指示

<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

 过滤器可以进行串联,有全局过滤器和局部过滤器,当全局过滤器和局部过滤器重名时,采用局部过滤器

  • 局部过滤器优先于全局过滤器被调用
  • 一个表达式可以使用多个过滤器。过滤器之间需要用管道符“|”隔开。其执行顺序从左往右

应用场景 

 单位转换、数字打点、文本格式化、时间格式化之类的等

什么是虚拟DOM?如何实现?说一下实现思路?

虚拟Dom是对真实dom的抽象,以Javscript对象作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上

创建虚拟dom是为了更好的将虚拟的节点渲染到页面视图中,所以虚拟dom对象的节点与真实dom的属性一一照应

为什么需要虚拟dom 

dom是很慢的,而且其元素非常庞大,页面的性能问题,大部分都是由dom操作引起的

真实的dom节点,哪怕是最简单的div也包裹着很多属性

操作真实dom代价非常昂贵,频繁操作dom还是会引起页面卡顿,影响用户体验

使用: 

  • 构造子类构造函数Ctor
  • installComponentHooks安装组件钩子函数
  • 实例化 vnode

vue的diff算法使用?

diff 算法是一种通过同层的树节点进行比较的高效算法

其有两个特点:

  • 比较只会在同层级进行, 不会跨层级比较
  • 在diff比较的过程中,循环从两边向中间比较

diff 算法在很多场景下都有应用,在 vue 中,作用于虚拟 dom 渲染成真实 dom 的新旧 VNode 节点比较

diff整体策略为:深度优先,同层比较

  1. 比较的过程中,循环从两边向中间收拢
  2. 比较只会在同层级进行, 不会跨层级比较

vue项目中有封装过axios吗?主要是哪方面?

axios是一个轻量的HTTP客户端

他是基于XMLHttpRequest服务来执行HTTP请求,支持丰富的配置,支持Promise,支持浏览器端和Node.js端,axios已经成为大部分vue开发的首选

特性

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON 数据
  • 客户端支持防御XSRF

 为什么要进行封装

axios 的 API 很友好,你完全可以很轻松地在项目中直接使用。

不过随着项目规模增大,如果每发起一次HTTP请求,就要把这些比如设置超时时间、设置请求头、根据项目环境判断使用哪个请求地址、错误处理等等操作,都需要写一遍

这种重复劳动不仅浪费时间,而且让代码变得冗余不堪,难以维护。为了提高我们的代码质量,我们应该在项目中二次封装一下 axios 再使用

如何封装

在封装的同时,我们需要和后端协商好一些约定,请求头,状态码,请求超时的时间

设置接口请求前缀:根据开发、测试、生产环境的不同,前缀需要加以区分

请求头 : 来实现一些具体的业务,必须携带一些参数才可以请求(例如:会员业务)

状态码: 根据接口返回的不同status , 来执行不同的业务,这块需要和后端约定好

请求方法:根据getpost等方法进行一个再次封装,使用起来更为方便

请求拦截器: 根据请求的请求头设定,来决定哪些请求可以访问

响应拦截器: 这块就是根据 后端`返回来的状态码判定执行不同业务

axios的原理?

 

SSR解决了什么问题,如何实现的? 

Server-Side Rendering 我们称其为SSR,意为服务端渲染

指由服务侧完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程

先来看看Web3个阶段的发展史:

  • 传统服务端渲染SSR
  • 单页面应用SPA
  • 服务端渲染SSR

Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序

服务器渲染的 Vue.js 应用程序也可以被认为是"同构"或"通用",因为应用程序的大部分代码都可以在服务器和客户端上运行

我们从上面解释得到以下结论:

  • Vue SSR是一个在SPA上进行改良的服务端渲染
  • 通过Vue SSR渲染的页面,需要在客户端激活才能实现交互
  • Vue SSR将包含两部分:服务端渲染的首屏,包含交互的SPA

解决了什么问题?

  • seo:搜索引擎优先爬取页面HTML结构,使用ssr时,服务端已经生成了和业务想关联的HTML,有利于seo
  • 首屏呈现渲染:用户无需等待页面所有js加载完成就可以看到页面视图(压力来到了服务器,所以需要权衡哪些用服务端渲染,哪些交给客户端

但是他也有一定的缺点:

复杂度

库的支持性,代码兼容

性能问题

服务器负载变大,相对于前后端分离服务器只提供静态资源来说,服务器负载更大,所以要慎重使用

在使用SSR之前,我们需要了解到SEO的页面是否只有少数几个,是否可以使用预渲染,

首屏的请求响应逻辑是否复杂,数据返回是否大量且缓慢

说一下vue的项目目录,如果是大型项目该如何划分结构和组件?

首先我们要了解为什么要划分结构,项目结构清晰会提高我们的开发效率,熟悉项目的各种配置会让我们开发效率更高

在划分项目结构的时候,需要遵守一些规则:

文件夹和文件夹的内部文件的语义一致性

单一的入口/出口:这样引用的好处就是无论文件夹内部多么混乱,外部引用时,都是从一个入口文件引入,这样就很好的实现了隔离,如果后续有重构的需求,更加高效

就近原则,紧耦合的文件应该放到一起,且应以相对路径引用

公共的文件就应该以绝对路径的方式从根目录引用

/src外的文件不应该被引入:vue-cli脚手架已经帮我们做了相关的约束了,正常的前端项目都会有一个src文件夹,里面放着的所有项目需要的资源,项目的配置,依赖,环境等文件

vue的权限管理怎么做?如果控制到按钮级别的权限怎么做? 

权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源

前端的权限归根结底是请求的发起权,请求的发起可能是由两种形式触发

页面加载触发

页面上的按钮点击触发

对触发权限的源头进行控制,最终要实现的目标是:

路由方面,用户登录之后只能看到自己有权限访问的导航菜单

视图方面:用户只能看到自己有权浏览的内容和有权操作的控件

如何做? 

前端权限控制可以分为四个方面:

接口权限:一般通过jwt进行验证,登录拿到token,将token存起来,通过axios请求拦截器进行拦截,每次请求的时候头部携带token

按钮权限:v-if判断 自定义指令

菜单权限:菜单权限可以理解成将页面与理由进行解耦(菜单和路由都由后端返回,菜单和路由分离,菜单由后端返回)

路由权限:初始化挂载全部路由,并且在路由上标记相应的权限信息

初始化的时候先挂载不需要权限控制的路由

vue是怎么解决跨域的?

跨域的本质是浏览器基于同源策略的一种安全手段

同源策略是一种约定,他是浏览器最核心也是最基本的安全功能

所谓同源:协议,主机,端口相同

 一定要注意跨域是浏览器的限制,你用抓包工具抓取接口数据,是可以看到接口已经把数据返回回来了,只是浏览器的限制,你获取不到数据。用postman请求接口能够请求到数据。这些再次印证了跨域是浏览器的限制

如何解决? 

jsonp:jsonp有一个缺点,只能发送get请求

cors:跨域资源共享,是一个系统,它是由一系列传输的HTTP头组成

proxy: 网络代理,是一种特殊的网络服务

vue项目本地开发完成后部署到服务器后报404是什么原因?

前后端是独立部署的,前端只需要将最后的构建物上传至目标服务器的web容器指定的静态目录下即可

404问题

HTTP404错误意味着连接指向的资源不存在

问题在于为什么不存在?为什么只有history模式下会出现这个问题?

vue属于 单页应用,而SPA是一种网络应用程序或网站的模型,所有用户交互是可以通过动态重写当前页面,前面我们也看到了,不管我们应用有多少页面,构建物都只会产生出一个index.html

为什么hsah模式下没有问题?

hash下我们用符号#表示,hash模式下,仅hash符号之前的内容会被包含在请求中,在请求中,即使没有配置location,也不会返回404

 如何解决vue项目中的错误?

错误类型:

代码本身逻辑错误:全局错误处理函数

后端接口错误 :通过axios实现网络请求前添加一层拦截

  • handleError在需要捕获异常的地方调用,首先获取到报错的组件,之后递归查找当前组件的父组件,依次调用errorCaptured 方法,在遍历调用完所有 errorCaptured 方法或 errorCaptured 方法有报错时,调用 globalHandleError 方法
  • globalHandleError调用全局的 errorHandler 方法,再通过logError判断环境输出错误信息
  • invokeWithErrorHandling更好的处理异步错误信息
  • logError判断环境,选择不同的抛错方式。非生产环境下,调用warn方法处理错误

vue3了解过吗?跟vue2有什么区别?

vue3利用信的语言特性(es6)

解决框架问题

vue3的新特性: 

  • 速度更快:重写了虚拟dom,编译模板的实现,更高效的组件实例化,SSR速度提高,ubdate性能提高
  • 体积减少:使用webpack打包,
  • 更易维护:可与现有的Options API一起使用,灵活的逻辑组合与复用,vue3可以和其他框架搭配使用
  • 更接近原生:可以之定义Api
  • 更易使用:响应式,将Api暴露出来,轻松识别组件重新渲染

vue新增的特性

  • framents:组件支持有多个根节点
  • Teleport:Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术,就有点像哆啦A梦的“任意门”
  • composition Api:composition Api,也就是组合式api,通过这种形式,我们能够更加容易维护我们的代码,将相同功能的变量进行一个集中式的管理
  • createRenderer:通过createRenderer,我们能够构建自定义渲染器,我们能够将 vue 的开发模型扩展到其他平台

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值