UNPKG

vue3-oop

Version:

vue3-oop take class component and di into vue

777 lines (760 loc) 23.3 kB
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 };