diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6c486b9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "prettier.configPath": ".prettierrc" +} diff --git a/package.json b/package.json index 65c2f2e..d99271c 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { - "name": "@vue-hooks-plus/monorepo", - "version": "1.0.0", - "private": true, + "name": "@vue-hooks-plus/monorepo", + "version": "1.0.0", + "private": true, "scripts": { - "bootstrap": "tsx scripts/bootstrap.ts", - "build:vitepress-demo-block":"cd packages/vitepress/vitepress-demo-block && pnpm build", - "docs:dev":"pnpm build:vitepress-demo-block && tsx scripts/docs.ts dev", - "docs:build":"pnpm build:vitepress-demo-block && tsx scripts/docs.ts build", - "docs:build-github":"pnpm build:vitepress-demo-block && tsx scripts/gitPage.ts github", - "docs:build-gitee":"pnpm build:vitepress-demo-block && tsx scripts/gitPage.ts gitee", - "clean": " rimraf dist lib es", + "bootstrap": "tsx scripts/bootstrap.ts", + "build:vitepress-demo-block": "cd packages/vitepress/vitepress-demo-block && pnpm build", + "docs:dev": "pnpm build:vitepress-demo-block && tsx scripts/docs.ts dev", + "docs:build": "pnpm build:vitepress-demo-block && tsx scripts/docs.ts build", + "docs:build-github": "pnpm build:vitepress-demo-block && tsx scripts/gitPage.ts github", + "docs:build-gitee": "pnpm build:vitepress-demo-block && tsx scripts/gitPage.ts gitee", + "clean": " rimraf dist lib es", "build": "pnpm bootstrap && tsx scripts/build.ts", - "test": "vitest", + "test": "vitest", "test:ui": "vitest --ui", - "coverage": "vitest run --coverage", + "coverage": "vitest run --coverage", "prepare": "husky install" }, "devDependencies": { @@ -30,20 +30,20 @@ "@types/node": "^17.0.21", "@types/qs": "^6.9.7", "@vitejs/plugin-vue": "^2.3.1", - "@vue/compiler-core": "^3.2.37", - "@vue-hooks-plus/vite-plugin-gen-temp": "^2.6.6", + "@vue/compiler-core": "^3.2.37", + "@vue-hooks-plus/vite-plugin-gen-temp": "^2.6.6", "@vue-hooks-plus/md-demo-plugins": "^1.0.0", "@vue-hooks-plus/vitepress": "^1.2.4", "@vue-hooks-plus/vitepress-demo-block": "workspace:^1.0.0", - "@vue-hooks-plus/use-immer":"workspace:^1.0.0", - "@vue-hooks-plus/use-worker":"workspace:^1.0.0", - "@vue-hooks-plus/use-request":"workspace:^2.0.0", - "@vue-hooks-plus/use-request-plugins":"workspace:^2.0.0", - "@vue-hooks-plus/types":"workspace:^2.0.0", - "@vue-hooks-plus/eslint-config":"workspace:^1.0.0", + "@vue-hooks-plus/use-immer": "workspace:^1.0.0", + "@vue-hooks-plus/use-worker": "workspace:^1.0.0", + "@vue-hooks-plus/use-request": "workspace:^2.0.0", + "@vue-hooks-plus/use-request-plugins": "workspace:^2.0.0", + "@vue-hooks-plus/types": "workspace:^2.0.0", + "@vue-hooks-plus/eslint-config": "workspace:^1.0.0", "@vue/test-utils": "^2.1.0", - "@vitest/coverage-c8":"^0.25.7", - "execa":"^6.1.0", + "@vitest/coverage-c8": "^0.25.7", + "execa": "^6.1.0", "husky": "^8.0.1", "lint-staged": "^13.0.3", "cross-env": "^7.0.3", @@ -52,12 +52,12 @@ "gh-pages": "^4.0.0", "happy-dom": "^7.5.10", "less": "^4.1.3", - "kolorist": "^1.6.0", + "kolorist": "^1.6.0", "prettier": "^1.19.1", "rimraf": "^3.0.2", "ts-morph": "^13.0.2", "ts-node": "^10.7.0", - "tsx": "^3.11.0", + "tsx": "^3.11.0", "typeit": "^8.7.0", "typescript": "^5.0.4", "vite": "3.0.2", @@ -68,11 +68,11 @@ "vue": "^3.2.25", "vue-tsc": "1.0.9", "vue-typical": "^2.1.0", - "pinia":"^2.0.34", - "broadcast-channel":"^5.1.0", - "three":"0.147.0", - "axios": "^1.4.0", - "vue-demi": "^0.13.11" + "pinia": "^2.0.34", + "broadcast-channel": "^5.1.0", + "three": "0.147.0", + "axios": "^1.4.0", + "vue-demi": "^0.13.11" }, "lint-staged": { "*.{js,ts,tsx,vue}": [ @@ -88,4 +88,4 @@ "vue hooks", "typeScript" ] -} +} \ No newline at end of file diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 204cba6..80fa906 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -33,7 +33,7 @@ "type": "tsc -d" }, "dependencies": { - "@vue/devtools-api": "^6.5.0", + "@vue/devtools-api": "^6.5.0", "@types/js-cookie": "^3.0.1", "js-cookie": "^3.0.1", "lodash": "^4.17.21", @@ -41,11 +41,11 @@ "query-string": "^7.1.1", "screenfull": "^5.0.0" }, - "peerDependencies": { + "peerDependencies": { "vue": "^3.2.25" }, "repository": "https://github.com/InhiblabCore/vue-hooks-plus", "homepage": "https://github.com/InhiblabCore/vue-hooks-plus", "author": "NelsonYong", "license": "MIT" -} +} \ No newline at end of file diff --git a/packages/hooks/src/useKeyPress/index.ts b/packages/hooks/src/useKeyPress/index.ts index abe4af3..4d836f3 100644 --- a/packages/hooks/src/useKeyPress/index.ts +++ b/packages/hooks/src/useKeyPress/index.ts @@ -1,5 +1,4 @@ import { ref } from 'vue' -// import { isFunction, isNumber, isString } from 'lodash' import { BasicTarget, getTargetElement } from '../utils/domTarget' import useDeepCompareEffectWithTarget from '../utils/useDeepCompareWithTarget' import { isNumber, isFunction, isString } from '../utils' diff --git a/packages/hooks/src/useRequest/plugins/useDebouncePlugin.ts b/packages/hooks/src/useRequest/plugins/useDebouncePlugin.ts index 7d3aae7..47bc2db 100644 --- a/packages/hooks/src/useRequest/plugins/useDebouncePlugin.ts +++ b/packages/hooks/src/useRequest/plugins/useDebouncePlugin.ts @@ -7,7 +7,7 @@ const useDebouncePlugin: UseRequestPlugin = ( fetchInstance, { debounceWait, debounceLeading, debounceTrailing, debounceMaxWait } ) => { - const debouncedRef = ref>(); + const debouncedRef = ref void) => void>>(); const options = computed(() => { const ret: DebounceSettings = {}; const debounceLeading_ = unref(debounceLeading) diff --git a/packages/hooks/src/useRequest/plugins/useThrottlePlugin.ts b/packages/hooks/src/useRequest/plugins/useThrottlePlugin.ts index 2ced2af..6c6a1a0 100644 --- a/packages/hooks/src/useRequest/plugins/useThrottlePlugin.ts +++ b/packages/hooks/src/useRequest/plugins/useThrottlePlugin.ts @@ -1,5 +1,5 @@ import { computed, unref, watchEffect } from 'vue' -import { DebouncedFunc, ThrottleSettings } from 'lodash' +import type { DebouncedFunc, ThrottleSettings } from 'lodash' import throttle from 'lodash/throttle' import { UseRequestPlugin } from '../types' diff --git a/packages/resolvers/package.json b/packages/resolvers/package.json index 28232b1..73df126 100644 --- a/packages/resolvers/package.json +++ b/packages/resolvers/package.json @@ -38,12 +38,5 @@ }, "peerDependencies": { "vue-hooks-plus": ">=1.5.2" - }, - "pnpm": { - "peerDependencyRules": { - "ignoreMissing": [ - "vue" - ] - } } } diff --git a/packages/tools/lodash/.internal/freeGlobal.ts b/packages/tools/lodash/.internal/freeGlobal.ts new file mode 100644 index 0000000..8cc5145 --- /dev/null +++ b/packages/tools/lodash/.internal/freeGlobal.ts @@ -0,0 +1,5 @@ +/** Detect free variable `global` from Node.js. */ +const freeGlobal = + typeof global === 'object' && global !== null && global.Object === Object && global + +export default freeGlobal diff --git a/packages/tools/lodash/.internal/root.ts b/packages/tools/lodash/.internal/root.ts new file mode 100644 index 0000000..c08103a --- /dev/null +++ b/packages/tools/lodash/.internal/root.ts @@ -0,0 +1,17 @@ +/* global globalThis, self */ +import freeGlobal from './freeGlobal' + +/** Detect free variable `globalThis` */ +const freeGlobalThis = + typeof globalThis === 'object' && + globalThis !== null && + globalThis.Object === Object && + globalThis + +/** Detect free variable `self`. */ +const freeSelf = typeof self === 'object' && self !== null && self.Object === Object && self + +/** Used as a reference to the global object. */ +const root = freeGlobalThis || freeGlobal || freeSelf || Function('return this')() + +export default root diff --git a/packages/tools/lodash/debounce.ts b/packages/tools/lodash/debounce.ts new file mode 100644 index 0000000..b803fe7 --- /dev/null +++ b/packages/tools/lodash/debounce.ts @@ -0,0 +1,253 @@ +import isObject from './isObject' +import root from './.internal/root' + +export interface DebouncedFunc any> { + /** + * Call the original function, but applying the debounce rules. + * + * If the debounced function can be run immediately, this calls it and returns its return + * value. + * + * Otherwise, it returns the return value of the last invocation, or undefined if the debounced + * function was not invoked yet. + */ + (...args: Parameters): ReturnType | undefined + + /** + * Throw away any pending invocation of the debounced function. + */ + cancel(): void + + /** + * If there is a pending invocation of the debounced function, invoke it immediately and return + * its return value. + * + * Otherwise, return the value from the last invocation, or undefined if the debounced function + * was never invoked. + */ + flush(): ReturnType | undefined +} +export interface DebounceSettings { + leading?: boolean | undefined + maxWait?: number | undefined + trailing?: boolean | undefined +} + +/** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked, or until the next browser frame is drawn. The debounced function + * comes with a `cancel` method to cancel delayed `func` invocations and a + * `flush` method to immediately invoke them. Provide `options` to indicate + * whether `func` should be invoked on the leading and/or trailing edge of the + * `wait` timeout. The `func` is invoked with the last arguments provided to the + * debounced function. Subsequent calls to the debounced function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until the next tick, similar to `setTimeout` with a timeout of `0`. + * + * If `wait` is omitted in an environment with `requestAnimationFrame`, `func` + * invocation will be deferred until the next frame is drawn (typically about + * 16ms). + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `debounce` and `throttle`. + * + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] + * The number of milliseconds to delay; if omitted, `requestAnimationFrame` is + * used (if available). + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', debounce(calculateLayout, 150)) + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })) + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * const debounced = debounce(batchLog, 250, { 'maxWait': 1000 }) + * const source = new EventSource('/stream') + * jQuery(source).on('message', debounced) + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel) + * + * // Check for pending invocations. + * const status = debounced.pending() ? "Pending..." : "Ready" + */ +export function debounce( + func: VoidFunction, + wait: number, + options?: DebounceSettings, +): { (...args: any[]): any; cancel: () => void; flush: () => any; pending: () => boolean } { + let lastArgs: any + let lastThis: any + let maxWait: number + let result: any + let timerId: number | undefined + let lastCallTime: number | undefined + let lastInvokeTime = 0 + let leading = false + let maxing = false + let trailing = true + + // Bypass `requestAnimationFrame` by explicitly setting `wait=0`. + const useRAF = !wait && wait !== 0 && typeof root.requestAnimationFrame === 'function' + + if (typeof func !== 'function') { + throw new TypeError('Expected a function') + } + wait = +wait || 0 + if (isObject(options)) { + leading = !!options?.leading + maxing = 'maxWait' in (options ?? {}) + maxWait = maxing ? Math.max(+(options?.maxWait ?? 0), wait) : 0 + trailing = options?.trailing ?? trailing + } + + function invokeFunc(time: number) { + const args = lastArgs + const thisArg = lastThis + + lastArgs = lastThis = undefined + lastInvokeTime = time + result = func.apply(thisArg, args) + return result + } + + function startTimer(pendingFunc: () => void, milliseconds: number) { + if (useRAF) { + root.cancelAnimationFrame(timerId) + return root.requestAnimationFrame(pendingFunc) + } + // eslint-disable-next-line @typescript-eslint/no-implied-eval + return setTimeout(pendingFunc, milliseconds) + } + + function cancelTimer(id: number) { + if (useRAF) { + root.cancelAnimationFrame(id) + return + } + clearTimeout(id) + } + + function leadingEdge(time: number) { + // Reset any `maxWait` timer. + lastInvokeTime = time + // Start the timer for the trailing edge. + timerId = startTimer(timerExpired, wait) + // Invoke the leading edge. + return leading ? invokeFunc(time) : result + } + + function remainingWait(time: number) { + const timeSinceLastCall = time - (lastCallTime ?? 0) + const timeSinceLastInvoke = time - lastInvokeTime + const timeWaiting = wait - timeSinceLastCall + + return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting + } + + function shouldInvoke(time: number) { + const timeSinceLastCall = time - (lastCallTime ?? 0) + const timeSinceLastInvoke = time - lastInvokeTime + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return ( + lastCallTime === undefined || + timeSinceLastCall >= wait || + timeSinceLastCall < 0 || + (maxing && timeSinceLastInvoke >= maxWait) + ) + } + + function timerExpired() { + const time = Date.now() + if (shouldInvoke(time)) { + return trailingEdge(time) + } + // Restart the timer. + timerId = startTimer(timerExpired, remainingWait(time)) + return undefined + } + + function trailingEdge(time: number) { + timerId = undefined + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time) + } + lastArgs = lastThis = undefined + return result + } + + function cancel() { + if (timerId !== undefined) { + cancelTimer(timerId) + } + lastInvokeTime = 0 + lastArgs = lastCallTime = lastThis = timerId = undefined + } + + function flush() { + return timerId === undefined ? result : trailingEdge(Date.now()) + } + + function pending() { + return timerId !== undefined + } + + function debounced(...args: any[]) { + const time = Date.now() + const isInvoking = shouldInvoke(time) + + lastArgs = args + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-this-alias + lastThis = this + lastCallTime = time + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime) + } + if (maxing) { + // Handle invocations in a tight loop. + timerId = startTimer(timerExpired, wait) + return invokeFunc(lastCallTime) + } + } + if (timerId === undefined) { + timerId = startTimer(timerExpired, wait) + } + return result + } + debounced.cancel = cancel + debounced.flush = flush + debounced.pending = pending + return debounced +} diff --git a/packages/tools/lodash/index.ts b/packages/tools/lodash/index.ts new file mode 100644 index 0000000..3c52094 --- /dev/null +++ b/packages/tools/lodash/index.ts @@ -0,0 +1 @@ +export * from './debounce' diff --git a/packages/tools/lodash/isObject.ts b/packages/tools/lodash/isObject.ts new file mode 100644 index 0000000..3003311 --- /dev/null +++ b/packages/tools/lodash/isObject.ts @@ -0,0 +1,29 @@ +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * isObject({}) + * // => true + * + * isObject([1, 2, 3]) + * // => true + * + * isObject(Function) + * // => true + * + * isObject(null) + * // => false + */ +function isObject(value: unknown): boolean { + const type = typeof value + return value != null && (type === 'object' || type === 'function') +} + +export default isObject diff --git a/packages/tools/package.json b/packages/tools/package.json new file mode 100644 index 0000000..0afe2e4 --- /dev/null +++ b/packages/tools/package.json @@ -0,0 +1,19 @@ +{ + "name": "@vue-hooks-plus/tools", + "version": "0.0.1", + "private": true, + "description": "library", + "type": "module", + "exports": { + "./lodash": "./src/lodash/index.ts" + }, + "scripts": { + "build":"echo 'no build'", + "clean": "rimraf dist" + }, + "keywords": [], + "repository": "https://github.com/InhiblabCore/vue-hooks-plus", + "homepage": "https://github.com/InhiblabCore/vue-hooks-plus", + "author": "NelsonYong", + "license": "MIT" +} diff --git a/packages/tools/tsconfig.json b/packages/tools/tsconfig.json new file mode 100644 index 0000000..0d5644c --- /dev/null +++ b/packages/tools/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", //输出文件 + "lib": ["esnext", "dom"], + "baseUrl": "./", + "rootDir": "./" + }, + "include": ["lodash"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/use-request/src/plugins/useThrottlePlugin.ts b/packages/use-request/src/plugins/useThrottlePlugin.ts index 2ced2af..6c6a1a0 100644 --- a/packages/use-request/src/plugins/useThrottlePlugin.ts +++ b/packages/use-request/src/plugins/useThrottlePlugin.ts @@ -1,5 +1,5 @@ import { computed, unref, watchEffect } from 'vue' -import { DebouncedFunc, ThrottleSettings } from 'lodash' +import type { DebouncedFunc, ThrottleSettings } from 'lodash' import throttle from 'lodash/throttle' import { UseRequestPlugin } from '../types'