UNPKG

vue3-oop

Version:

vue3-oop take class component and di into vue

814 lines (796 loc) 25.6 kB
"use strict"; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; 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; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { Autobind: () => Autobind, Component: () => Component, Computed: () => Computed, GlobalStoreKey: () => GlobalStoreKey, Hook: () => Hook, InjectorKey: () => InjectorKey, Link: () => Link, Mut: () => Mut, VueComponent: () => VueComponent, VueService: () => VueService, camelizePropKey: () => camelizePropKey, createCurrentInjector: () => createCurrentInjector, createDecorator: () => createDecorator, createSymbol: () => createSymbol, defMut: () => defMut, defineComponent: () => defineComponent, getCurrentApp: () => getCurrentApp, getCurrentInjector: () => getCurrentInjector, getEmitsFromProps: () => getEmitsFromProps, getProtoMetadata: () => getProtoMetadata, injectService: () => injectService, mergeRefs: () => mergeRefs, provideService: () => provideService, useClassAndStyle: () => useClassAndStyle, useCtx: () => useCtx, useForwardRef: () => useForwardRef, useProps: () => useProps }); module.exports = __toCommonJS(index_exports); // src/extends/component.ts var import_vue7 = require("vue"); // src/decorators/computed.ts var import_vue2 = require("vue"); // src/helper.ts var import_vue = require("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 = (0, import_vue.getCurrentInstance)(); return instance == null ? void 0 : instance.props; } function useCtx() { const instance = (0, import_vue.getCurrentInstance)(); return instance == null ? void 0 : instance.setupContext; } function getCurrentApp() { var _a; return (_a = (0, import_vue.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 = (0, import_vue2.shallowRef)(); (0, import_vue2.watchEffect)( () => { var _a; try { keyVal.value = (_a = desc.get) == null ? void 0 : _a.call(targetThis); } finally { } }, { flush: option === true ? "sync" : option } ); } else { keyVal = (0, import_vue2.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 var import_vue3 = require("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 = import_vue3.onBeforeMount; break; case "Mounted": vueFn = import_vue3.onMounted; break; case "BeforeUpdate": vueFn = import_vue3.onBeforeUpdate; break; case "Updated": vueFn = import_vue3.onUpdated; break; case "BeforeUnmount": vueFn = import_vue3.onBeforeUnmount; break; case "Unmounted": vueFn = import_vue3.onUnmounted; break; case "Activated": vueFn = import_vue3.onActivated; break; case "Deactivated": vueFn = import_vue3.onDeactivated; break; case "ErrorCaptured": vueFn = import_vue3.onErrorCaptured; break; case "RenderTracked": vueFn = import_vue3.onRenderTracked; break; case "RenderTriggered": vueFn = import_vue3.onRenderTriggered; break; case "ServerPrefetch": vueFn = import_vue3.onServerPrefetch; break; } doneLife[option] = true; vueFn((...args) => targetThis[item.key](...args)); } } } var HookHandler = { key: "Hook", handler: handler2 }; // src/decorators/link.ts var import_vue4 = require("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 = (0, import_vue4.getCurrentInstance)(); 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 var import_vue5 = require("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 = (0, import_vue5.shallowRef)(); } else if (typeof options === "function") { keyVal = (0, import_vue5.customRef)(options); } else { keyVal = (0, import_vue5.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 var import_vue6 = require("vue"); var import_injection_js = require("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 (0, import_injection_js.Injectable)()(target); }; } function resolveComponent(target) { var _a, _b; if (!Reflect.getMetadata("annotations", target)) return new target(); const parent = (0, import_vue6.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 = import_injection_js.ReflectiveInjector.resolve(deps); Reflect.defineMetadata(MetadataProviderKey, resolveProviders, target); } const injector = import_injection_js.ReflectiveInjector.fromResolvedProviders(resolveProviders, parent); if (options == null ? void 0 : options.globalStore) { const current = (0, import_vue6.getCurrentInstance)(); const app = current.appContext.app; app.provide(InjectorKey, injector); app.getStore = () => injector; app.getService = (token) => injector.get(token); } else { (0, import_vue6.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 = import_injection_js.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 import_injection_js.SkipSelf || dep.key.token instanceof import_injection_js.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 = (0, import_vue6.getCurrentInstance)(); return (instance == null ? void 0 : instance.provides[InjectorKey]) || (0, import_vue6.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 = import_injection_js.ReflectiveInjector.resolve(deps); const parent = (0, import_vue6.inject)(InjectorKey, void 0); const injector = import_injection_js.ReflectiveInjector.fromResolvedProviders(resolveProviders, parent); (0, import_vue6.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 = (0, import_injection_js.resolveForwardRef)(token); return currentInjector.get(token, notFoundValue); } function provideService(...service) { const instance = (0, import_vue6.getCurrentInstance)(); let injector; if (Reflect.has(instance, InjectorKey)) { injector = instance.provides[InjectorKey]; } if (!injector) { injector = import_injection_js.ReflectiveInjector.resolveAndCreate([], (0, import_vue6.inject)(InjectorKey)); instance.provides[InjectorKey] = injector; } import_injection_js.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.$ = (0, import_vue7.getCurrentInstance)(); (0, import_vue7.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); (0, import_vue7.getCurrentInstance)().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 = (0, import_vue7.getCurrentInstance)(); 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 ((0, import_vue7.isRef)(r)) { r.value = ref2; } } }; } // src/extends/service.ts var import_vue8 = require("vue"); var _VueService = class _VueService { constructor() { (0, import_vue8.markRaw)(this); _VueService.handler.forEach((handler5) => handler5.handler(this)); } }; _VueService.handler = [MutHandler, ComputedHandler, LinkHandler, HookHandler]; var VueService = _VueService; // src/simple-props/index.ts var import_vue10 = require("vue"); // src/simple-props/composables.ts var import_vue9 = require("vue"); function camelizePropKey(p) { if (typeof p === "string") { if (p.startsWith("data-")) return p; return (0, import_vue9.camelize)(p); } return p; } function useProps2() { const instance = (0, import_vue9.getCurrentInstance)(); if (!instance) { throw new Error("useProps must be called inside setup()"); } const slots = (0, import_vue9.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" ? (0, import_vue9.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 = (0, import_vue9.getCurrentInstance)(); if (!instance) { throw new Error("useClassAndStyle must be called inside setup()"); } const attrs = (0, import_vue9.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 (0, import_vue10.defineComponent)(fn, __spreadValues({ inheritAttrs: false, name: comp.name || comp.displayName }, extraOptions)); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { 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 });