最近发现有个项目中对 $nextTick 的用法做了约束,统一使用 this.$nextTick().then() 的方式,此约束来自 eslint-plugin-vue vue/next-tick-style

此规则强制规定 Vue.nextTick this.$nextTick 需要使用 callback 或者 Promise (Vue2.1.0以下推荐)的风格。

  • promise
  • <script>
    import { nextTick as nt } from 'vue';
    export default {
      async mounted() {
        /* ✓ GOOD */
        nt().then(() => callback());
        await nt(); callback();
        Vue.nextTick().then(() => callback());
        await Vue.nextTick(); callback();
        this.$nextTick().then(() => callback());
        await this.$nextTick(); callback();
        /* ✗ BAD */
        nt(() => callback());
        nt(callback);
        Vue.nextTick(() => callback());
        Vue.nextTick(callback);
        this.$nextTick(() => callback());
        this.$nextTick(callback);
    </script>
    
  • callback
  • <script>
    import { nextTick as nt } from 'vue';
    export default {
      async mounted() {
        /* ✓ GOOD */
        nt(() => callback());
        nt(callback);
        Vue.nextTick(() => callback());
        Vue.nextTick(callback);
        this.$nextTick(() => callback());
        this.$nextTick(callback);
        /* ✗ BAD */
        nt().then(() => callback());
        await nt(); callback();
        Vue.nextTick().then(() => callback());
        await Vue.nextTick(); callback();
        this.$nextTick().then(() => callback());
        await this.$nextTick(); callback();
    </script>
    

    默认值为promiseVue版本低于2.1.0才推荐使用callback

    "vue/next-tick-style": ["error", "promise" | "callback"]

    尝试去分析为什么引入这项规则

    1. 首先是去分析源码

    // 只贴出部分代码
    export function nextTick (cb?: Function, ctx?: Object) {
      let _resolve
      callbacks.push(() => {
        if (cb) {
          try {
            cb.call(ctx)
          } catch (e) {
            handleError(e, ctx, 'nextTick')
        } else if (_resolve) {
          _resolve(ctx)
      if (!pending) {
        pending = true
        timerFunc()
      // $flow-disable-line
      if (!cb && typeof Promise !== 'undefined') {
        return new Promise(resolve => {
          _resolve = resolve
    
  • 可以看到promise的方式其实就是不传callback,然后返回了一个Promise实例,等到timeFunc()生成的异步任务执行resolve
  • 个人观点:其实timerFunc本身就按promiseMutationObserversetImmediatesetTimeout的顺序注册了异步任务,然后promise的格式执行then的时候又是一个异步任务,感觉不是很有必要这样去约束
  • 分析到这里,还是不太理解,然后继续,就到eslint-plugin-vuegithub上去找相关信息

    2. 上github查找

    然后在上面找到了vue/next-tick-style的提案详情 总的来说就只是为了代码更加简洁和统一,并没有什么深层次的原因

    个人观点:

  • 感觉callback的方式反而更加地直观和简洁,promise的方式还需要在then里面去做回调操作(也可能是用习惯了callback的方式)
  • 建议是爱用哪个用哪个,统一就好

  • vue/next-tick-style官方文档说明
  • vue/next-tick-style提案详情
  • 呼啦啦呼_
    私信