包装 Vue 计算属性和方法,同时在 Vue.extend 构造函数上保留类型签名

Wrapping Vue computed properties and methods while preserving type signature on Vue.extend constructor

我想将我所有定义的方法和计算的属性包装在一个函数中,该函数为它们的执行计时。

我想保留从 Vue.extend({...

的类型签名派生的 IntelliSense 预测

我未能在创建自己的方法的同时维护复杂类型签名,而无需从 vue.d.ts 打字中复制数十个文件。

我在调用之前替换 Vue.extend 取得了一定的成功,但我宁愿拥有自己的构造函数方法,它具有与 Vue 相同的类型优势。

庞大但有效的示例,需要 .tsconfig 中的 "noImplicitThis": false

<template>
    <div>
        {{ computedValue }}
    </div>
</template>

<script lang="ts">
    import Vue from 'vue';

    const ext = Vue.extend;
    Vue.extend = function (x: any, ...rest:any[]) {
        const f = x.computed.computedValue;
        console.log(x, rest);
        x.computed.computedValue = function () {
            const start = Date.now();
            const rtn = f.call(this, x, ...rest);
            console.log(`Took ${(Date.now() - start) / 1000} seconds`);
            return rtn;
        }
        return ext.call(this, x, ...rest);
    } as any

    const component = Vue.extend({
        computed: {
            computedValue() {
                return 'passed';
            }
        }
    });
    Vue.extend = ext;
    export default component;
</script>

期望的结果:一种被调用而不是 Vue.extend 的方法,它将计算的属性和方法包装在计时器中,同时在组件上保留 IntelliSense

到目前为止的结果:一个庞大的实现,需要在每个组件的实现中进行大量干预才能使用

在为此输入示例组件时,我设法实现了我想要的:一个包装 Vue.extend 的单一方法,同时在某些组件方法上挂接计时表。

import Vue from 'vue';
import { ThisTypedComponentOptionsWithArrayProps } from 'vue/types/options';
import { ExtendedVue } from 'vue/types/vue';

export function wrap<Data, Methods, Computed, PropNames extends string = never>
    (options: ThisTypedComponentOptionsWithArrayProps<Vue, Data, Methods, Computed, PropNames>):
    ExtendedVue<Vue, Data, Methods, Computed, Record<PropNames, any>> {
    if ('computed' in options) {
        Object.keys(options.computed as any).forEach((key: string) => {
            const f: Function = (options.computed as any)[key] as any as Function;
            (options.computed as any)[key] = function (...args: any[]) {
                const start = Date.now();
                const rtn = f.apply(this, args);
                console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
                return rtn;
            };
        });
    }
    if ('methods' in options) {
        Object.keys(options.methods as any).forEach((key: string) => {
            const f: Function = (options.methods as any)[key] as any as Function;
            (options.methods as any)[key] = function (...args: any[]) {
                const start = Date.now();
                const rtn = f.apply(this, args);
                console.log(`${key} took ${(Date.now() - start) / 1000} seconds.`);
                return rtn;
            };
        });
    }
    return Vue.extend(options);
}

只需调用 wrap({...componentOptions}) 而不是 Vue.extend({...componentOptions}) 即可挂钩计时表。

$options玩的不是太好,但偷偷摸摸的似乎可以抑制错误

    export default wrap({
        ...{
            a: 4
        },
    });