vue——$forceUpdate()

  • 2019-04-26
  • 31
  • 0

vue的官方文档有对于数组循环渲染问题出过一个API——$forceUpdate()。

作用
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件.(官方介绍)

强制更新
vue对强制更新的介绍如下:

如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。

你可能还没有留意到数组或对象的变更检测注意事项,或者你可能依赖了一个未被 Vue 的响应式系统追踪的状态。

使用
日常的使用基本是对于v-for循环数组发生变动的时候,watch监听不到数组子元素数据的改变而不去触发update导致页面没有刷新的情况,然后主动调用this.$forceUpdate()去强制重新渲染。

原因
相比针对上述情况,大家也知道了,他的产生部分原因是因为,vue的响应式数据对于data中的数组变化是监听不到的,逼近vue对于数组方法也只重写了7种,但是vue也告诉了我们大部分需要使用这个api的原因就是因为我们写的代码‘有问题’,没有彻底理解vue的数据响应式

源码

 Vue.prototype.$forceUpdate = function () {
    const vm: Component = this
    if (vm._watcher) {
      vm._watcher.update()
    }
  }

  // vm_watcher 是vue的自定义观察者类
  // 下面是 _watcer 的 update()方法

  /**
   * Subscriber interface.
   * Will be called when a dependency changes.
   */
  update () {
    /* istanbul ignore else */
    if (this.lazy) {
      this.dirty = true
    } else if (this.sync) {
      this.run()
    } else {
      queueWatcher(this)
    }
  }

  //  下面是queueWatcher()

  /**
 * Push a watcher into the watcher queue.
 * Jobs with duplicate IDs will be skipped unless it's
 * pushed when the queue is being flushed.
 */
 export function queueWatcher (watcher: Watcher) {
  const id = watcher.id
  if (has[id] == null) {
    has[id] = true
    if (!flushing) {
      queue.push(watcher)
    } else {
      // if already flushing, splice the watcher based on its id
      // if already past its id, it will be run next immediately.
      let i = queue.length - 1
      while (i > index && queue[i].id > watcher.id) {
        i--
      }
      queue.splice(i + 1, 0, watcher)
    }
    // queue the flush
    if (!waiting) {
      waiting = true

      if (process.env.NODE_ENV !== 'production' && !config.async) {
        flushSchedulerQueue()
        return
      }
      nextTick(flushSchedulerQueue)
    }
  }
}

notes
还是希望大家能熟悉vue的底层,写更好的代码,少用$forceUpdate(),除非遇到一些不可抗力,那就没办法了

评论

还没有任何评论,你来说两句吧

- 友情链接 - Theme by Qzhai