Vue面试笔记

💡VUE

main.js 的运行过程

  1. 引入Vue对象(相当于引入vue.js)
  2. 引入App.vue 对象
  3. 实例化vue
  4. 渲染App页面
  5. 把页面渲染到 index.html 里,手动挂载到id为app的dom中。

data 为什么是一个函数

MVVM模式

MVC的改进,MVVM是双向的,数据变化更新视图,视图更新会自动同步据。

==优点==:

  1. 耦合性低,view 和 model 完全分离
  2. 维护性高
  3. 双向绑定
  4. 减少了 DOM 操作。

MVC 模式

将==视图==和==数据==进行分离,让代码更好维护,耦合性变低,提高复用性。

  1. 设计

vue语法中的命令

  1. 插值表达式:{ { } }

在 dom 中直接插入 vue 数据变量,数据变量在 js 中 data 函数里面声明

  1. 给标签属性设置变量的值:v-bind / :
  1. 给标签绑定事件 : v-on / @click

事件中的 this 指向 exports default { } 中的变量

  1. 事件修饰符:v-on : 事件名.修饰符 = ‘’函数‘’

    • .prevent 阻止默认行为
    • .stop 阻止冒泡
    • .once 程序运行期间,只触发一次事件函数

       v-on : keyup.enter = ''函数''  监测回车
      
    • v-on :keyup.esc = ‘’函数‘’ 监测返回
  2. 表单value和vue变量的双向绑定:v-model : ‘‘vue变量’’

  1. v-model.修饰符 = “”

作用:实现数据的双向绑定,以及组件之间的通信 原理:input事件和 :value的语法糖

<input v-model="val">
//相当于
<input :value="val" @input = "val = $event.target.value>

场景:

  1. 在表单中使用。
  2. 组件通信:当父组件传递给子组件,且子组件要修改数据传递给父组件时,用 v-model 进行简化。
<child v-model="color"> //传递color给子组件
  //相当于
 <child :value = "color" @input = "color = $event">
  
<div @click = "$emit('input','数据')">
 
props:['value']
  
 //也可以自定义v-model 的属性名和事件名
 model:{
   prop:'自定义属性名',
  event:'自定义事件名'
 }
  1. sync 修饰符
<child :color.sync = "color">
  
  //相当于
 <child :属性名=“数据” @update属性名 =  “数据 = $event>
//父组件
@update:属性名1 = “对象.属性1 = 新值”
@update:属性名2 = “对象.属性2 = 新值”

//子组件
$emit('update:属性名1',新值);
$emit('update:属性名2',新值);
  1. v-if 和 v-for 为什么避免同时使用

computed 和 watch的区别

🔺vuex的同步异步流程

  1. 同步流程
  1. 异步流程

🔺简单谈谈vuex

  1. vuex就是基于vue的一个状态管理工具
  2. 它主要用于实现数据的共享,同时数据也是响应式的,因此它就方便了各个组件之间共享数据的操作,也有利于数据的维护的管理。
  3. 它有五个主要的状态:
    • state 是用来存储和定义用来共享的数据的属性,可以用$store 或者是 辅助函数来拿到state的数据,因为辅助函数本质上会返回一个对象,可以把vuex中的数据映射过来,在使用的时候必须解构出来。
    • mutations 是 用来修改state 数据的唯一来源,但是也可以直接修改state 中的数据,但是不建议,因为一旦数据出现错误会造成state中的数据混乱,它一般是用来处理同步流程,通过commit 提交给mutations 从而修改state 中的数据,如果用它处理异步流程,那么可能造成调试工具的不准确。
    • actions 主要用来处理异步流程,通过dispatch 传递给 actions 在调用 mutations 来修改数据,一般在工作中,为了避免操作的繁琐,基本都把同步异步流程都放到actions中进行处理,而把数据的修改提交到mutations中。
    • getters 主要把state中的数据新建派生处理,即根据state中的数据生成另一种数据。
    • modules 主要是把vuex数据模块化,方便管理和维护,每个模块里都有对应模块的 state/mutations/actions/getters 属性,如果没有开启命名空间,模块中的 mutations/actions中的方法和全局中的并无差别,开启命名空间之后,使用各自模块的方法和数据都必须加上模块名,或者是根据createNamespacedHelper生成对应命名空间的辅助函数,它能拿到当前命名空间的所有辅助函数,从而实现对当前命名空间数据或方法的使用。
  4. vuex的缺点就是 他其中的数据不支持持久化操作,当然我们可以通过添加本地存储的方式来实现手动持久化,或者是通过插件vuex-persistedstate 来实现自动的数据持久化操作,其中可以对指定模块进行数据持久化。在 plugins 配置项中的createPersistedState() 对单独的模块进行配置
  5. 在日常的业务中,一般的用户信息以及用户唯一标识token都放到vuex中进行存储,以及一些多组件之间需要频繁传递的参数一般也放到vuex中进行存储。

v-if 和 v-show 的区别

  1. v-if / v-show 都会控制元素的显示和隐藏

  2. v-show 相当于给标签添加了样式 display:none ,

    优点:不会频繁创建或者删除 dom。

    缺点:首次渲染,如果为false,也会创建元素依旧在,更高的初始渲染开销。

    场景:如果需要频繁的切换,可以用v-show。

  3. v-if 是直接从 DOM 中移除或者添加元素。

    优点:懒渲染,如果有此渲染是false ,那么久不会创建元素,如果是组件,可以重新触发生命周期。 缺点:会频繁的删除和创建dom元素,增加了性能负担,v-if有更高的切换开销 应用场景:如果元素很少改变,或者组件需要重新触发生命周期,或者首次元素为隐藏。

route 和 router 的区别

  1. route 是当前路由信息,可以获取到当前路由地址(path)参数(params,query)等等。$ route是一个跳转的路由对象(路由信息对象),每一个路由都会有一个$route对象,是一个局部的对象。
  2. router 是全局路由(VueRouter)实例对象,可以通过 router 进行路由的跳转后退等等。他包含了所有的路由,包括路由的跳转方法,钩子函数,也包含一些子对象(例如history)

Vue.use(install(){},2,3)原理

请求优化

vue封装组件的思想

$nextTick

作用:用来数据更新后,开始触发,更新视图。

场景:一般的话,用可以用在,想要在create()中拿到dom的时候。

vue生命周期

  1. 创建阶段
    • beforeCreate() : vue实例开始初始化,但是拿不到实例里面的方法和数据,此时方法和数据并没有添加到实例中。
    • created() : vue实例初始化完成,可以访问到 实例的数据和方法。
  2. 挂载阶段
    • beforeMount():dom 未挂载,不可以操作dom
    • mounted():dom 已挂载,此时可以操作dom
  3. 更新阶段
    • beforeUpdate():数据更新,但是视图没有更新,此时是不同步的。
    • updateed():数据更新,视图也更新,二者同步。此时虚拟dom变为新的dom。
  4. 销毁阶段
    • beforeDestory():实例开始销毁,清除挂载在 window 上的行为定时器或者是事件。vue实例上绑定的东西会解绑,解除事件监听。
    • destory():实例销毁后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁
  5. 父子生命周期
    • 创建阶段和挂载阶段
      • 父beforeCreate()— 父created()— 父beforeMount()— 子beforeCreated()— 子created()— 子beforeMount()— 子mounted()—- 父mounted()
    • 更新阶段
      • 如果父级更新的数据不涉及子组件:父beforeUpdate()—父update()
      • 如果父级更新的数据涉及子组件:父beforeUpdate()—子beforeUpdate()—子update()–父update()
    • 销毁阶段
      • 父beforeDestory()—子beforeDestory()—子destoryed()–父destoryed()

虚拟DOM

  1. 本质:是一个js对象,用来描述真的DOM。
  2. 优点:可以进行高效更新,跨平台
  3. 实现高效更新:
    1. 初始化:根据数据和模板生成一个虚拟dom树。
    2. 当数据发生变化:根据新的数据生成一个新的虚拟dom树。
    3. 对比两个新旧虚拟dom:diff算法
      • 采用同级比较,深度优先的方法,进行双指针算法处理,新旧dom都分别有两个指向开始和结束的指针。
      • 对比之后,元素不同:对元素删除重建
      • 元素相同,属性不同:元素复用,属性更新
      • 用 v-for 遍历数据:
        1. 无 key :观察数据的变化是否影响到顺序
          • 顺序发生变化:那么就会影响到性能,不会对元素进行复用
          • 顺序没发生变化:复用相同元素,更新不同元素
        2. 有 key :会根据 key 值来判断元素是否更新,如果可以找到相同的 key 则会复用,如果找不到相同的 key 值,那么就只更新这个 key 值的元素。
        3. key 不推荐使用 index :一旦在对元素进行逆序的删除或者添加的话,那么所有元素的索引就会改变,会产生没必要的 dom 更新或者是错误的更新,影响性能 。

Mixins

1. 概念

2. 优先级

❗数据响应式

1. 概念

2. 响应式核心

Object.defineProperty:可对对象进行属性定义内部有:

3. 劫持数据

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>Document</title>
  </head>
  <body>
    <div>
      <p id="name"></p>
      <p id="age"></p>
    </div>
    <script>
      // 定义数据
      const data = {
        name: '张三',
        age: 19
      }

      // 同步视图的方法
      function setView() {
        document.getElementById('name').innerHTML = data.name
        document.getElementById('age').innerHTML = data.age
      }
      setView()

      // 利用循环对数据进行监听
      Object.keys(data).forEach(key => {
        // 利用外部数据进行数据的读写控制
        let getValue = data[key]
        Object.defineProperty(data, key, {
          // 读数据
          get() {
            return getValue
          },
          // 写数据
          set(val) {
            getValue = val
            setView()
          }
        })
      })
    </script>
  </body>
</html>

4. 观察者模式

另外响应式原理还需要配合观察者模式。

img

V2 和 V3 的区别

  1. api
  1. 使用
  1. 性能
  1. 数据劫持

keep-alive