vue总结

210 阅读5分钟

如何理解组件化

组件化就是将我们的页面按照业务逻辑、功能划分成为不同的模块化组件。每个模块只完成自己特定的功能,从而使得整个项目中的组件高内聚低耦合。组件化的尝试早在jsp、asp时代就已经在使用,但是当时的组件化属于静态组件化,通过后端服务器将组件渲染生成静态DOM元素,而如今的react,vue所构建的是动态组件化。每个组件基于数据驱动视图,动态变化,使前端开发人员不再将关注重点放在DOM操作中,而只需要关心数据流转。

解释下MVVM

MVVM分为三个模块。

  • M model层: 数据模型,用于定义数据和业务逻辑
  • V view层: UI视图层-DOM元素
  • VM viewModel层: 有两个主要功能。①将Model数据的更新到DOM元素,②处理DOM事件,并更新数据层数据。 这种模式基于数据驱动视图,前端开发人员只需注重对数据的维护,不需要对DOM进行操作,有利于构建复杂的项目。

Vue响应式原理

核心API:

  • 2.x 使用Object.defineProperty
    • 缺点:
      • 深度监听,使用递归监听到底,一次性计算量大
      • 无法监听新增属性、删除属性。(Vue.set,Vue.delete)
      • 无法原生监听数组,需要重写数据原型实现。
  • 3.x 使用Proxy
    • 优点:
      • 深度监听不是一次性递归监听,而是触发get时才会添加监听
      • 可以监听删除属性、新增属性
      • 可以监听数组变化
    • 缺点:
      • 无法兼容所有浏览器,且无法polyfill

vue2.x中如何监测数组变化

vue将data中的数组的原型链进行了重写,指向了自己定义的数组原型方法。当数组调用api时,就可以实时监听到数据变化,通知依赖更新。如果数组中包含引用类型。会对数组中的引用类型继续进行递归遍历进行监控。

vue生命周期

生命周期描述
beforeCreate组件实例被创建之初,组件的属性生效之前
created组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用
beforeMount在挂载开始之前被调用:相关的 render 函数首次被调用
mountedel 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子
beforeUpdate组件数据更新之前调用,发生在虚拟 DOM 打补丁之前
update组件数据更新之后
activitedkeep-alive 专属,组件被激活时调用
deactivatedkeep-alive 专属,组件被销毁时调用
beforeDestory组件销毁前调用
destoryed组件销毁后调用
  • 生命周期示意图

生命周期示意图

computed 和 watch 的区别

  • computed:是计算属性,依赖其他属性的值。具有缓存,只有他依赖的值发生变化,下一次取当前属性时才会重新计算。这样避免了每次取值时都重新计算。内部不允许改变其他属性的值。且必须返回当前属性值。
  • watch:
    • 观察作用。用于监听某个值变化后的回调操作。而且watch内部可以允许异步操作。内部可以同时改变多个属性的值或者执行多个方法。
    • watch默认对引用类型数据只做一层监听。可以通过以下方法实现深度监听。但是监听引用类型的数据。无法取到oldval。
watch:{
    info: {
      handler: function (oldVal, newVal) {
        console.log(oldVal, newVal)
      },
      deep: true
    }
}

vue中 父组件和子组件生命周期函数执行的顺序

按照不同的过程可以分为4类:

  1. 加载渲染的过程 父组件beforeCreate -> 父组件created -> 父组件beforeMounted -> 子组件beforeCreate -> 子组件created -> 子组件beforeMount -> 子组件 mounted -> 父组件 mounted

  2. 子组件更新 父组件 beforeUpdate -> 子组件 beforeUpdate -> 子组件 updated -> 父组件updated

  3. 父组件更新 父组件 beforeUpdate -> 父组件updated

  4. 销毁 父组件 beforeDestroy -> 子组件 beforeDestroy -> 子组件 destroyed -> 父组件 destroyed

v-model 原理

v-model指令实际上就是语法糖,在表单元素上创建双向数据绑定。根据不同的表单元素,绑定不同的属性值和事件实现双向数据绑定。

  • input[type='text']、textarea 绑定属性value 和 input 事件
<input v-model="a">
<!-- 相当于 -->
<input :value="a" @input="a = $event.target.value">
  • input[type='checkbox']、input[type='radio'] 绑定属性checked 和 change 事件
<input type="checkbox" v-model="a">
<!-- 相当于 -->
<input :checked="a" @change="a = $event.target.checked">
  • select 绑定属性value 和 change 事件
<select v-model="a"></select>
<!-- 相当于 -->
<select :value="a" @change="a = $event.target.value"></select>

在自定义组件上使用v-model,相当于给自定义组件传入一个属性 value, 并且绑定一个input方法

// 父组件:
<Parent v-model="a"></Parent>

// 子组件:
<template>
  <div>{{value}}</div>
</template>
<script>
export default {
  props:{
    value: String
  },
  methods: {
    test(){
       this.$emit('input', 'aaaaaa')
    },
  },
}
</script>

vue 组件间通信的方法

  1. props / $emit() 用于父子组件间的通信
  2. ref$parent / $children 用于父子组件间的通信
  • ref 绑定在DOM元素上是返回的是DOM元素,绑定在Vue组件上时返回的是Vue组件的实例对象
  1. EventBus $emit() / $on 用于父子组件、隔代组件和兄弟组件间的通信
// bus.js
import Vue from 'vue'
export default new Vue()
// 在组件中created()方法中监听事件
import Bus from 'path/to/bus'
export default {
  created(){
    Bus.$on('clickme', target => {
      console.log('clickme', target)
    })
  }
}
// 在其他组件中触发事件
import Bus from 'path/to/bus'
export default {
  methods:{
    test(){
      Bus.$emit('clickme', '啦啦啦啦啦')
    }
  }
}

  1. $attrs / $listeners用于隔代组件间通信

通过$attrs向子孙组件传递属性 通过$listeners子孙组件向爷爷组件$emit()通信 看到一篇文章讲解很详细

文章的地址

  1. provide / inject 用于隔代组件间通信
 // 爷爷组件
<script>
export default {
  provide:{
    a:1
  }
}
</script>
// 孙子组件
<template>
  <div>{{ a }}</div>
</template>
<script>
export default {
  inject:{
    a:{
      defalut: 0
    }
  }
}
</script>
  1. vuex 用于父子组件、隔代组件、兄弟组件间通信

vuex官网

Vue模版编译原理

  1. 首先构建AST树。使用正则进行模板解析。
  2. 优化AST树,深度遍历AST树,将不是响应式的节点进行标记。这样这些节点就会跳过他们的对比,优化对比性能
  3. 转换代码,将优化后的AST树转换为render函数,执行render函数返回vnode。

Vue.extend、Vue.component、Vue.mixin的区别

  • Vue.extend:传入一个对象option,包含组件选项的对象。最后返回一个子组件构造器方法.
  • Vue.component:用于注册全局组件,传入两个参数。id和构造器。也就是说第二个参数就是一个vue.extend({})。如果第二个参数传入的是一个组件选项的对象,则会自动调用vue.extend
  • Vue.mixin: 全局混入。用于将一些公用的方法注册进每个Vue实例中。
  • 当一个组件中即存在mixin,还存在extend时。其中的同名属性。最终使用mixin的值。

vue性能优化的方式

  • 合理使用v-show和v-if
  • 合理使用computed
  • v-for是使用key,不和v-if同时使用
  • 自定义事件、DOM事件、定时器及时销毁
  • 合理使用异步组件
  • 合理使用keep-alive
  • data层级不要太深。在实现响应式是会一次性深度递归添加监听函数,深度太深影响性能。