vue3-oop
Version:
vue3-oop take class component and di into vue
777 lines (760 loc) • 23.3 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/extends/component.ts
import { getCurrentInstance as getCurrentInstance4, isRef, markRaw } from "vue";
// src/decorators/computed.ts
import { computed, shallowRef, watchEffect } from "vue";
// src/helper.ts
import { getCurrentInstance } from "vue";
// node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js
function _typeof(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function _typeof2(obj2) {
return typeof obj2;
};
} else {
_typeof = function _typeof2(obj2) {
return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
};
}
return _typeof(obj);
}
function boundMethod(target, key, descriptor) {
var fn = descriptor.value;
if (typeof fn !== "function") {
throw new TypeError("@boundMethod decorator can only be applied to methods not: ".concat(_typeof(fn)));
}
var definingProperty = false;
return {
configurable: true,
get: function get() {
if (definingProperty || this === target.prototype || this.hasOwnProperty(key) || typeof fn !== "function") {
return fn;
}
var boundFn = fn.bind(this);
definingProperty = true;
Object.defineProperty(this, key, {
configurable: true,
get: function get2() {
return boundFn;
},
set: function set(value) {
fn = value;
delete this[key];
}
});
definingProperty = false;
return boundFn;
},
set: function set(value) {
fn = value;
}
};
}
function boundClass(target) {
var keys;
if (typeof Reflect !== "undefined" && typeof Reflect.ownKeys === "function") {
keys = Reflect.ownKeys(target.prototype);
} else {
keys = Object.getOwnPropertyNames(target.prototype);
if (typeof Object.getOwnPropertySymbols === "function") {
keys = keys.concat(Object.getOwnPropertySymbols(target.prototype));
}
}
keys.forEach(function(key) {
if (key === "constructor") {
return;
}
var descriptor = Object.getOwnPropertyDescriptor(target.prototype, key);
if (typeof descriptor.value === "function") {
Object.defineProperty(target.prototype, key, boundMethod(target, key, descriptor));
}
});
return target;
}
function autobind() {
if (arguments.length === 1) {
return boundClass.apply(void 0, arguments);
}
return boundMethod.apply(void 0, arguments);
}
// src/helper.ts
function Autobind() {
return autobind;
}
function useProps() {
const instance = getCurrentInstance();
return instance == null ? void 0 : instance.props;
}
function useCtx() {
const instance = getCurrentInstance();
return instance == null ? void 0 : instance.setupContext;
}
function getCurrentApp() {
var _a;
return (_a = getCurrentInstance()) == null ? void 0 : _a.appContext.app;
}
function getEmitsFromProps(defaultProps) {
const keys = Array.isArray(defaultProps) ? defaultProps : Object.keys(defaultProps);
const emits = [];
for (let key of keys) {
if (!/^on/.test(key)) continue;
key = key.slice(2).replace(/Once$/, "");
emits.push(key[0].toLowerCase() + key.slice(1));
}
return emits;
}
function createSymbol(name) {
return typeof Symbol === "undefined" ? name : Symbol(name);
}
// src/decorators/util.ts
function createDecorator(name, allowRepeat = false) {
const metaName = `VUE3-OOP_${name.toUpperCase()}`;
const MetadataKey2 = createSymbol(metaName);
const decoratorFn = function(options) {
return function(target, key) {
let list = Reflect.getMetadata(MetadataKey2, target) || [];
list = list.slice();
const hasIndex = list.findIndex((k) => k.key === key);
if (hasIndex === -1) {
list.push({ key, options: allowRepeat ? [options] : options });
} else {
const item = Object.assign({}, list[hasIndex]);
if (!allowRepeat) {
item.options = options;
} else if (Array.isArray(item.options)) {
item.options = item.options.concat(options);
}
list[hasIndex] = item;
}
Reflect.defineMetadata(MetadataKey2, list, target);
};
};
decoratorFn.MetadataKey = MetadataKey2;
Object.defineProperty(decoratorFn, "MetadataKey", {
get() {
return MetadataKey2;
}
});
return decoratorFn;
}
function getProtoMetadata(target, key, withDesc = false) {
const proto = Object.getPrototypeOf(target);
if (!proto) return [];
const res = Reflect.getMetadata(key, proto) || [];
if (withDesc) {
res.forEach((k) => k.desc = getDeepOwnDescriptor(proto, k.key));
}
return res;
}
function getDeepOwnDescriptor(proto, key) {
if (!proto) return null;
const desc = Object.getOwnPropertyDescriptor(proto, key);
if (desc) return desc;
return getDeepOwnDescriptor(Object.getPrototypeOf(proto), key);
}
// src/decorators/computed.ts
var Computed = createDecorator("Computed");
function handler(targetThis) {
const list = getProtoMetadata(targetThis, Computed.MetadataKey, true);
if (!list || !list.length) return;
for (const item of list) {
const desc = item.desc;
const option = item.options;
if (!desc) continue;
let keyVal;
if (option) {
keyVal = shallowRef();
watchEffect(
() => {
var _a;
try {
keyVal.value = (_a = desc.get) == null ? void 0 : _a.call(targetThis);
} finally {
}
},
{
flush: option === true ? "sync" : option
}
);
} else {
keyVal = computed({
get: () => {
var _a;
return (_a = desc.get) == null ? void 0 : _a.call(targetThis);
},
set: (v) => {
var _a;
return (_a = desc.set) == null ? void 0 : _a.call(targetThis, v);
}
});
}
Object.defineProperty(targetThis, item.key, {
enumerable: desc == null ? void 0 : desc.enumerable,
configurable: true,
get() {
return keyVal.value;
},
set(v) {
keyVal.value = v;
}
});
}
}
var ComputedHandler = {
key: "Computed",
handler
};
// src/decorators/hook.ts
import {
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onServerPrefetch,
onUnmounted,
onUpdated
} from "vue";
var Hook = createDecorator("Hook", true);
function handler2(targetThis) {
const list = getProtoMetadata(targetThis, Hook.MetadataKey);
if (!(list == null ? void 0 : list.length)) return;
for (const item of list) {
let vueFn;
const doneLife = {};
const options = item.options.slice();
for (const option of options) {
if (Array.isArray(option)) {
options.push(...option);
continue;
}
if (doneLife[option]) continue;
switch (option) {
case "BeforeMount":
vueFn = onBeforeMount;
break;
case "Mounted":
vueFn = onMounted;
break;
case "BeforeUpdate":
vueFn = onBeforeUpdate;
break;
case "Updated":
vueFn = onUpdated;
break;
case "BeforeUnmount":
vueFn = onBeforeUnmount;
break;
case "Unmounted":
vueFn = onUnmounted;
break;
case "Activated":
vueFn = onActivated;
break;
case "Deactivated":
vueFn = onDeactivated;
break;
case "ErrorCaptured":
vueFn = onErrorCaptured;
break;
case "RenderTracked":
vueFn = onRenderTracked;
break;
case "RenderTriggered":
vueFn = onRenderTriggered;
break;
case "ServerPrefetch":
vueFn = onServerPrefetch;
break;
}
doneLife[option] = true;
vueFn((...args) => targetThis[item.key](...args));
}
}
}
var HookHandler = {
key: "Hook",
handler: handler2
};
// src/decorators/link.ts
import { getCurrentInstance as getCurrentInstance2 } from "vue";
var Link = createDecorator("Link");
function handler3(targetThis) {
const list = getProtoMetadata(targetThis, Link.MetadataKey);
if (!list || !list.length) return;
for (const item of list) {
const { key, options } = item;
const instance = getCurrentInstance2();
Object.defineProperty(targetThis, key, {
enumerable: true,
configurable: true,
get() {
var _a;
return (_a = instance == null ? void 0 : instance.refs) == null ? void 0 : _a[options || key];
}
});
}
}
var LinkHandler = {
key: "Link",
handler: handler3
};
// src/decorators/mut.ts
import { customRef, ref, shallowRef as shallowRef2 } from "vue";
var Mut = createDecorator("Mut");
function handler4(targetThis) {
const list = getProtoMetadata(targetThis, Mut.MetadataKey);
if (!list || !list.length) return;
for (const item of list) {
const { options, key } = item;
defMut(targetThis, key, options);
}
}
function defMut(targetThis, key, options) {
let keyVal;
if (options === true) {
keyVal = shallowRef2();
} else if (typeof options === "function") {
keyVal = customRef(options);
} else {
keyVal = ref();
}
Object.defineProperty(targetThis, key, {
enumerable: true,
configurable: true,
get() {
return keyVal.value;
},
set(v) {
keyVal.value = v;
}
});
}
var MutHandler = {
key: "Mut",
handler: handler4
};
// src/di/index.ts
import { getCurrentInstance as getCurrentInstance3, inject, provide } from "vue";
import { Injectable, InjectionToken, ReflectiveInjector, resolveForwardRef, SkipSelf } from "injection-js";
var InjectorKey = createSymbol("VUE3-OOP_ReflectiveInjector");
var MetadataKey = createSymbol("VUE3-OOP_Component");
var MetadataProviderKey = createSymbol("VUE3-OOP_ResolveProviders");
function Component(options) {
return function(target) {
Reflect.defineMetadata(MetadataKey, options, target);
return Injectable()(target);
};
}
function resolveComponent(target) {
var _a, _b;
if (!Reflect.getMetadata("annotations", target)) return new target();
const parent = inject(InjectorKey, void 0);
let resolveProviders = Reflect.getOwnMetadata(MetadataProviderKey, target);
const options = Reflect.getOwnMetadata(MetadataKey, target);
if (!resolveProviders || (options == null ? void 0 : options.stable) === false) {
let deps = [target];
if ((_a = options == null ? void 0 : options.providers) == null ? void 0 : _a.length) {
deps = deps.concat(options.providers);
}
if ((options == null ? void 0 : options.autoResolveDeps) !== false) {
deps = resolveDependencies(deps);
}
if ((_b = options == null ? void 0 : options.exclude) == null ? void 0 : _b.length) {
deps = deps.filter((k) => {
var _a2;
return !((_a2 = options.exclude) == null ? void 0 : _a2.includes(k));
});
}
resolveProviders = ReflectiveInjector.resolve(deps);
Reflect.defineMetadata(MetadataProviderKey, resolveProviders, target);
}
const injector = ReflectiveInjector.fromResolvedProviders(resolveProviders, parent);
if (options == null ? void 0 : options.globalStore) {
const current = getCurrentInstance3();
const app = current.appContext.app;
app.provide(InjectorKey, injector);
app.getStore = () => injector;
app.getService = (token) => injector.get(token);
} else {
provide(InjectorKey, injector);
}
const compInstance = injector.get(target);
resolveProviders.forEach((k) => injector.get(k.key.token));
return compInstance;
}
function resolveDependencies(inputs) {
const noConstructor = [];
for (const input of inputs) {
if (!(input instanceof Function) && !Array.isArray(input)) {
noConstructor.push(input);
}
}
const deps = /* @__PURE__ */ new Set();
function resolver(klass) {
if (deps.has(klass) || noConstructor.find((k) => k !== klass && k.provide === klass)) return;
deps.add(klass);
const resolves = ReflectiveInjector.resolve([klass]);
for (const item of resolves) {
for (const fact of item.resolvedFactories) {
for (const dep of fact.dependencies) {
if (dep.optional || dep.visibility instanceof SkipSelf || dep.key.token instanceof InjectionToken || typeof dep.key.token !== "function") {
continue;
}
resolver(dep.key.token);
}
}
}
}
for (const input of inputs) resolver(input);
return Array.from(deps);
}
function getCurrentInjector() {
const instance = getCurrentInstance3();
return (instance == null ? void 0 : instance.provides[InjectorKey]) || inject(InjectorKey);
}
function createCurrentInjector(providers, exclude) {
let deps = resolveDependencies(providers);
if (exclude == null ? void 0 : exclude.length) {
deps = deps.filter((k) => exclude == null ? void 0 : exclude.includes(k));
}
const resolveProviders = ReflectiveInjector.resolve(deps);
const parent = inject(InjectorKey, void 0);
const injector = ReflectiveInjector.fromResolvedProviders(resolveProviders, parent);
provide(InjectorKey, injector);
resolveProviders.forEach((k) => injector.get(k.key.token));
return injector;
}
function injectService(token, notFoundValue) {
const currentInjector = getCurrentInjector();
if (!currentInjector) return notFoundValue;
if (typeof token === "function") token = resolveForwardRef(token);
return currentInjector.get(token, notFoundValue);
}
function provideService(...service) {
const instance = getCurrentInstance3();
let injector;
if (Reflect.has(instance, InjectorKey)) {
injector = instance.provides[InjectorKey];
}
if (!injector) {
injector = ReflectiveInjector.resolveAndCreate([], inject(InjectorKey));
instance.provides[InjectorKey] = injector;
}
ReflectiveInjector.resolve(service.map((k) => ({ provide: k.constructor, useValue: k }))).forEach((provider, i) => {
const index = injector._providers.length;
injector._providers[index] = provider;
injector.keyIds[index] = provider.key.id;
injector.objs[index] = service[i];
});
return injector;
}
// src/extends/component.ts
var GlobalStoreKey = "GlobalStoreKey";
var hasOwnProperty = Object.prototype.hasOwnProperty;
var hasOwn = (val, key) => hasOwnProperty.call(val, key);
var _VueComponent = class _VueComponent {
constructor() {
/** 组件属性 */
this.props = useProps();
/** 组件上下文 */
this.context = useCtx();
// 公开的一些属性 publicPropertiesMap
/** 组件内部实例,如果使用组件实例请 this.$.proxy */
this.$ = getCurrentInstance4();
markRaw(this);
const current = this.$;
current.exposed = this;
current.exposeProxy = this;
_VueComponent.handler.forEach((handler5) => handler5.handler(this));
}
/** 主要给jsx提示用 */
get $props() {
return this.props;
}
get $el() {
return this.$.proxy.$el;
}
get $data() {
return this.$.proxy.$data;
}
get $attrs() {
return this.$.proxy.$attrs;
}
get $slots() {
return this.$.proxy.$slots;
}
get $options() {
return this.$.proxy.$options;
}
get $refs() {
return this.$.proxy.$refs;
}
get $parent() {
return this.$.proxy.$parent;
}
get $root() {
return this.$.proxy.$root;
}
get $emit() {
return this.$.proxy.$emit;
}
get $forceUpdate() {
return this.$.proxy.$forceUpdate;
}
get $nextTick() {
return this.$.proxy.$nextTick;
}
get $watch() {
return this.$.proxy.$watch;
}
};
/** 装饰器处理 */
_VueComponent.handler = [MutHandler, ComputedHandler, LinkHandler, HookHandler];
/** 是否自定义解析组件 */
_VueComponent.resolveComponent = resolveComponent;
var VueComponent = _VueComponent;
Object.defineProperty(VueComponent, "__vccOpts", {
enumerable: true,
configurable: true,
get() {
if (this === VueComponent) {
console.warn("base VueComponent only to be extends");
return;
}
if (hasOwn(this, "__vccOpts__value")) return this.__vccOpts__value;
const parent = Object.getPrototypeOf(this);
const parentOpt = parent === VueComponent ? null : parent.__vccOpts;
const CompConstructor = this;
const _a = CompConstructor, { displayName, defaultProps, emits } = _a, rest = __objRest(_a, ["displayName", "defaultProps", "emits"]);
let optValue;
const setup = (props, ctx) => {
const instance = VueComponent.resolveComponent(CompConstructor);
getCurrentInstance4().data = instance;
if (CompConstructor.__vccOpts__value.render) return instance;
const render = instance.render.bind(instance);
if (typeof instance.init === "function") {
const res = instance.init();
if (typeof (res == null ? void 0 : res.then) === "function" && CompConstructor.async) {
return res.then(() => render);
}
}
return render;
};
if (parentOpt) {
optValue = __spreadProps(__spreadValues(__spreadValues({}, parentOpt), rest), {
name: displayName || CompConstructor.name,
setup
});
if (defaultProps) optValue.props = defaultProps;
if (emits) optValue.emits = emits;
} else {
optValue = __spreadProps(__spreadValues({}, rest), {
name: displayName || CompConstructor.name,
props: defaultProps || {},
// 放到emits的on函数会自动缓存
emits: (emits || []).concat(getEmitsFromProps(CompConstructor.defaultProps || {})),
setup
});
}
Object.defineProperty(this, "__vccOpts__value", {
configurable: true,
enumerable: false,
value: optValue,
writable: true
});
return optValue;
}
});
function useForwardRef() {
const instance = getCurrentInstance4();
function forwardRef(ref2) {
instance.exposed = ref2;
instance.exposeProxy = ref2;
}
return forwardRef;
}
function mergeRefs(...values) {
return function(ref2, refs) {
for (const r of values) {
if (typeof r === "string") {
refs[r] = ref2;
} else if (typeof r === "function") {
r(ref2, refs);
} else if (isRef(r)) {
r.value = ref2;
}
}
};
}
// src/extends/service.ts
import { markRaw as markRaw2 } from "vue";
var _VueService = class _VueService {
constructor() {
markRaw2(this);
_VueService.handler.forEach((handler5) => handler5.handler(this));
}
};
_VueService.handler = [MutHandler, ComputedHandler, LinkHandler, HookHandler];
var VueService = _VueService;
// src/simple-props/index.ts
import { defineComponent as vueDefineComponent } from "vue";
// src/simple-props/composables.ts
import { camelize, getCurrentInstance as getCurrentInstance5, useAttrs, useSlots } from "vue";
function camelizePropKey(p) {
if (typeof p === "string") {
if (p.startsWith("data-")) return p;
return camelize(p);
}
return p;
}
function useProps2() {
const instance = getCurrentInstance5();
if (!instance) {
throw new Error("useProps must be called inside setup()");
}
const slots = useSlots();
const getProps = () => {
return Object.fromEntries(Object.entries(instance.vnode.props || {}).map(([k, v]) => [camelizePropKey(k), v]));
};
const proxy = new Proxy(
{},
{
get(target, p, receiver) {
const slotName = getSlotName(p);
if (slotName) {
const slot = Reflect.get(slots, slotName, receiver);
if (slot) return slot;
}
const key = camelizePropKey(p);
if (key in instance.props) {
return instance.props[key];
} else {
return Reflect.get(getProps(), key, receiver);
}
},
ownKeys() {
return [
.../* @__PURE__ */ new Set([
...Reflect.ownKeys(instance.props),
...Reflect.ownKeys(getProps()),
...Reflect.ownKeys(slots).map((k) => typeof k === "string" ? camelize(`render-${k}`) : k)
])
];
},
has(target, p) {
const slotName = getSlotName(p);
if (slotName) {
return Reflect.has(slots, slotName);
}
return Reflect.has(getProps(), camelizePropKey(p));
},
getOwnPropertyDescriptor(target, p) {
const slotName = getSlotName(p);
if (slotName) {
const descriptor = Reflect.getOwnPropertyDescriptor(slots, slotName);
if (descriptor) return descriptor;
}
return Reflect.getOwnPropertyDescriptor(getProps(), camelizePropKey(p));
}
}
);
return proxy;
}
function getSlotName(p) {
if (typeof p === "string" && p.startsWith("render")) return p.slice(6).replace(/^[A-Z]/, (s) => s.toLowerCase());
}
function useClassAndStyle() {
const instance = getCurrentInstance5();
if (!instance) {
throw new Error("useClassAndStyle must be called inside setup()");
}
const attrs = useAttrs();
const keys = ["class", "style"];
return new Proxy(attrs, {
get(target, p, receiver) {
if (keys.includes(p)) {
return Reflect.get(target, p, receiver);
}
},
ownKeys: () => keys,
has: (target, p) => keys.includes(p)
});
}
// src/simple-props/index.ts
function defineComponent(comp, extraOptions) {
const fn = (_props, ctx) => {
const props = useProps2();
return comp(props, ctx);
};
Object.keys(comp).forEach((key) => {
fn[key] = comp[key];
});
return vueDefineComponent(fn, __spreadValues({
inheritAttrs: false,
name: comp.name || comp.displayName
}, extraOptions));
}
export {
Autobind,
Component,
Computed,
GlobalStoreKey,
Hook,
InjectorKey,
Link,
Mut,
VueComponent,
VueService,
camelizePropKey,
createCurrentInjector,
createDecorator,
createSymbol,
defMut,
defineComponent,
getCurrentApp,
getCurrentInjector,
getEmitsFromProps,
getProtoMetadata,
injectService,
mergeRefs,
provideService,
useClassAndStyle,
useCtx,
useForwardRef,
useProps
};