前端面试题

1. Vue 实例的 data 属性,可以在哪些生命周期中获取到?

A. beforeCreate B. created C. beforeMount D. mounted

(b,c,d)

2. 下列对 Vue 原理的叙述,哪些是正确的?

A. Vue 中的数组变更通知,通过拦截数组操作方法而实现
B. 编译器目标是创建渲染函数,渲染函数执行后将得到 VNode 树
C. 组件内 data 发生变化时会通知其对应 watcher,执行异步更新
D. patching 算法首先进行同层级比较,可能执行的操作是节点的增加、删除和更新
(A,B,C,D)

3. 对于 Vue 中响应式数据原理的说法,下列哪项是不正确的?

A. 采用数据劫持方式,即 Object.defineProperty() 劫持 data 中各属性,实现响应式数据
B. 视图中的变化会通过 watcher 更新 data 中的数据
C. 若 data 中某属性多次发生变化,watcher 仅会进入更新队列一次
D. 通过编译过程进行依赖收集
(B D)

4. 下列说法不正确的是哪项?

A. key 的作用主要是为了高效地更新虚拟 DOM
B. 若指定了组件的 template 选项,render 函数不会执行
C. 使用 vm.$nextTick 可以确保获得 DOM 异步更新的结果
D. 若没有 el 选项,vm.$mount(dom) 可将 Vue 实例挂载于指定元素上
(B)


5. 下列关于 Vuex 的描述,不正确的是哪项?

A. Vuex 通过 Vue 实现响应式状态,因此只能用于 Vue

B. Vuex 是一个状态管理模式

C. Vuex 主要用于多视图间状态全局共享与管理

D. 在 Vuex 中改变状态,可以通过 mutations 和 actions

(C)

6. 关于 Vue 组件间的参数传递,下列哪项是不正确的?

A. 若子组件给父组件传值,可使用 $emit 方法
B. 祖孙组件之间可以使用 provide 和 inject 方式跨层级相互传值
C. 若子组件使用 $emit('say') 派发事件,父组件可使用 @say 监听
D. 若父组件给子组件传值,子组件可通过 props 接受数据
 (B)


7. 下列关于 vue-router 的描述,不正确的是哪项?

A. vue-router 的常用模式有 hash 和 history 两种

B. 可通过 addRoutes 方法动态添加路由

C. 可通过 beforeEnter 对单个组件进行路由守卫

D. vue-router 借助 Vue 实现响应式的路由,因此只能用于 Vue

(C)

8. 下列说法不正确的是哪项?

A. 可通过 this.$parent 查找当前组件的父组件

B. 可使用 this.$refs 查找命名子组件

C. 可使用 this.$children 按顺序查找当前组件的直接子组件

D. 可使用 $root 查找根组件,并可配合 children 遍历全部组件

(C)

9. 下列关于 v-model 的说法,哪项是不正确的?

A. v-model 能实现双向绑定

B. v-model 本质上是语法糖,它负责监听用户的输入事件以更新数据

C. v-model 是内置指令,不能用在自定义组件上

D. 对 input 使用 v-model,实际上是指定其 :value 和 :input

(C)

10. 关于 Vue 的生命周期,下列哪项是不正确的?

A. DOM 渲染在 mounted 中就已经完成了
B. Vue 实例从创建到销毁的过程,就是生命周期
C. created 表示完成数据观测、属性和方法的运算和初始化事件,此时 $el 属性还未显示出来
D. 页面首次加载过程中,会依次触发 beforeCreate,created,beforeMount,mounted,beforeUpdate,updated
(D)

10,vue2.0和vue3.0渲染器的Diff算法分别说一下

简单来说,diff算法有以下过程

1、 同级比较,再比较子节点

2、 先判断一方有子节点一方没有子节点的情况(如果新的children没有子节点,将旧的子节点移除)

3、 比较都有子节点的情况(核心diff)

4、 递归比较子节点

正常Diff两个树的时间复杂度是O(n^3),但实际情况下我们很少会进行跨层级的移动DOM,所以Vue将Diff进行了优化,从O(n^3) -> O(n),只有当新旧children都为多个子节点时才需要用核心的Diff算法进行同层级比较。

Vue2的核心Diff算法采用了双端比较的算法,同时从新旧children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。相比React的Diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。

Vue3.x借鉴了 ivi算法和 inferno算法

在创建VNode时就确定其类型,以及在mount/patch的过程中采用位运算来判断一个VNode的类型,在这个基础之上再配合核心的Diff算法,使得性能上较Vue2.x有了提升。(实际的实现可以结合Vue3.x源码看。)

该算法中还运用了动态规划的思想求解最长递归子序列。

(看到这你还会发现,框架内无处不蕴藏着数据结构和算法的魅力)

2.解释一下:响应式原理?

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty把这些 property 全部转为 getter/setter这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更,每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

3.vue有哪些缺点

  1. Vue 不能检测数组和对象的变化

4.为什么vue不能检测对象的变化

对于对象, Vue 无法检测 property 的添加或移除,由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的.

  • 追问:那如何解决上述问题?

使用this.$set(this.someObject,'b',2) 添加新的属性
使用this.$delete(this.someObject,'b') 删除旧属性

5.讲一下 $set 的实现原理

1、如果目标是数组,使用 vue 实现的变异方法 splice 实现响应式
2、如果目标是对象,判断属性存在,即为响应式,直接赋值
3、如果 target 本身就不是响应式,直接赋值
4、如果属性不是响应式,则调用 defineReactive 方法进行响应式处理


6.new Vue()实例中,data 可以直接是一个对象,为什么在 vue 组件中,data 必须是一个函数呢?

关键词:复用+污染 + 函数返回 + 数据拷贝

因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。

7.computed 和 watch 有什么区别?

computed 计算属性 :
依赖其它属性值,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值,如果和上次计算结果不一致,重新渲染页面。
watch 侦听器 : 更多的是「观察」的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。

追问:computed 和 watch 应用场景?
关键词 computed+缓存

computed :当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算。
watch: 当我们需要在数据变化时执行的操作时使用(如调用其它函数)

追问 :能使用箭头函数定义computed和watch吗?

不应该使用箭头函数来定义 watcher 函数,理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,为undefined

8.vue数据绑定是双向还是单向的

Vue 在不同组件间强制使用单向数据流。这使应用中的数据流更加清晰易懂。

9.v-model双向绑定的原理?

v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据.

Object.defineproperty()重新定义(set方法)对象设置属性值和(get方法)获取属性值的操纵来实现的.
1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

10.全局导航钩子函数应用场景?

vue router.beforeEach(全局前置守卫)router.beforeEach 是页面加载之前(before each)意思是在 每次每一个路由改变的时候都得执行一遍.
vue router.afterEach(全局后置守卫),相反router.afterEach是页面加载之后.

应用场景:

  1. 可进行一些页面跳转前处理,例如判断需要登录的页面进行拦截,做登录跳转!
    2.进入页面登录判断、管理员权限判断、浏览器判断

11.vue-loader是什么?它有什么作用?

解析和转换 .vue 文件,提取出其中的逻辑代码 script、样式代 码 style、以及 HTML 模版 template,再分别把它们交给对应的 Loader 去处理。

12.怎样动态加载路由?

通过router.addRoutes方法可以动态加载路由.

let router=new VueRouter({
       routes:[           
             {path:'/product',component:a,name:'product'} 
        ]
        });  
      router.addRoutes([     
         {path:'/user',component:c,name:'user'},       
         {path:'/address',component:address,name:'address'}  
       ]);

22.说说active-class是哪个组件的属性?

active-class是vue-router模块的router-link组件中的属性,用来设置选中连接的样式.

23.为什么vue使用异步更新组件?

收集当前的改动一次性批量更新,为了节省diff开销.

24.vuex中actions和mutations有什么区别?

1.mutations可以直接修改state,但只能包含同步操作,同时,只能通过提交commit调用.
2.actions可以包含异步操作,通过store.dispatch触发,不能直接修改数据,需要调用commit去修改数据.

25. 怎么监听vuex数据的变化?

通过watch监听数据的变化

watch:{ 
     '$store.state.test':function(value){    
          console.log('数据修改了',value) 
      }}

28.开启vuex中的严格模式有什么好处?

主要用户防止不合理的改变状态值如:this.$.store.state.list = [],这样就会抛出异常

A.在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
B. 不要在发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。

29.vue组件会在什么时候下被销毁?

1.页面关闭、
2.路由跳转、
3.v-if为false
4.改变key值

什么是插槽(slot)?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值