2020-11-27 MessageChannel / nextTick一例 / var a = {} 和 a = {}

128 阅读2分钟

var a = {} 和 a = {}

var a = {}a = {}的返回值不同,前者返回undefined后者返回a本身
所以有以下简写

// 当slots[name]为空的时候,会被赋值为一个新数组,而slot也会被赋值为slots[name]
var slot = (slots[name] || (slots[name] = []));

nextTick一例

<span id='name' ref='name'>{{ name }}</span>
<button @click='change'>change name</button>

methods: {
  change() {
      this.$nextTick(() => console.log('setter前:' + this.$refs.name.innerHTML))
      this.name = ' vue3 '
      console.log('同步方式:' + this.$refs.name.innerHTML)
      setTimeout(() => this.console("setTimeout方式:" + this.$refs.name.innerHTML))
      this.$nextTick(() => console.log('setter后:' + this.$refs.name.innerHTML))
      this.$nextTick().then(() => console.log('Promise方式:' + this.$refs.name.innerHTML))
  }
}
// 同步方式:vue2
// setter前:vue2
// setter后: vue3 
// Promise方式: vue3 
// setTimeout方式: vue3 

setter前为什么还打印原来的是原来内容呢,是因为 nextTick 在被调用的时候把回调挨个push进callbacks数组,之后执行的时候也是 for 循环出来挨个执行,所以是类似于队列这样一个概念,先入先出;在修改name之后,触发把render watcher填入 schedulerQueue 队列并把他的执行函数 flushSchedulerQueue 传递给 nextTick ,此时callbacks队列中已经有了 setter前函数 了,因为这个 cb 是在 setter前函数 之后被push进callbacks队列的,那么先入先出的执行callbacks中回调的时候先执行 setter前函数,这时并未执行render watcher的 watcher.run,所以打印DOM元素仍然是原来的内容。

kb.cnblogs.com/page/129756…

读取es6 class上的方法原本

Class.constructor.prototype.xxx

MessageChannel

我们知道:在浏览器环境中,常见的 macro tasksetTimeoutMessageChannelpostMessagesetImmediate。而常见的 micro taskMutationObseverPromise.then

Vue中对于 macro task 的实现,优先检测是否支持原生 setImmediate,这是一个高版本 IE 和 Edge 才支持的特性,不支持的话再去检测是否支持原生的MessageChannel,如果也不支持的话就会降级为 setTimeout 0;

该api可以实现对含有循环引用和undefined的对象的深拷贝

// 有undefined + 循环引用
    let obj = {
      a: 1,
      b: {
        c: 2,
        d: 3,
      },
      f: undefined
    }
    obj.c = obj.b;
    obj.e = obj.a
    obj.b.c = obj.c
    obj.b.d = obj.b
    obj.b.e = obj.b.c

    function deepCopy(obj) {
      return new Promise((resolve) => {
        const {port1, port2} = new MessageChannel();
        port2.onmessage = ev => resolve(ev.data);
        port1.postMessage(obj);
      });
    }

    deepCopy(obj).then((copy) => {           // 请记住`MessageChannel`是异步的这个前提!
        let copyObj = copy;
        console.log(copyObj, obj)
        console.log(copyObj == obj)
    });