Skip to content

[BUG]v8.0.0-rc.1,使用createDecorator创建自定义装饰器,如果用在多次继承的类里,会导致混乱 #548

Open
@gowiny

Description

@gowiny

代码文件:prop.ts

import { createDecorator } from 'vue-class-component'

function createProp(params:any, target: any, propertyKey: string,descriptor?: PropertyDescriptor){
createDecorator(function (options, key) {
if(!options.props){
options.props = {}
}
const props = options.props
if(descriptor && typeof params.default === 'undefined'){
params.default = function(){ return descriptor.value }
if(options.methods){
delete options.methods[key]
}
}
//添加新的prop 到 options.props里
props[key] = params
})(target, propertyKey);
}

export function Prop(params?:any):any;
export function Prop(target: any, propertyKey: string):void;
export function Prop(target: any, propertyKey: string,descriptor: PropertyDescriptor):void;
export function Prop(target: any={}, propertyKey="",descriptor?: PropertyDescriptor):void | any {
if(propertyKey){
createProp({},target,propertyKey,descriptor)
}else{
const params = target;
return function (target: any, propertyKey: string,descriptor?: PropertyDescriptor) {
createProp(params,target,propertyKey,descriptor)
}
}
}


代码文件:my-test-input.vue
<template>
<div></div>
</template>
<script lang="ts">
import { Vue} from 'vue-class-component';
import { Prop } from '@/lib-ref/vue-class';
class MyTestSuper extends Vue {
@prop({
type:String,
default:'MyTestSuper'
})
declare readonly label:string
}

class MyTestBase1 extends MyTestSuper {
@prop({
type:String,
default:'MyTestBase1'
})
declare readonly label:string
}

export default class MyTestInput extends MyTestSuper {

}
</script>


测试文件:Test.vue

<template>
<div class="test">
<my-test-input ref="testComp" ></my-test-input>
<el-button @click="test">测试</el-button>
</div>
</template>
<script lang="ts">
import { Options,Vue } from 'vue-class-component';
import { refs} from '@/utils/app-utils';
import MyTestInput from '@/components/my/my-test/my-test-input.vue';
@Options({
components:{
MyTestInput
}
})
export default class Test extends Vue {
test(){
const testComp = refs(this,'testComp')
console.log('testComp label',testComp.label)
}
}
</script>


使用createDecorator方法定义了一个新的装饰器:Prop

MyTestSuper 类是基类
MyTestBase1 和 MyTestInput 都继承MyTestSuper 类
MyTestBase1 类里覆盖了MyTestSuper 类的 label属性定义

在测试页面点击按钮测试。
**实际输出的 label 值 是 'MyTestBase1' **
期望输出的 label 值应该是 MyTestInput 的父类MyTestSuper 里定义的 默认值:'MyTestSuper'


经过调试源码发现,createDecorator 方法里 是把 工厂函数 factory,添加到 类的构造函数的 __d 属性里,
但因为多重继承的原因,createDecorator 里取到的 Ctor.__d 都是基类 MyTestSuper 的引用,而非重新创建的数组。
所以,所有子类 使用 自定义装饰器 都 添加了一条记录到 基类的 __d里了。而子类是引用的 基类 __d,导致
MyTestSuper 的所有子类里定义的prop 都应用到所有子类,即便是非直接继承的类。

附上源代码文件:
bug-src.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions