Vue高频面试题整理-3

223 阅读6分钟

1、路由懒加载

Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入。


// 将
// import UserDetails from './views/userDetails.vue
// 替换成

const UserDetails = () => import('./views/userDetails.vue')
const router = createRouter({
    routes: [{ path: '/users/:id', component: UserDetails }]
})

2、用过插槽吗?用的是具名插槽还是匿名插槽

用过,都使用过。插槽相当于预留了一个位置,可以将我们书写在组件内的内容放入,写一个插槽就会将组件内的内容替换一次,两次则替换两次。为了自定义插槽的位置我们可以给插槽取名,它会根据插槽名来插入内容,一一对应。

举例来说,这里有一个 <FancyButton> 组件,可以像这样使用:

    <!-- tempTate -->
    
    <FancyButton>
       click me!  <!-- 插槽内容 -->
    </FancyButton>
    

<FancyButton> 的模板是这样的:

  <!-- tempTate -->
  
  <button cTass="fancy-btn">
     <slot></slot>  <!-- 插槽出口 -->
  </button>
        

3、Vue-loader解释一下

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

4、Vue和React中diff算法区别

vue和react的diff算法,都是忽略跨级比较,只做同级比较。vue diff时调动patch函数,参数是vnode和oldvnode,分别代表新旧节点。

1、vue对比节点。当节点元素相同,但是classname不同,认为是不同类型的元素,删除重建,而react认为是同类型节点,只是修改节点属性。

2、vue的列表对比,采用的是两端到中间比对的方式,而react采用的是从左到右依次对比的方式。当一个集合只是把最后一个节点移到了第一个,react会把前面的节点依次移动,而vue只会把最后一个节点移到第一个。总体上,vue的方式比较高效。

4、请你说一下Vue 中 create 和 mount 的区别

create为组件初始化阶段,在此阶段主要完成数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,此时还未生成真实的DOM,也就无法获取和操作DOM元素。而mount主要完成从虚拟DOM到真实DOM的转换挂载,此时html已经渲染出来了,所以可以直接操作dom节点。

5、axios是什么? 怎么使用? 描述使用它实现登录功能的流程?

axios 是请求后台资源的模块。 通过npm instal axios -S来安装,在大多数情况下我们需要封装拦截器,在实现登录的过程中我们一般在请求拦截器中来加入token,在响应请求器中通过判断后端返回的状态码来对返回的数据进行不同的处理。如果发送的是跨域请求,需在配置文件中 config/index.is 进行代理配置。


//添加一个请求拦截器
axios.interceptors.request.use((config) => {
  //在请求发出之前进行一些操作
  //do something...
  
  return config;
}, function (error) {
  return Promise.reject(error);
});

//添加一个响应拦截器
axios.interceptors.response.use((response) => {
  //在请求返回之前进行一些操作
  //do something...
  
  return response;
}, function (error) {
  return Promise.reject(error);
});

6、computed和watch的区别? watch实现原理? watch有几种写法?

计算属性computed:

1、支持缓存,只有依赖数据发生改变,才会重新进行计算。

2、不支持异步,当computed内有异步操作时无效,无法监听数据的变化。

3、computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值。

4、如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed。

5、如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

 computed: {
     //一个计算属性的 getter
     pubTishedBooksMessage() {
         //this 指向当前组件实例
         return this.author.books.length > 0 ? 'Yes' : 'No'
     }
 }
    

侦听属性watch:

1、不支持缓存,数据变,直接会触发相应的操作

2、watch支持异步

3、监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值

4、当一个属性发生变化时,需要执行对应的操作:一对多

5、监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数:

  • immediate:组件加载立即触发回调函数执行
  • deep:深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。

 watch: {
     //每当 question 改变时,这个函数就会执行
     question(newQuestion, oldQuestion) {
        if (newQuestion.includes('?')) {
            this.getAnswer();
        }
     }
 }
 
 watch: {
      someobject: {
          handler(newValue, oldvalue) {
              //注意: 在嵌套的变更中
              //只要没有替换对象本身
              //那么这里的newValue 和 oldvalue相同
          },
          deep: true
       }
 }
 

7、Vue $forceUpdate的原理

1、作用:

迫使 vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

2、内部原理:


Vue.prototype.$forceUpdate = function () {
    const vm: Component = this
    if (vm._watcher) {
        vm._watcher.update()
    }
}

实例需要重新渲染是在依赖发生变化的时候会通知watcher,然后通知watcher来调用update方法,就是这么简单。

8、 v-for key

  • key是为Vue中的vnode标记的唯一id,通过这个key,我们的diff操作可以更准确、更快速。
  • diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的key与旧节点进行比对,然后超出差异。

diff过程可以概括为: oldCh和newCh各有两个头尾的变量Startldx和Endldx,它们的2个变量相互比较,一共有4种比较方式。如果4种比较都没匹配,如果设置了key,就会用key进行比较,在比较的过程中,变量会往中间靠,一旦Startldx>Endldx表明oldCh和newCh至少有一个已经遍历完了,就会结束比较,这四种比较方式就是首、尾、旧尾新头、旧头新尾。

准确: 如果不加key,那么vue会选择复用节点(Vue的就地更新策略),导致之前节点的状态被保留下来,会产生一系列的bug.

快速: key的唯一性可以被Map数据结构充分利用,相比于遍历查找的时间复杂度 0(n),Map 的时间复杂度仅仅为O(1)。

9、为什么要设置key值,可以用index吗? 为什么不能?

vue中列表循环需加:key="唯一标识“ 唯一标识可以是item里面id index等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件,key的作用主要是为了高效的更新虚拟DOM。

写在最后

码字不易,谢谢关注、点赞和转发。

越笨拙,越努力; 越努力,越幸运; 大家加油!