乐趣区

关于vue.js:Vue-30-简介

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.vue

export 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.vue
import {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 = null
function 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()
    })
  }
}
退出移动版