Vue 3.0 性能晋升次要是通过哪几方面体现的?

  1. 响应式零碎的降级
  • Vue 2.0 应用 defineProperty

    • defineProperty 代理对象中的某个属性
    • 初始化时将 data 中的数据进行解决,如果属性时 object 类型还须要递归解决
  • Vue 3.0 应用 Proxy 对象重写响应式零碎

    • Proxy 代理整个对象
    • 调用时递归
    • 能够监听动静新增的属性
    • 能够监听删除的属性
    • 能够监听数组的索引和 length 属性
  1. 编译优化
  • Vue 2.0 中通过标记动态根节点,优化 diff 过程
  • Vue 3.0 中标记和晋升所有的动态根节点,diff 只须要比照动静节点内容

    • Fragments
    • 动态晋升
    • Patch flag
    • 缓存事件处理函数
  1. 源码体积优化
  • Vue 3.0 中移除了一些不罕用的 API

    • inline-tempalte、filter
  • Tree-shaking

Vue 3.0 所采纳的 Composition Api 与 Vue 2.x应用的Options Api 有什么区别?

  1. Vue 2.0 Options Api
在一个 vue 文件中应用 datamethodscomputedwatch 定义属性和办法,独特解决页面逻辑

问题:当组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以浏览和了解。

// src/components/UserRepositories.vueexport default {  components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },  props: {    user: {      type: String,      required: true    }  },  data () {    return {      repositories: [], // 1      filters: { ... }, // 3      searchQuery: '' // 2    }  },  computed: {    filteredRepositories () { ... }, // 3    repositoriesMatchingSearchQuery () { ... }, // 2  },  watch: {    user: 'getUserRepositories' // 1  },  methods: {    getUserRepositories () {      // 应用 `this.user` 获取用户仓库    }, // 1    updateFilters () { ... }, // 3  },  mounted () {    this.getUserRepositories() // 1  }}
  1. Vue 3.0 Composition Api
在 Composition API 中,代码是依据逻辑性能来组织的,一个性能的所有 API 会放在一起(高内聚,低耦合)
// src/components/UserRepositories.vueimport { toRefs } from 'vue'import useUserRepositories from '@/composables/useUserRepositories'import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'import useRepositoryFilters from '@/composables/useRepositoryFilters'export default {  components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },  props: {    user: {      type: String,      required: true    }  },  setup(props) {    const { user } = toRefs(props)    const { repositories, getUserRepositories } = useUserRepositories(user)    const {      searchQuery,      repositoriesMatchingSearchQuery    } = useRepositoryNameSearch(repositories)    const {      filters,      updateFilters,      filteredRepositories    } = useRepositoryFilters(repositoriesMatchingSearchQuery)    return {      // 因为咱们并不关怀未经过滤的仓库      // 咱们能够在 `repositories` 名称下裸露过滤后的后果      repositories: filteredRepositories,      getUserRepositories,      searchQuery,      filters,      updateFilters    }  }}

Proxy 绝对于 Object.defineProperty 有哪些长处?

  • defineProperty 代理对象中的某个属性,Proxy 代理整个对象
  • defineProperty 无奈监控到数组下标的变动, Proxy 能够

Vue 3.0 在编译方面有哪些优化?

  • Vue 2.0 中通过标记动态根节点,优化 diff 过程
  • Vue 3.0 中标记和晋升所有的动态根节点,diff 只须要比照动静节点内容

    • Fragments
    • 动态晋升
    • Patch flag
    • 缓存事件处理函数

Proxy 和 Reflect 中的 receiver 指向问题?

Proxy 中的 receiver 指向 proxy 实例

const proxy = new Proxy({}, {  get: function(target, key, receiver) {    return receiver;  }});proxy.getReceiver === proxy // true

Reflect 中的 receiver

  • 如果属性部署了读取函数(getter),则读取函数的 this 绑定 receiver。
var myObject = {  foo: 1,  bar: 2,  get baz() {    return this.foo + this.bar;  },};var myReceiverObject = {  foo: 4,  bar: 4,};Reflect.get(myObject, 'baz', myReceiverObject) // 8
  • Reflect.set 一旦传 receiver,就会将属性赋值到 receiver 下面(即obj),导致触发 defineProperty 拦挡
      let p = {        a: "a",      };      let handler = {        set(target, key, value, receiver) {          console.log("set");          Reflect.set(target, key, value, receiver);        },        defineProperty(target, key, attribute) {          console.log("defineProperty");          Reflect.defineProperty(target, key, attribute);        },      };      let obj = new Proxy(p, handler);      obj.a = "A";      // set      // defineProperty

Vue.js 3.0 响应式零碎的实现原理?

Vue 3.0 的响应式零碎是独立的模块,能够齐全脱离 Vue 而应用,而贯通整个响应式零碎得无非是 reactive、effect 办法

  • reactive:通过 Proxy 设置 get、set、deleteProperty 代理,返回对象的响应式正本。

    • get:收集依赖,递归将代理对象转成响应式对象
    • set:更新值并触发更新
    • deleteProperty:删除并触发更新
  • effect:立刻执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时从新运行该函数

依赖收集-track

当 effect 被立刻执行时,触发代理对象的 getter 办法,get 办法外部会调用 track 办法将属性与对应的 effect 函数建设依赖关系

let activeEffect = nullfunction effect(callback) {  activeEffect = callback  callback()  activeEffect = null}let targetMap = new WeakMap()function track(target, key) {  if(!activeEffect) return  let depsMap = targetMap.get(target)  if (!depsMap) targetMap.set(target, (depsMap = new Map()))  let dep = depsMap.get(key)  if (!dep) depsMap.set(key, (dep = new Set()))  dep.add(activeEffect)}

触发更新-trigger

更新/删除属性时触发代理对象的 setter 办法,set 外部调用 trigger 办法进行更新操作。

trigger 会去依赖记录中查找对应字段依赖的 effect 并顺次执行

function trigger(target, key) {  let depsMap = targetMap.get(target)  if (!depsMap) return  const dep = depsMap.get(key)  if (dep) {    dep.forEach(effect => {      effect()    })  }}