Vue2相关面试题(持续更新)

news2024/11/30 8:42:19

前言

  • 目前这套面试题只适合 初级前端,后面会进行深层次补充和拓展以及Vue2源代码的讲解(虽然Vue2今年开始不维护了,但是我的面试题不会止步,冲冲冲)。
  • 在面试的过程中,一定要清楚哪些该说哪些不该说,如果一个知识点不太清楚,就不要做过多的解释,一笔带过就可以。
  • 给孩子点点关注吧!😭
    image.png

Vue2相关面试题

1. 谈谈对Vue的理解

  • Vue是一种用于构建用户页面的渐进式JavaScript框架,也是一个创建SPA单页面应用的Web应用框架,Vue的核心是数据驱动试图,通过组件内特定的方法实现视图和模型的交互。

  • 特性:(看自己要不要对每一项特性进行解释,如果解释可能会牵扯出很多面试题)

    • 数据驱动试图

      • MVVM是一种双向数据绑定的模式,用ViewModel来建立起Model数据层和View视图层的连接,数据和视图的改变是双向的。
      • 可能会问:MVVM 和 MVC 的区别?(见4)
    • 组件开发

      • 组件可以在项目中直接进行复用,出现问题时可以实现快速定位,能够提高代码可复用性和可维护性。
      • 可能会问:如何封装一个组件?(见后面)
    • 指令系统

      • Vue内置很多 v- 系列的指令,可以响应式的作用于DOM,比如v-if条件渲染,v-for列表渲染,v-model双向数据绑定等。
      • 可能会问:自定义封装指令的一些知识(见后面)
  • 缺点

    • 不利于SEO优化:
      • 解决办法:
        • SSR服务器渲染;
        • 静态化;
        • 预渲染;
        • 使用Phantomjs针对爬虫做处理;
    • 首屏加载速度慢:加载时,将所有的css,js文件及逆行加载;
    • 不支持IE678(IE也不用了😂);
    • 有些数据不需要响应式,但必须写在data里,影响加载速度和性能;
    • Vue的响应式是通过Object.defineProperty:
      • 无法监听ES6的Set、Map变化;
      • 无法监听Class类型的数据;
      • 属性的新加或删除无法监听;
      • 数组元素的增加和删除无法监听;

2. Vue最大优势

  • 轻量级框架,简单易学,数据双向绑定,虚拟DOM,组件化;
  • 文档都是中文的,入门教程很多,上手简单;
  • Vue是单页面应用,使页面局部刷新,不用每次跳转页面都去请求所有的数据和DOM,加快了访问速度和提升用户体验;
  • 相比传统的页面通过超链接实现页面的切换和跳转,Vue使用路由,不会刷新页面;
  • 使用Vue编写出来的界面效果本身就是响应式的,这种网页在各种设备上都能显示出非常好看的效果;
  • 第三方UI库使用起来非常方便,节省了很多开发时间,从而提升了开发效率。

3. Vue 和 jQuery 的区别是什么?

  • jQuery:

    • 应该算是一个插件,里面封装了各种简单易用的方法,它的本质就是使用更少的代码操作DOM节点,它是使用选择器获取DOM对象,对其进行赋值、取值、事件绑定等操作,对数据的操作依赖于对应的DOM对象;
  • Vue:

    • 一套渐进式的框架,拥有自己的规则体系和语法,特别是MVVM的设计思想,让数据和视图进行双向绑定,极少操作DOM,对数据进行操作不再依赖于对应的DOM对象。

4. MVVM 和 MVC 区别是什么?

  • MVC:

    • 一种设计模式,是Model数据模型,View视图,Controller控制器,在控制器这层里面编写代码,控制数据和视图进行关联,MVC是单向通信;
  • MVVM:

    • 既Model-View-ViewModel的简写(模型-视图-视图模型),VM是整个设计模式的核心,是用来连接视图和模型的桥梁;

    • 有两个方向:

      • 首先:模型转换为视图,将从后端请求回来的数据转换为网页;
        • 实现方式:数据绑定;
      • 其次,视图转换为模型,将网页转化为后端的数据;
        • 实现方式:监听DOM事件。
      • 这两个方向都实现的,我们称为数据的双向绑定。
  • 区别:

    • MVC是单向通信,MVVM是双向通信;
    • 主要是MVC中的Controller演变成了MVVM中的VM,MVVM主要解决了MVC中大量的DOM操作导致的页面渲染性能降低,加载速度慢,影响用户体验。

5. Vue常用修饰符

  • 事件修饰符:
    .stop => 阻止事件冒泡
    .prevent => 阻止事件默认行为
    .once => 程序运行期间,事件处理函数只执行一次
    .native => 原生事件(使用组件库的时候可能会用到)
  • 按键修饰符:
    .enter ➡ 监测Enter键
    .esc ➡ 监测ESC
  • v-model修饰符:
    .number ➡ 尝试用parseFloat转数字
    .trim ➡ 去除字符串首尾两侧的空白字符
    .lazy ➡ 内容改变并且失去焦点触发
  • 特殊:
    .sync ➡ 可以在子组件内部直接修改父组件的值
    格式: 
        父组件:<子组件 变量名.sync="数据属性"/>
        this.$emit('update:对应的属性名', 值)
    注意:此处的  update:对应的属性名 不能有空格
    见下图

具体使用如下:

  • 父组件:
<template>
  <div class="home">
    <HelloWorld
      msg="Welcome to Your Vue.js App"
      :type.sync="type"
      :arr.sync="arr"
      :obj.sync="obj"
    />
  </div>
</template>

<script>
import HelloWorld from "@/components/HelloWorld.vue";

export default {
  name: "HomeView",
  data() {
    return {
      type: 1,
      arr: [1, 2, 3],
      obj: {
        a: 1,
        b: 2,
      },
    };
  },
  components: {
    HelloWorld,
  },
};
</script>
  • 子组件:
<template>
  <div class="hello">
    <button @click="updateData">改变数据</button>
    <span> {{ type }} </span>
    <span> {{ arr }} </span>
    <span> {{ obj }} </span>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  props: {
    type: {
      type: Number,
      require: true,
    },
    arr: {
      type: Array,
      require: true,
    },
    obj: {
      type: Object,
      require: true,
    },
  },
  methods: {
    updateData() {
      this.$emit("update:type", 2);
      this.$emit("update:arr", [4, 5, 6]);
      this.$emit("update:obj", {
        a: "张三",
        b: "李四",
      });
    },
  },
};
</script>

6. Vue常用指令

    v-bind:属性名 = "表达式"      ➡       给标签动态赋值
            简写::属性名 = "表达式"
            
    v-on:事件名 = "少量代码 / 函数名 / 函数名(实参)"      ➡       绑定事件
            简写: @事件名 = "少量代码 / 函数名 / 函数名(实参)"
    
    v-model = "表达式"      ➡       将表单元素的 value属性 和 Vue数据属性 进行双向绑定
            可以使用v-model语法糖实现组件传值
            
    v-for = "(值, 索引) in 目标结构"      ➡       循环列表
    
    v-show = "表达式"      ➡       控制元素显示隐藏
    
    v-if = "表达式"      ➡       控制元素显示隐藏
    
    v-slot      ➡       插槽

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

  • 共同点:

    • 都可以控制元素的显示和隐藏(效果一样);
  • 区别:

    • 原理不同:

      • v-show:本质就是通过CSS属性来让元素显示隐藏(display: none;);
      • v-if:动态的 向DOM树 添加 或 删除 元素;
    • 编译条件不同:

      • v-show:不管条件真假与否,都会编译,如果是false,会将display设置为none,但它也编译了;
      • v-if:初始值为false,就不会编译;
    • 性能不同:

      • v-show:
        • 只编译一次,后面就是控制CSS;
        • 产生更大的首次加载消耗;
      • v-if:
        • 不停的销毁和创建实例;
        • 产生更大的切换消耗;
    • 优先级不同:

      • v-if > v-show

8. 为什么避免 v-if 和 v-for 一起使用,非要在一起使用该怎么办?

  • Vue避免同时使用v-if和v-for是因为这样会影响性能。
  • 当v-if和v-for同时存在时,v-for会先执行,然后才考虑v-if条件。如果列表很长,这样会导致不必要的计算,影响渲染性能。
  • 一起使用:
    • 可以先写if,再使用template标签包裹需要循环的内容,讲循环写在template标签上;
    • 如果非要在一起使用,可以考虑使用计算属性来优化性能。计算属性可以先根据条件筛选出需要渲染的数据,然后再使用v-for渲染,这样可以避免不需要的计算和喧染,提高性能。
<template>
  <div>
    <div v-for="item in filteredList" :key="item.id">
      {{ item.name }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      list: [
        { id: 1, name: "Apple", show: true },
        { id: 2, name: "Banana", show: false },
        { id: 3, name: "Orange", show: true },
        { id: 4, name: "Grape", show: false },
      ],
    };
  },
  computed: {
    filteredList() {
      return this.list.filter((item) => item.show);
    },
  },
};
</script>

9. 数组更新有时候v-for不渲染

  • 因为Vue内部只能监测数组 顺序 / 位置 / 数量 的改变;

  • 如果是某个值被重新赋值或者使用了不改变原始数组的方法,Vue是监测不到的;

    • 可能会问:改变原始数组和不改变原始数组的方法有哪些?
  • 针对上述问题,有两种解决方案:

    • 某个值被重新赋值:
      • this.$set(更新的目标结构, 改变元素的索引 / 对象的属性, 更新的值)
    • 使用不改变原始数组的方法:
      • 用得到的新数组替换旧数组。

10. Vue中 key 的作用

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

  • key:

    • 一段唯一不重复的数字或字符串;
    • 为了更高效的更新虚拟DOM;
    • 是给v-for循环生成标签办法唯一标识的;
    • 只做数据展示,不写key是没有任何影响的;
    • key不会出现在真实DOM中;
  • 为什么不能使用索引?

    • 因为索引是连续的,如果删除其中一个会导致最后一个被删除;
    • 当我们再删除的时候,key再根据数据来把新旧的DOM做对比,删除key不存在的对应的标签。

11. diff算法比较机制

  • 根元素变化:

  • 根元素未变:

    • 顺序改变:
      • 更新属性;
    • 子元素/子元素内容改变:
      • 按照key比较,如果没有key或者key是索引,尝试就地更新;
      • 如果key是id,新旧虚拟DOM做对比,共有的部分不发生变化,没有的就在对应的位置插入DOM节点;
  • key使用规范:

    • 有id用id,没有id用索引;
    • 一段唯一不重复的数字或字符串。

12. 怎么自定指令,有哪些钩子函数,对应的有哪些入参?

  • 全局注册:
    • 在 Vue对象 的 directive 方法里面有两个参数,一个指令名称,一个回调 / 对象;
    • 如果是个对象,在对象内部必须指定 inserted方法。
    // 注册一个全局自定义指令 `v-focus`
    Vue.directive('focus', {
        // 当被绑定的元素插入到 DOM 中时……
        inserted: function (el) {
            // 聚焦元素
            el.focus()
        }
    })
  • 局部注册:
    • 组件中接受一个 directives选项。
    // 注册局部指令
    directives: {
        // 指令名
        focus: {
            // 指令的定义
            inserted: function (el) {
                el.focus()
            }
        }
    }
  • 钩子函数:
    bind()               ➡   只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置;
    inserted()           ➡   被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中);
    update()             ➡   所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前,指令的值可能发生变化,也肯能没有。但是你可以通过比较前后的值来忽略不必要的模板更新;
    componentUpdated()   ➡   指令所在组建的VNode及其子VNode全部更新后调用;
    unbind()             ➡   只调用一次,指令与该元素解绑时调用。
  • 钩子函数参数:
    image.png

13. 怎么封装一个组件,具体的过程是咋样的

  • 组件提升了整个项目的开发效率,能够把页面抽离成相对独立的模块。解决了传统项目开发过程中的效率低、难维护、复用性差等问题;

  • 组件的封装我们可以看作是一个函数的封装:

    • 根据业务需求,把页面中可复用的template、script、style,抽离到一个单独的 .vue文件 中,实现复用;
    • 上述步骤完成之后,还需要考虑入参和出参:
      • 入参:使用 props机制;
      • 出参:
        • 使用 $emit机制;
        • 使用 .sync修饰符(见5);
        • 使用 v-model语法糖实现;
      • 针对一些标签不确定的地方,我们可以使用插槽实现;
      • 至此,组件的封装完成。
  • 组件的使用步骤:

    • 封装组件;
    • 导入组件:
      • import 组件对象 from '组件路径'
    • 注册组件;
      • 全局注册:
        • Vue.component('组件名', 组件对象)
      • 局部注册(常用):
        • image.png
      • 使用组件:组件标签;

14. Vue组件中 data 为什么是个函数?

  • Vue中每个组件都是一个实例;
  • 组件共享data属性,当data的值是同一个引用数据类型的值时,改变其中一个其他的都会收到影响;
  • 组件中的data写成一个函数,数据以函数返回值的形式定义,这样每复用一次组件,就会返回一份最新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护自己的数据;
  • 单纯的写成对象的形式,就会使得所有的组件实例共享一份data,就会造成一变全变的结果。

15. Vue组件如何进行传值

  • props$emit:

    • 父组件向子组件传递数据通过 props 传递的;
    • 子组件传递数据给父组件是通过 $emit 触发事件;
  • attrs$listeners

  • 中央事件总线bus:

    • 上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系,这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit 触发事件,bus.$on 监听触发事件。
  • provideinject:

    • 父组件通过provider来提供变量,然后再子组件中通过inject来注入变量。不论子组件多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
  • v-model:

    • 父组件通过v-model传递值给子组件时,会自动传递一个 value 的prop属性,在子组件中通过 this.$emit('input', value) 自动修改v-model绑定的值,父组件中也不用定义input事件。
  • $parent$children

  • boradcastdispatch

  • Vuex:

    • Vuex主要处理组件之间的数据交互,如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这些方法可能不利于项目的维护,Vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

16. 组件中写 name 选项有什么用?

  • 项目中使用 keep-alive 时,可以搭配组件 name 进行组件的缓存;
  • 使用插槽时,name 属性可以作为占位标签的名字,供 template 使用;
  • Vue-devtools调试工具里显示的组件名称是由Vue组件内部的 name 属性决定的。

17. Vue该如何实现组件的缓存?

  • 为什么需要组件缓存?

    • 在面向组件开发中,会把整个项目拆分成多个业务组件,按照需求对组件进行整合;
    • 存在组件频繁切换的问题,在这个过程中,组件的实例都是在不断的销毁和创建,很是消耗性能,并且如果需要该组件的数据的话,我们是获取不到的,所以需要对组件的状态进行缓存。
  • 怎么实现组件的缓存?

    • 使用 keep-alive 标签包裹需要被缓存的组件,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染;
    • 优点:提高渲染性能,提升用户体验。

18. Vue中 keep-alive 的作用

  • keep-alive是Vue内置的一个组件,可以使被包裹的组件保留状态,或避免重新渲染。一旦使用keep-alive激活组件,此时mountedcreated等钩子函数只会在第一次进入组件时调用,当再次切换回来时将不会调用。此时如果我们还想在每次切换时做一些事情,就需要用到另外的周期函数,activeddeactived,这两个钩子函数只有被keep-alive包裹后才会调用。

19. 谈谈对 Vue 生命周期的理解

  • Vue实例从创建到销毁的整个过程,就是Vue的生命周期(四个阶段 + 八个钩子函数);

  • 初始化阶段:

    • beforeCreate():
      • 此时,data数据和methids方法还没有挂载到Vue实例身上,无法使用(如果使用了,会报错,undefined);
    • created():
      • data数据和methods方法已经挂载到Vue实例身上,可以正常使用;
      • 使用场景:发起异步请求(可以更早的获取数据,渲染页面);
  • 挂载阶段:

    • beforeMount():
      • 将App.vue文件中的所有标签编译完毕(知识编译完毕,还没有变成真实DOM);
    • mounted():
      • 虚拟DOM变成真实DOM,此时可以获取DOM节点;
  • 更新阶段:

    • beforeUpdate():、
      • data数据变化后更新,此时数据是最新的,但是DOM节点还不是最新的;
    • updated():
      • 当组件渲染完毕后执行,此时可以获取最新的DOM内容;
  • 销毁阶段:

    • beforeDestroy():
      • 这一步,Vue实例仍然可以使用;
    • destroyed():
      • 实例销毁后调用,该钩子函数被调用后,对应的Vue实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。
      • 使用场景:销毁定时器;
        • 单个定时器:直接调用 clearInterval()clearTimeout()进行销毁;
        • 多个定时器:在data声明一个对象,使用 Object.keys() 获取该对象的所有属性名,进行循环销毁。

20. 第一次页面加载会触发哪几个钩子函数?

  • beforeCreate()created()beforeMount()mounted()
  • 第一次页面加载需要将data数据和methods方法挂载到Vue实例上v,并且需要将虚拟DOM变成真实DOM。

21. 父组件嵌套一个子组件,第一次加载的时候,钩子函数的触发顺序

    父beforeCreate()父created()父beforeMount()子beforeCreate()子created()子beforeMount()子mounted() ➡父mounted()

22. 怎样理解Vue的单向数据流

  • 数据从父组件传递给子组件,只能单向绑定;

  • 子组件内部不能直接修改从父组件传递过来的数据;

  • 所有的prop都使得其父子prop之间形成一个单向下行绑定:

    • 父级prop的更新会向下流动到子组件中,但是反过来不行;
  • 这样会防止从子组件意外改变父组件的状态,从而导致应用的数据流向难以理解;

  • 额外的,每次父组件发生更新时,子组件中所有的prop都将会刷新为最新的值;

  • 这意味着你不应该在一个子组件内部改变prop,如果这样做了,Vue会在浏览器的控制台中发出警告;

  • 子组件向修改时,只能通过$emit()派发一个自定义事件,父组件接收后,由父组件修改。

22. 组件中写 name 选项有什么用?

  • 项目中使用keep-alive时,可以搭配组件name进行组件缓存;
  • 使用插槽时,name属性可作为占位标签的名字,供template使用;
  • Vue-devtools调试工具里显示的组件名称是由Vue组件内部的name属性决定的。

23. Vue该如何实现组件缓存

  • 为什么需要组件缓存?
    • 在面向组件开发中,会把整个项目拆分成多个业务组件,按照需求对组件进行整合;
    • 组件频繁切换过程中,组件的实例都是在不断的销毁和创建,很消耗性能,并且如果需要该组件的数据的话,我们时获取不到的,所以需要对组件进行缓存;
  • 怎样实现组件缓存?
    • 使用keep-alive标签包裹需要被缓存的组件,会缓存不活动的组件实例,主要用域保留组件状态或避免重新渲染;
    • 优点:提高渲染性能,提升用户体验。

24. 对Vue生命周期的理解

  • Vue实例从创建到销毁的整个过程,就是Vue的生命周期(四个阶段 + 八对钩子函数)
  • 初始化阶段:
    • beforeCreate()
      • 在实例化之后,数据的观测和事件的配置之前的时候调用,此时组件的选项对象还未创建,el和data并未初始化,因此无法访问methods、data、computed等上的方法和数据;
    • created()
      • 在创建之后调用,data数据和methods方法已经挂载到Vue实例身上,可以正常使用,通常在这个钩子函数里面会发起异步请求(原因:更早的拿到数据,更早渲染页面)。
  • 挂载阶段:
    • beforeMount()
      • 在这个阶段是获取不到dom操作的,把data里面的数据和模板生成html,完成了data等初始化,但此时还没有挂载html页面上(此时是虚拟dom);
    • mounted()
      • 用于挂载之后使用,在这个时候可以获取dom操作,比如可以获取到ref等,操作的dom。
  • 更新阶段:
    • beforeUpdate()
      • 在数据更新之前被调用,发生在虚拟DOM重新渲染,可以在该钩子中进一步地更改状态,不会触发重复渲染过程;
    • updated()
      • 在由于数据更改导致的虚拟DOM重新渲染会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多数情况下,应该避免在此期间更改状态,因为这可能导致更新无限循环,但是再服务端渲染。期间不能调用,可以用于监听某些数据的时候
  • 销毁阶段:
    • beforeDestroy()
      • 在这个时候,Vue实例还可以正常使用;
    • destroyed()
      • 在实例销毁之后调用,调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。

25. 第一次页面加载会触发哪几个钩子函数?

  • beforeCreate、created、beforeMount、mounted
  • 第一次页面加载需要将data数据和methods方法挂载到Vue实例上,并且需要将虚拟DOM变成真实DOM。

26. 父组件包裹子组件,他们的生命周期执行顺序是什么?

  • 父创建前后,父挂载前,子创建前后,子挂载前后,父挂载后。

27. style 上加 scoped属性的原理

  • 什么是scoped
    • 在组件中,为了使样式私有化,不对全局造成污染,可以在 style 标签上添加 scoped 属性,以标示它只局限于当前组件;
  • 原理:
    • 给当前组件添加 data-开头的8位随机哈希值的属性;
    • Vue中scoped属性的效果主要通过PostCSS转译实现:既PostCSS给当前组件内的所有标签添加一个唯一不重复的动态属性,然后,给选择器额外添加一个属性选择器。

28. Vue响应式数据原理

  • 主要是利用通过了Object.defineProperty()的方法里面的settergetter方法的观察者模式来实现的;
  • 在组件初始化的时会给每一个data属性注册getterserter,然后再给自己new一个Watcher对象,此时Watcher对象会立即调用render函数去生成虚拟DOM;
  • 再调用render的时候,就会需要用到data的属性值,此时会触发getter函数,将当前Watcher函数注册进sub里;
  • 当data属性发生改变之后,就会遍历sub里所有的watcher对象,通知他们去重新渲染组件;
    Object.defineProperty(对象, 属性值, {
        setter() {
            // xxx
        },
        getter() {
            // xxx
            return xxx
        }
    })

29. computed、methods、computed之间的区别

  • computed:计算属性
    • 会被挂载到Vue实例身上;
    • 一个计算属性的值,依赖于另外的数据属性计算而来,当依赖发生变化的时候,计算属性也会发生变化;
    • 计算属性具有缓存性,基于依赖的值进行缓存,依赖不发生变化,都直接从缓存中取结果;当依赖发生变化,函数会自动执行,并把最新的结果再次缓存;
    • 不能写异步代码
      • 定义的函数接收return的结果,return属于同步执行,是没办法拿到异步请求的结果的
  • methods
    • 会被挂载到Vue实例身上;
    • 方法中的this指向Vue实例;
    • 不具有缓存特性;
  • watch
    • 观察和响应Vue实例上的数据变动;
    • 能写异步代码;

30. 说一下$root$parent$refs

  • $root,和$parent都能访问父组件的属性和方法,区别在于如果存在多级子组件,通过parent访问得到的就是它最近一级的父组件,通过root访问得到的就是根父组件。
  • 通过在子组件标签定义的ref属性,在父组件中可以使用$refs访问子组件实例。

31. v-model原理

    <input v-model="username" type="text">
    <input type="text" :value="username" @input="username = $event.target.value">
  • 原理:
    • 将元素的value属性和Vue数据属性进行双向绑定
    • 标签上绑定input事件,在该事件内,将输入框中的值赋给vue数据属性;
    • 在标签上使用v-bind命令给value属性绑定Vue数据属性。
  • texttextarea元素使用value属性input事件
  • checkboxradio元素使用checkedchange事件

32. 关于keep-alive说法

  • keep-alive可以通过include属性,匹配要进行缓存的组件;
  • 当组件在keep-alive内被切换,它的activateddeactivated这两个钩子函数将会被执行;
  • max属性控制最多可以缓存几个组件,一旦这个数字达到了,在新实例被创建之前,已缓存的组件中,最久没有被访问的实例会被销毁。

33. Vue中template的编译过程

  • vue template模板编译的过程经过parse()生成ast(抽象语法树)optimize对静态节点优化,generate()生成render字符串之后调用new Watcher()函数,用来监听数据的变化,render函数就是数据监听的回调所调用的,其结果便是重新生成Vnode,如果是数据的更新,那么Vnode会与数据改变之前的Vnode做diff,对内容做改动之后,就会更新到我们真正的DOM。

34. 什么是 Vue.nextTick()?原理是什么

  • $nextTick是在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM,意思是 等你DOM加载完毕以后再去调用nextTick()里面的数据内容。

  • 原理:

    • nextTick方法主要使用了宏任务和微任务,定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空队列。
  • 作用:

    • nextTick用于下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用nextTick用于下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用nextTick,则可以在回调中获取更新后的DOM。
  • $nextTick本质是返回一个Promise

35. new Vue的时候做了什么事

  • image.png
  • 可以看看这位大佬写的

36. axios是什么,怎么使用,描述使用它实现登录功能的流程

  • axios是请求后台资源的模块。通过npm install axios -S来安装,在大多数情况下我们需要封装拦截器,在实现登录的过程中我们一般在请求拦截器中来加入token,在响应拦截器中通过后端返回的状态码来对返回的数据进行不同的处理。
// TODO 封装请求拦截器 
axios.interceptors.request.use(config => {
  // TODO 在发送请求之前做一些事
  return config
}, error => {
  // TODO 处理请求错误
  return Promise.reject(error)
})

// TODO 封装响应拦截器 
axios.interceptors.response.use(response => {
  // TODO 位于2xx范围内的任何状态码都会触发此函数
  // TODO 对响应数据做处理
  return response
}, error => {
  // TODO 任何超出2xx范围的状态码都会触发此函数
  // TODO 做一些响应错误的事情
  return Promise.reject(error)
})

37. 对axios进行二次封装

    import axios from 'axios'
    
    const request = axios.create({
        baseURL: '',
        timeout: 5000
    })
    
    // 参数是个函数
    // 请求拦截器
    request.interceptors.request.use()
    
    // 响应拦截器
    request.interceptors.response.use()
    
    export default request

38. Vue中的路由模式

  • hash模式:
    • url带有#号,#以及#后面的称为hash,用 window.location.hash 读取,对浏览器安全无用;
    • 通过 onhashchange 事件,监听url修改;
    • 特点:
      • 前端访问,#后面的变化不会经过服务器;
      • hash虽然在url中,但不被包括在http请求中;
  • history模式:
    • url没有#号;
    • history采用H5的新特性,且提供了两个新方法 pushState()replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更;
    • 特点:
      • 正常访问,后端访问,url的变化都会经过服务器
  • 切换模式:
    • new VueRouter() 里面,增加 model 属性,属性值为 hashhistory

39. 路由配置项常用的属性

    path       ➡   展示的url
    component  ➡   和path对应的组件路径(可以使用 () => import('组件路径'))
    name       ➡   命名路由
    children   ➡   子路由的配置对象(路由嵌套)
    props      ➡   路由解耦
    redirect   ➡   重定向路由
    meta       ➡   路由元信息

40. 路由跳转的方式

  • 声明式导航:
    <router-link to="需要跳转到页面的路径" />
  • 编程式导航:
    this.$router.push()      ➡    跳转到指定的url,并在history中添加记录,点击回退到上一个页面
    this.$router.go(n)       ➡    向前或向后跳转n个页面,n可以是正数也可以是负数
    this.$router.replace()   ➡    跳转到指定的url,但是history中不会添加记录
    this.$router.back()      ➡    回退到上一个页面

41. 路由传参的方式有哪些

  • 编程式导航:
    • name 和 params 搭配传参
    • this.$router.push({ name: 'news', params: { userId: 123} })
    • path 和 query 搭配传参
    • this.$router.push({ path: '/news', query: { userId: 123 } })
  • 声明式导航:
    • 命名路由:

      • <router-link to="{ name: 'news', params: { userId: 123 } }"></router-link>
    • 查询参数:

      • <router-link to="{ path: '/news', query: { userId: 123 } }"></router-link>

42. $route$router 的区别

  • 都是在注册路由的时候,提供的两个全局对象
  • $route
    • 路由信息对象,包括path、hash、query、params、name等路由信息参数,标识当前激活的路由对象;
  • $router
    • VueRouter的实例,相当于一个全局的路由对象,里面包含很多属性和子对象,如history对象,将常用的跳转连接可以用this.$router.push()会往history栈中添加一个新的记录,this,$router.go()等方法。

43. query 和 params之间的区别

  • query
    • path 配合使用;
    • 接收参数的时候,使用 this,$route.query.属性名
  • params
    • name 配合使用;
    • 接收参数的时候,使用 this,$route.params.属性名

44. Vue-Router 有哪几种路由守卫

  • 全局前置守卫:beforeEach()
  • 全局后置守卫:afterEach()
  • 全局解析守卫:beforeResolve()
  • 路由独享守卫:beforeEnter()
  • 单个路由独享的钩子:beforeEbter()
  • 组件路由守卫相关的钩子:
    • beforeRouterEnter()
    • beforeRouterUpdate()
    • beforeRouterLeave()
  • 入参:
    • to:即将要进入的目标路由对象(去哪里)
    • form:当前导航即将离开的路由对象
    • next:调用该方法,才能进入下一个钩子函数(afterEach)
      • next():通过;
      • next('url'):跳到指定地址
    router.beforeEach(async (to, from, next) => {
        // 相关逻辑
        // next()必须执行,但是参数可能不同
    })

45. 如何监测动态路由的变化

  • 可以通过watch方法对$route进行监听,或者通过导航守卫的钩子函数beforeRouteUpdate来监听它的变化。

46. Vue-Router中的router-link上v-slot属性怎么使用

  • router-link通过一个作用域插槽暴露底层的定制能力。这是一个更高阶的API。主要面向库作者,但也可以为开发者提供便利,多数情况用在一个类似NavLink这样的自定义组件里;
  • 有时我们可能想把激活的 class 应用到一个外部元素而不是<a>标签本身,这时可以在一个router-link中包裹该元素并使用v-slot属性来创建链接:
    <router-link
      to="/foo"
      custom
      v-slot="{ href, route, navgiate, isActive, isExactActive }"
    >
        <li
          :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active' ]"
        >
            <a :href="href" @click="navigate">{{ route.fullPath }}</a>
        </li>
    </router-link>

47. Vue路由实现的底层原理

  • 在Vue中利用数据劫持defineProperty原型prototype上初始化一些getter,分别是:
    • router代表当前Router的实例;
    • route代表当前Router的新信息。
  • install中也全局注册了router-view, router-link,其中的Vue.util.defineReactive,这是Vue里面观察者劫持数据的方法,劫持_route,当_route触发setter方法的时候,则会通知到依赖的组件;
  • 接下来在init中,会挂载判断是路由的模式,是history或hash,点击行为按钮,调用hashchange或popstate的同时更新_route_route的更新会触发route-view的重新渲染。

48. 为什么使用Vuex

  • 项目比较大,以往的关系组件通信进行数据的传递很麻烦,不方便;
  • 状态的统一管理,实现数据的共享;
  • 实现非关联组件之间的通信。

49. Vuex的5个核心属性

  • modules:模块化
  • state
    • 状态管理(定义变量);
    • 使用:
      • 不使用辅助函数:
        • this.$store.state.模块名.变量名
      • 辅助函数:
        • image.png
  • mutations
    • 同步修改state;
    • 定义在mutations中的方法,有两个入参,分别是:statepayload
    • 使用:
      • 不使用辅助函数:
        • this.$store.commit('模块名/方法名', 需要传递的数据)
      • 辅助函数:
        • image.png
  • actions
    • 异步修改state,使用commit方法将数据提交给mutations中的方法进行修改;
    • 定义在actions中的方法,有两个入参,分别是:contextpayload
    • 使用:
      • 不使用辅助函数:
        • this.$store.dispatch('模块名/方法名', 传递的数据)
  • getters
    • 相当于Vue的计算属性,
    • getters中的方法有两个入参,分别是:statepayload
    • 在srore下新建getters.js文件
    • image.png
    • image.png

50. 为什么需要对Vuex持久化

  • vuex中的数据在页面刷新后就没有了;
  • 要实现数据的长久保存,可以通过浏览器的本地存储能力实现
    • cookie
    • localStorage

51. Vuex可以直接修改state的值吗

  • 可以直接修改,但是及其不推荐;
  • state的修改必须在mutation来修改,否则无法被devtools所监测,无法监测数据的来源,无法保存状态快照,也就无法实现时间漫游 / 回滚之类的操作。

52. 为什么Vuex的mutation不能做异步操作

  • Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过Action来提交mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用;
  • 每个mutation执行完成后都会对应一个新的状态变更,这样devtools就可以打个快照存下来,否则无法被devtools所监测;
  • 如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。

53. Vue单页面应用的优缺点

  • 优点:
    • 内容的改变不需要重新加载整个页面,web应用更具响应性;
    • 没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并没有“闪烁”现象;
    • 相对服务器压力小,服务器只用出数据就可以,不用展示逻辑和页面合成,吞吐能力会提高几倍;
    • 良好的前后端分离。后端不再负责模板渲染、输出页面工作。后端API通用化,既一套后端程序代码,不用修改可以用于Web界面、手机、平板等多种客户端。
  • 缺点:
    • 首次加载耗时比较长;
    • SEO问题,不利于百度,360等搜索引擎收录;
    • 容易造成Css命名冲突;
    • 前进、后退、地址栏、书签等,都需要程序进行管理,页面的复杂程度很高,需要一定的技能水平和开发成本。

54. 如何对首屏加载实现优化

  • 把不常用的库放到index.html中,使用cdn引入;
  • 使用懒加载;
  • Vue组件避免全局注册;
  • 使用更轻量级的工具库;
  • 预渲染;
  • 减少http请求;
  • 开启gzip压缩。

55. 对SPA单页面的理解,它的优缺点分别是什么?

  • 单页Web应用是一种特殊的Web应用。他将所有的活动局限于一个web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript和CSS,一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转。取而代之的是利用JavaScript动态的变换HTML的内容,从而实现UI与用户的交互。由于避免了页面的重新加载,SPA可以提供较为流畅的用户体验。得益于Ajax,我们可以实现无跳转刷新,又多亏了浏览器的history机制,我们用hash的变化从而可以实现推动界面变化,从而模拟元素客户端的单页面切换效果;

  • 优点:

    • 单页面应用的内容的改变不需要重新加载整个页面,Web应用更具响应性;

    • 单页面没有页面之间的切换,就不会出现“白屏现象”,也不会出现假死并没有“闪烁”现象;

    • 单页面应用相对服务器压力小,服务器只用出数据就可以,不用管展示逻辑和页面和声,吞吐能力会提高几倍;

    • 良好的前后端分离。后端不再负责模板渲染、输出页面工作,后端API通用化,既同一套后端程序代码,不用修改就可以用于Web界面、手机、平板等多种客户端。

  • 缺点:

    • 首次加载耗时比较多;
    • 不利于SEO优化;
    • 各个浏览器的版本兼容性不一样;
    • 业务随着代码量增加而增加,不利于首屏优化;
    • 前进、后退、地址栏、书签等,都需要程序进行管理,页面的复杂程度很高,需要一定的技能水平和开发成本。

56. 项目优化

  • 减少http请求;
  • 减少DOM操作;
  • 使用JSON格式来进行数据的交换;
  • 使用CDN加速;
  • 优化代码,减少代码体积;
  • 服务端渲染。

57. Vue2 和 Vue3 的区别?

  • 根节点数目:

    • Vue2只能有一个根节点;
      • 因为vdom是一棵单根树型结构,pacth方法在遍历的时候从根节点开始遍历,他要求只有一个根节点,组件也会转换为一个vdom,自然应该满足这个要求。
    • Vue3可以有多个根节点;
      • Vue3中引入了Fragment的概念,这是一个抽象的节点,如果发现组件是多个根节点,就创建一个 Fragment节点,把多个根节点作为它的children。将来patch的时候,如果发现是一个Fragment节点,则直接遍历children创建或更新。
  • 数据双向绑定原理不同:

    • Vue2采用Object.defineProperty
    • Vue3采用ES6新增的Proxy
  • 生命周期不同:

    Vue2                      ==>                   Vue3
    
    beforeCreate()            ==>                   setup()     
    Created()                 ==>                   setup()
    beforeMount()             ==>                   onBeforeMount()
    mounted()                 ==>                   onMounted()
    beforeUpdate()            ==>                   onBeforeUpdate()
    updated()                 ==>                   onUpdated()
    beforeDestroyed()         ==>                   onBeforeUnmount()
    destroyed()               ==>                   onUnmounted()
    activated()               ==>                   onActivated()
    deactivated()             ==>                   onDeactivated()
    注意:
        setup 要比 beforeCreate 更早执行
        setup 有两个入参,proxy + context
            如果解构proxy,得到的数据会丢失响应式
            如果还想保持响应式,可以使用 toRefs() 或者 toRef()
            
            import { toRefs, toRef } from 'vue'
            export default {
                setup(props) { 
                    // 将 `props` 转为一个其中全是 ref 的对象,然后解构 
                    const { title } = toRefs(props)
                    // `title` 是一个追踪着 `props.title` 的 ref 
                    console.log(title.value) 
                    // 或者,将 `props` 的单个属性转为一个 ref 
                    const title = toRef(props, 'title')
                    }
                  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云剪辑-B端在线剪辑⼯具架构设计与演进

腾讯云音视频的云剪辑致力于让客户在自己的应用&#xff08;Web、小程序&#xff09;中快速集成剪辑能力&#xff0c;同时强大的模板能力能够极大地提升视频生产效率。我们在探索B端在线剪辑产品的过程中遇到不少挑战&#xff1a;如何满足快速与定制两种集成场景&#xff1f;如…

Linux性能监控

一、htop 安装&#xff1a;yum install htop -ytop是linux下常用的监控程序&#xff0c;htop相当于其加强版&#xff0c;颜色显示不同参数&#xff0c;且支持鼠标操作&#xff0c;相对于top简单和人性化&#xff01;第一行与第二行&#xff0c;显示CPU当前的运行负载&#xff…

F407标准库之时钟系统

主要参考正点原子数据手册和源码资料等。 第19讲 STM32时钟系统精讲_哔哩哔哩_bilibili 此处记录较为重要或者较易出错的一些遗漏之处&#xff0c;作为补充。 一般而言&#xff0c;时钟越高&#xff0c;速度越快&#xff0c;但同时抗干扰能力也越差&#xff0c;功耗也越高&am…

java入门学习

输入 数字输入&#xff08;为什么类型的数字就是sc.next类型&#xff09;float sumsc.nextFloat() int xsc.nextInt(); import java.util.Scanner;public class 相加问题 {public static void main(String[] args){Scanner scnew Scanner(System.in);int xsc.nextInt();int …

AMB300系列母线槽红外测温解决方案某锂电厂房项目案例分享

安科瑞 耿敏花 一、 行业背景 近年来&#xff0c;在国家政策引导与技术革新驱动的双重作用下&#xff0c;锂电产业保持快速增长态势&#xff0c;产业规模持续扩大&#xff0c;同时新能源产业工厂锂电池生产线对于电的依赖性很高&#xff0c;因而对供电设备的可靠性提出…

php+vue网上培训课程直播授课学习平台

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 1、优智学在线授课平台主要是针对 疫情期间高校对在线教学直播的需求&#xff0c;为在校师生提供高质量…

TOGAF® 基本内容—架构开发方法—E阶段:机会和解决方案

本章描述识别有效交付的交付工具&#xff08;项目、项目群或项目组合&#xff09;的过程 在前面阶段确定的目标体系结构。 一、目标 E阶段的目标是&#xff1a; 根据差距分析和候选架构生成架构路线图的初始完整版本 阶段 B、C 和 D 的路线图组件确定是否需要增量方法&#xf…

WooCommerce电商开发:高性能订单存储HPOS性能基准测试

自去年以来&#xff0c;我们一直致力于构建和推出 HPOS&#xff08;高性能订单存储&#xff09;作为一项可选功能。这改变了我们在数据库中存储订单数据的方式&#xff0c;从自定义帖子类型 wp_post和wp_postmeta表到专门用于存储订单数据的自定义表。我们还发布了这些表的详细…

六、Spring Cloud Alibaba-nacos配置中心

一、Nacos配置中心 前面说了三、Spring Cloud Alibaba组件nacos&#xff0c;主要介绍的是服务发现。该篇主要介绍配置中心的功能。 官方地址&#xff1a; https://github.com/alibaba/spring-cloud-alibaba/wiki/Nacos-config。 Nacos 提供用于存储配置和其他元数据的 key/val…

tomcat集群下的session共享和负载均衡(memcache实现)

环境 操作系统&#xff1a;windows tomcat1&#xff1a;Apache Tomcat/7.0.52&#xff08;8085&#xff09; tomcat2&#xff1a;Apache Tomcat/7.0.52&#xff08;8086&#xff09; jdk&#xff1a;1.8.0_251 nginx&#xff1a;nginx-1.20.1&#xff08;8070&#xff09; memc…

美颜SDK的算法分析:探究其背后的机器学习模型

美颜SDK作为常见的美颜工具&#xff0c;其使用的算法也备受关注。本文将从机器学习的角度&#xff0c;深入分析美颜SDK的算法模型与实现原理。 一、算法模型 美颜SDK主要采用的算法模型是卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;。…

网卡名称排序

udev是一种动态设备管理系统&#xff0c;用于在Linux系统中自动管理设备的插拔、识别、配置等操作。它的主要作用是监视系统中的设备事件&#xff0c;并根据设备事件动态地创建、删除或修改系统中的设备节点。 udev的工作原理是通过读取系统中的硬件信息、驱动程序和设备特征信…

AI天后,在线飙歌,人工智能AI孙燕姿模型应用实践,复刻《遥远的歌》,原唱晴子(Python3.10)

忽如一夜春风来&#xff0c;亚洲天后孙燕姿独特而柔美的音色再度响彻华语乐坛&#xff0c;只不过这一次&#xff0c;不是因为她出了新专辑&#xff0c;而是人工智能AI技术对于孙燕姿音色的完美复刻&#xff0c;以大江灌浪之势对华语歌坛诸多经典作品进行了翻唱&#xff0c;还原…

李沐论文精度系列之九:InstructGPT

文章目录 一、背景1.1 时间线1.2 ChatGPT功能展示1.3 指示学习&#xff08;Instruct Learning&#xff09;和提示&#xff08;Prompt Learning&#xff09;学习1.4 人工反馈的强化学习&#xff08;RLHF&#xff09; 二、摘要三、导言3.1 算法3.2 结论 四、方法和实验细节4.1 数…

【数据结构与算法】树和二叉树

1 树 1.1 术语 关系术语 孩子结点 —— 子树的根 父结点 兄弟结点 —— 同一个结点的孩子结点互为兄弟 祖先结点 后代结点 层次类术语 根的层次为1 其余结点的层次为其父结点层次加1 高度/深度 —— 整个树中结点的最大层次 度 —— 结点的孩子数目称为结点的度 叶子&#xf…

Smartbi携手广州轻工集团打造集团价值创造型总部

广州轻工工贸集团有限公司&#xff08;简称“广州轻工集团”&#xff09;是广州市第一家工贸合一的大型企业集团公司&#xff0c;最早起源于1950年9月成立的广州市合作事业管理局&#xff0c;逐渐演化形成广州市轻工业局。1995年10月&#xff0c;广州市轻工业局成建制改建为经济…

spring-transaction源码分析(3)Transactional事务失效原因

问题概述 在Transactional方法中使用this方式调用另一个Transactional方法时&#xff0c;拦截器无法拦截到被调用方法&#xff0c;严重时会使事务失效。 类似以下代码&#xff1a; Transactional public void insertBlogList(List<Blog> blogList) {for (Blog blog : …

【人工智能】在VScode中使用AI插件Bito,功能与ChatGPT类似

文章目录 前言一、到官网下载VScode软件二、VScode软件安装步骤三、Bito插件下载与VScode软件中的使用四、注册Bito 前言 之前在VScode中使用ChatGPT中文版&#xff0c;后来要注册与收费&#xff0c;可采用一些ChatGPT中文版的替代插件。 后发现BitoAI插件功能同样强大&#…

港联证券|断臂、收缩、变阵 “中植系”何去何从?

经历灵魂人物猝然离世的巨震&#xff0c;国内最老牌资本系之一的“中植系”&#xff0c;尚未显露出穿越周期的企稳之象&#xff0c;似仍在风雨飘摇。 投资端&#xff0c;随着监管持续升级与注册制改革全面推进&#xff0c;“中植系”惯用“PE上市公司”以低买高卖的资本套利模式…

流水线三维可视化运维,装配自动化提质增效 | 设备产线管理合集

为大家带来图扑智慧生产线/设备流水线合集。依托图扑对设备加工、物流输送、车辆装配等多个车间流水线进行 3D 可视化展示&#xff0c;通过数字孪生技术推动行业数字化转型升级。 智慧仓储产线 智慧仓储产线通过对仓储现场的数字化建模&#xff0c;利用先进的物联网、大数据、…