【问题标题】:data of extended component is undefined when used in data of extending component用于扩展组件的数据时,扩展组件的数据未定义
【发布时间】:2018-05-11 14:07:50
【问题描述】:

假设我有一个组件(单文件组件):

// Cat.vue
export default {
    data() {
        return {
            actionsPredefined: {
                eat () => (console.log('eat')),
                purr () => (console.log('purr')),
                meow () => (console.log('meow')),
            }
        }
    }
}

扩展:

// Lion.vue
export default {
    extends: Cat,

    data() {
        return {
            actions: {
                eat: this.actionsPredefined.eat, // is undefined - why?
                purr: this.actionsPredefined.purr, // is undefined - why?
                roar () => (console.log('roar'))
            }
        }
    }
}

现在当我使用 Lion.vue 时,我得到:

[Vue 警告]:data() 中的错误:“TypeError:无法读取属性‘吃’的 未定义”

所以看起来this.actionsPredefined 在 Lion.vue 中是未定义的。

这里有选择地将扩展组件(Cat.vue)的actionsPredefined与扩展组件(Lion.vue)的actions合并的正确方法是什么?

在 Lion.vue 中,当我将 actionsdata 移动到 computed 时,Vue 知道 this.actionsPredefined 是什么,但我无法将其移动到 computed(因为我需要能够更改 @987654333 @ 通过其他方法并更改计算值...显然违背了使用计算值的想法并且不起作用)。

我还可以将Lion.vue 数据中的actions 设置为空,然后仅在created() 钩子中使用predefinedActions 填充它们,它会起作用,但不知何故,它感觉不是正确的方法。

【问题讨论】:

  • 我不这么认为——我仍然可以在计算和创建的钩子中访问this.actionsPredefined。那么在这种情况下正确的做法是什么?
  • 为什么不直接创建这些方法,然后您可以根据需要覆盖或添加? codepen.io/anon/pen/YLLQKo?editors=1010
  • 但 Lions 不能喵喵叫 ;) 通过这种方法,Lion 也继承了 meow,并且只有 Cat 应该拥有 meow action。这就是我需要选择性继承的原因。
  • 如果你想挑选方法,我想我根本不会使用扩展,并且会有一组我可以导入的预定义方法。 codesandbox.io/s/r7x9lpln5m
  • 方法是在创建Vue实例时绑定到Vue的,所以方法内部的this会引用Vue(假设方法没有用箭头函数定义,一般是错误的)。查看更新的沙盒。

标签: javascript vue.js vuejs2


【解决方案1】:

Vue 调用子组件 (Lion) 的 data 函数 它调用超级组件 (Cat) 的 data 函数之前。 Cat 中定义的数据属性届时将无法在实例上使用。

我也可以在 Lion.vue 数据中设置空的 actions 并仅在 created() 钩子中填充它们,它会起作用,但不知何故它感觉不是正确的方法。

为什么不呢?如果在data 钩子中初始化actionscreated 钩子有什么区别?

【讨论】:

  • 将数据保存在data() 中感觉更干净,而不是在created hook 中使用的某些方法。我还认为Vue提供了一些其他方法来处理这种情况,似乎是一个常见的情况......
  • 不幸的是,您无法通过data()Lion 访问actionsPredefined
【解决方案2】:

我已经做了自己的测试,这是我发现的

如果您不在子类上创建 data 对象,则扩展可以正常工作,即:

//Lion
<script>
import Cat from './cat';

export default {
  extends: Cat,
  created() {
    this.actionsPredefined.purr(); //this prints purr
  }
}

</script>

如果您将data 及其继承属性定义为箭头函数,它也可以正常工作,即:

<script>
import Cat from './cat';

export default {
  extends: Cat,
  data() {
    return {
      actions: {
        eat: () => this.actionsPredefined.eat(), 
        purr: () => this.actionsPredefined.purr(),
        roar: (console.log('roar'))
      }
    }
  },
  created() {
    this.actions.eat(); // eat
    this.actions.purr(); // purr
    this.actions.roar; // roar
  }
}

</script>

还有 Cat 组件:

<script>
  export default {
    data() {
      return {
        actionsPredefined: {
          eat: () => (console.log('eat')),
          purr: () => (console.log('purr')),
          meow: () => (console.log('meow')),
        }
      }
    }
  }
</script>

【讨论】:

  • actionsPredefined 在 Lion 的 created 钩子中都可用...但是调用函数的函数,而不是直接引用函数是聪明的,没有考虑到这一点。顺便说一句,它不一定是箭头函数,它只是关于参考。
猜你喜欢
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2021-06-15
  • 2020-11-11
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 2021-08-21
相关资源
最近更新 更多