前端面试题整理 - vue

1、new Vue() 发生了什么

   New Vue() 是实例化一个Vue 对象
   在构造函数中执行_init(options),随后导入Mixin,进行实例化的初始化过程
1、initMixin(Vue)  //options初始化
2、StateMixin(Vue) //状态props、state、computed、watch
3、eventMixin(Vue) //事件
4、lifeCycleMixin(Vue) //生命周期
5、renderMixin(Vue) //页面渲染
initLifeCycle : 初始化生命周期
initEvents:初始化事件
initRender:渲染页面
callHook(vm,’beforeCreate’) beforeCreate钩子函数
initState: 初始化状态 props data computed watch methods
callHook(vm,’created’) created 钩子函数

双向绑定:initState 里的initData
Proxy和 Observe:
Proxy 将key做代理,间接调用
Observe 做一个数据监听,订阅者Object.defineProperty 在存取值可以添加依赖进行操作,在复制是通知订阅者进行依赖更新

2、对 SPA 单页面应用的理解,优缺点是什么?

   SPA 即( single-page application )仅在Web页面初始化加载相应的HTML、CSS和JavaScript。
一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转;
而是通过路由机制来实现HTML内容的变换,UI与用户的交互,避免页面的重新加载。
优点:1. 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
2. SPA相对服务器压力小;
3. 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责处理数据;
缺点:1. 首屏(初次)加载慢:为实现单页面Web应用功能和显示效果,需要在加载资源的时候将CSS和JavaScript统一加载,部分页面按需加载;
2. 不利于SEO:由于所有的内容都在一个页面中动态替换显示,所以在SEO上有着天然的弱势。

3、 Vue.use是干什么的?原理是什么?

Vue.use()是用来使用插件的,需要在new Vue()之前完成
插件的作用:插件通常用来为Vue添加全局功能,插件的功能没有严格的限制,一般有以下几种:
添加全局方法或property,如:vue-custom-element
添加全局资源:指令、过滤器、过度等,如:vue-touch
通过全局混入来添加一些组件选项,如: vue-router
添加Vue实例方法,通过把它们添加到Vue.prototype上实现
一个库,提供自己的API,同时提供上边的一种或几种功能,如: vue-router

Vue.use的参数必须是一个Object对象或者function函数,如果是对象的话,必须要提供install方法,之后会将Vue作为参数传入
Vue.use的参数为函数时,这个函数的参数是 Vue对象
Vue.use的参数为对象时,install方法的参数是Vue对象

4、vue set方法的实现原理

  Object.defineProperty()这个方法对对象的属性方法的添加或者删除不能做到实时的监听,数组通过索引去 修改数组都是不能被检测?所以vue实现了set方法,那么实现的set方法的原理是什么呢?
  用法:向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性。

5、Vue中模板编译原理?

  第一步是将 模板字符串 转换成 element ASTs(解析器)
  第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
  第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)

6、ES6 Proxy 与 Object.defineProperty 的优劣对比?

    Proxy 的优势如下:
	Proxy 可以直接监听数组的变化
	Proxy 可以直接监听对象而非属性
	Proxy 有 13 种拦截方法,比 Object.defineProperty 要更加丰富的多
	兼容性不好
	Object.defineProperty 的优势如下:
	兼容性好
	Object.defineProperty (obj, prop, descriptor) 的问题主要有三个
	  无法监听数组的变化
	必须遍历对象的每个属性
	必须深层遍历嵌套的对象

7、 Vue3.x响应式数据原理

Vue2.0  object.defineProperty
Vue3.0  proxy

8、vue生命周期钩子是怎么实现的?

处理生命周期的lifecycle.js中定义了一个callHook函数
export function callHook (vm: Component, hook: string) {
  const handlers = vm.$options[hook]
  if (handlers) {
    for (let i = 0, j = handlers.length; i < j; i++) {
      try {
        handlers[i].call(vm)
      } catch (e) {
        handleError(e, vm, `${hook} hook`)
      }
    }
  }
  if (vm._hasHookEvent) {
    vm.$emit('hook:' + hook)
  }
}
vue实例在各个生命周期阶段,都会去调用钩子callHook,当options中有对应的内容时,就会去运行相关的方法。

9、Vue 的父组件和子组件生命周期钩子执行顺序

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

10、 Vue中的组件的data 为什么是一个函数?

   组件是可以被复用的,那么注册了一个组件本质上就是创建了一个组件构造器的引用,而真正当我们使用组件的时候才会去将组件实例化
当我们使用组件的时候,虽然data是在构造器的原型链上被创建的,但是实例化的component1和component2确是共享同样的data对象,当你修改一个属性的时候,data也会发生改变

11、Vue 组件间通信有哪几种方式?

父子通信:父向子传递数据是通过 props,子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;v-bind=$attrs/v-on=$listeners
兄弟通信:Bus;Vuex
跨级通信:Bus;Vuex;provide / inject API、$attrs/$listeners

12、[vue] 组件中写name选项有什么作用?

项目使用keep-alive时,可搭配组件name进行缓存过滤
DOM做递归组件时需要调用自身name
vue-devtools调试工具里显示的组件名称是由vue中组件name决定的

13、keep-alive平时在哪里使用?原理是?

keep-alive用于保存组件的渲染状态,有两个钩子函数activated  deactivated
Include:这里定义的缓存  
Exclude:这里定义的不缓存
Max:定义最多缓存的数量

14、vue的mixin的理解和应用场景

mixin作为功能模块的使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂。
mixin(混入),提供了一种非常灵活的方式,来分发vue组件中的可复用功能。
其本质就是一个js对象,可以包含我们组件想要复用的任意功能和生命周期,如:data、created、methods、computed等等。
局部混入:
let myMixin = {
	created: function() {
		this.hello()
	},
	methods: {
		hello: function() {
			console.log('hello myMixin')
		}
	}
}
import myMixin from '@/mixin'
export default {
	mixins: [myMixin],
	data () {
		return {}
	}
}
全局混入:
let myMixin = {}
new Vue({
	i18n,
	router,
	mixins: [myMixin],
	render: h => h(App)
}).$mount('#app')
当组件存在与mixin对象相同的选项的时候,混入的时候组件的选项会覆盖mixin的选项
如果相同选项为生命周期钩子的时候,混入的时候会合并成一个数组,先执行mixin的钩子,再执行组件的钩子

15、Vue-router有几种钩子函数?具体是什么及执行流程是怎样的?

全局路由:
beforeEach(to,from,next):前置守卫
afterEach(to,from):后置钩子
路由独享的钩子:
    const router = new VueRouter({
    routes: [
      {
        path: '/foo',
        component: Foo,
        beforeEnter: (to, from, next) => {
         // ...
        }
      }
    ]
})
   组件内的导航钩子:
beforeRouteEnter(to,from,next):在渲染该组件的对应路由被 confirm 前调用
beforeRouteUpdate(to,from,next):在当前路由改变,但是该组件被复用时调用
beforeRouteLeave(to,from,next):导航离开该组件的对应路由时调用

16、nextTick在哪里使用?原理是?

场景:下次DOM更新循环结束之后执行的延迟回调,需要在视图更新之后,基于新的视图进行操作,获取更新后的DOM
原理:下次DOM更新循环结束之后执行的延迟回调异步方法(promise, mutationObserver, setImmediate, setTimeout)
事件循环:Vue在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。

17、Vue 为什么需要虚拟DOM? 虚拟DOM的优劣如何?

用js对象来描述真实DOM,是对真实DOM的抽象,直接操作真实DOM效率低,用DOM操作转化为对象操作,最终通过diff算法比对差异更新DOM,虚拟DOM不依赖真实平台从而实现跨平台

18、Vue中key的作用和工作原理,说说你对它的理解

作用:为了高效的更新虚拟DOM
原理:通过key可以判断两个节点是否是同一个,避免更新不同的元素,提高效率,减少DOM操作量

19、Vue 中的diff原理

vue的diff算法是平级比较,不考虑跨级比较的情况。内部采用深度递归的方式 + 双指针的方式进行比较。

20、computed 和 watch 的区别和运用的场景?

computed: 计算属性。依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 监听数据的变化。更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
场景:1)当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
2)当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

21、如何理解自定义指令?

    指令的实现原理,可以从编译原理 =>代码生成=> 指令钩子实现进行概述
	1、在生成 ast 语法树时,遇到指令会给当前元素添加directives属性
	2、通过 genDirectives 生成指令代码
	3、在patch前将指令的钩子提取到 cbs中,在patch过程中调用对应的钩子。
	4、当执行指令对应钩子函数时,调用对应指令定义的方法

22、V-model的原理是什么?

v-model本质就是一个语法糖,可以看成是value + input方法的语法糖。可以通过model属性的prop和event属性来进行自定义。原生的v-model,会根据标签的不同生成不同的事件和属性。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
1)text 和 textarea 元素使用 value 属性和 input 事件;
2)checkbox 和 radio 使用 checked 属性和 change 事件;
3)select 字段将 value 作为 prop 并将 change 作为事件。

23、Vue性能优化

23.1 编码阶段
尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher;
如果需要使用v-for给每项元素绑定事件时使用事件代理;
SPA 页面采用keep-alive缓存组件;
在更多的情况下,使用v-if替代v-show;
key保证唯一;
使用路由懒加载、异步组件;
防抖、节流;
第三方模块按需导入;
长列表滚动到可视区域动态加载;
图片懒加载;

23.2 用户体验
骨架屏;
PWA; progressive  web app(渐进式web  App)
还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。

23.3  SEO优化
预渲染;prerender-spa-plugin
服务端渲染SSR;

23.4 打包优化
压缩代码;
Tree Shaking/Scope Hoisting;
使用cdn加载第三方模块;
多线程打包happypack;
splitChunks抽离公共文件;
sourceMap优化;

24、修饰符 .prevent .passive .native的区别以及用在哪里

 .prevent:阻止冒泡事件发生,某些标签有自己的默认事件,如a[href=”#”] button[type=’submit’]
 .passive:会执行默认方法,如@scroll  @touchmove
 .native: 给自定义的组件添加原生事件,可以理解为该修饰符的作用就是把一个vue组件转化为一个普通的HTML标签,并且该修饰符对普通HTML标签是没有任何作用的。

25、== 和 === 的区别,什么情况下用相等==?

:运算符称作相等,用来检测两个操作数是否相等,这里的相等定义的非常宽松,可以允许进行类型转换
===:用来检测两个操作数是否严格相等 1、对于string,number等基础类型, == 和 === 是有区别的 不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等
同类型比较,直接进行“值”比较,两者结果一样 2、对于Array,Object等高级类型, == 和 ===是没有区别的

26、typeof 和 instanceof的区别

typeof(x)   a instanceof array

27、this的各种情况?

1、以函数形式调用时,this永远是window
2、以方法形式调用时,this是调用方法的对象
3、以构造函数的形式调用时,this是被创建的那个对象
4、使用call和apply调用时,this是指定的那个对象
5、箭头函数:看外层是否有函数,有则是内部函数的this,没有则是window
6、特殊情况:this指向最后调用它的对象

28、

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值