Skip to content

Extend options should not be confused with the super options #4767

@z-ZYS-s

Description

@z-ZYS-s

A simple case:

const Base = Vue.extend({
  computed: {
    a () { return 'aa' }
  }
})
const Sub = Base.extend()
Sub.options.computed.b = () => 'bb'

console.log(Base.options.computed.b()) // 'bb'
console.log(Base.options.computed === Sub.options.computed) // true

The reason has been found, in line 181, vue/src/core/util/options.js

strats.props =
strats.methods =
strats.computed = function (parentVal: ?Object, childVal: ?Object): ?Object {
  if (!childVal) return parentVal

It just return the parent object. Maybe it should be replaced by code like this

strats.props =
strats.methods =
strats.computed = function (parentVal: ?Object, childVal: ?Object): ?Object {
  if (!childVal) return extend({}, parentVal)

There is a same problem for strats.watch in line 158.
There is no need to change strats.data in line 69 because the type is function.

I'd like to submit a PR but I'm not familiar with the code, like that props could be a Array so more things should be done after `extend({}, parentVal)...

Hope someone can fix this bug, Thanks!


Actually, it is not commonly used to set Sub.options.computed directly, but I met this bug when using vue-loader with css module. For example:

base.vue

<template>
<div :class="$style.base">base<div>
</template>
<script>
import Vue from 'vue';

export default Vue.extend({
  name: 'my-base',
});
</script>
<style module>
.base {
  color: red;
}
</style>

sub.vue

<template>
<div :class="$style.sub">sub<div>
</template>
<script>
import Base from './base.vue';

export default Vue.extend({
  name: 'my-sub',
});
</script>
<style module>
.sub {
  color: blue;
}
</style>

And finally, you will find that the computed property $style of <my-base> has been replaced by the one of <my-sub>. They share the same $style in fact.

The following lines using options directly are in vue-loader:

  • __vue_options__ = __vue_options__.options in line 254, vue-loader/lib/loader.js
  • __vue_options__.computed[key] = function () { return module } in line 285

And with the mentioned bug above in vue cause the final problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions