@aoao-y33/hooks 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@aoao-y33/hooks",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "description": "vue-hook包",
6
+ "main": "index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "vite build",
17
+ "add": "pnpm install",
18
+ "publish": "npm publish --access public"
19
+ },
20
+ "keywords": [],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "packageManager": "pnpm@10.32.1",
24
+ "dependencies": {
25
+ "@aoaoy33/utils": "workspace:*",
26
+ "lodash": "^4.18.1"
27
+ }
28
+ }
@@ -0,0 +1,14 @@
1
+ import {mergeDeep} from "@aoaoy33/utils";
2
+ import {type Ref, ref} from "vue";
3
+
4
+ export function useState<T>(initValue: T) {
5
+ const state = ref<T>(initValue) as Ref<T>;
6
+ const setState = (value: Partial<T> | T, write: boolean = false) => {
7
+ if (write) {
8
+ state.value = value as T;
9
+ } else {
10
+ state.value = mergeDeep(state.value, value);
11
+ }
12
+ }
13
+ return [state, setState] as const;
14
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './core/useState';
@@ -0,0 +1,91 @@
1
+ import {useState} from "@/core/useState";
2
+ import {describe, expect} from "vitest";
3
+ import {mount} from '@vue/test-utils';
4
+ import {defineComponent, nextTick} from "vue";
5
+
6
+ describe('useState 测试', () => {
7
+ it('基本数据显示 ', () => {
8
+ const vueWrapper = mount(defineComponent({
9
+ setup() {
10
+ const [state] = useState(1);
11
+ return {state};
12
+ },
13
+ template: '<div></div>'
14
+ }));
15
+ expect(vueWrapper.vm.state).toEqual(1);
16
+ });
17
+
18
+ it('数组数据显示', () => {
19
+ const vueWrapper = mount(defineComponent({
20
+ setup() {
21
+ const [state] = useState([2, 4, 5]);
22
+ return {state};
23
+ },
24
+ template: '<div></div>'
25
+ }));
26
+ expect(vueWrapper.vm.state).toEqual([2, 4, 5]);
27
+ });
28
+
29
+ it("对象数据显示", () => {
30
+ const vueWrapper = mount(defineComponent({
31
+ setup() {
32
+ const [state] = useState({name: "ax-y33"});
33
+ return {state};
34
+ },
35
+ template: '<div></div>'
36
+ }))
37
+ expect(vueWrapper.vm.state).toEqual({name: "ax-y33"});
38
+ })
39
+
40
+ it('setState 默认合并对象数据', async () => {
41
+ const vueWrapper = mount(defineComponent({
42
+ setup() {
43
+ // 初始状态包含 name 和 version
44
+ const [state, setState] = useState({ name: "ax-y33", version: "1.0.0" })
45
+ return { state, setState }
46
+ },
47
+ template: '<div></div>'
48
+ }))
49
+
50
+ const { state, setState } = vueWrapper.vm
51
+
52
+ // 仅传入部分属性进行合并
53
+ setState({ version: "2.0.0" })
54
+ await nextTick() // 等待响应式更新
55
+
56
+ // 期望 name 保留,version 被更新
57
+ expect(state).toEqual({ name: "ax-y33", version: "2.0.0" })
58
+ })
59
+
60
+ it('setState 使用 write=true 完全替换数据', async () => {
61
+ const vueWrapper = mount(defineComponent({
62
+ setup() {
63
+ const [state, setState] = useState({ name: "ax-y33", version: "1.0.0" })
64
+ // 传入第二个参数 true,期望完全替换
65
+ setState({ name: "new-app" }, true)
66
+ return { state, setState }
67
+ },
68
+ template: '<div></div>'
69
+ }))
70
+ // 期望旧的 version 属性消失,被新对象完全覆盖
71
+ expect(vueWrapper.vm.state).toEqual({ name: "new-app" })
72
+ })
73
+
74
+ it('setState 修改基本类型数据', async () => {
75
+ const vueWrapper = mount(defineComponent({
76
+ setup() {
77
+ const [state, setState] = useState(100)
78
+ return { state, setState }
79
+ },
80
+ template: '<div></div>'
81
+ }))
82
+
83
+ const { state, setState } = vueWrapper.vm
84
+
85
+ // 对于基本类型,write 参数通常影响不大(因为无法合并),主要测试赋值
86
+ setState(200)
87
+ await nextTick()
88
+
89
+ expect(state).toBe(200)
90
+ })
91
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "compilerOptions": {
4
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5
+ "types": [
6
+ "vite/client",
7
+ "vitest/globals"
8
+ ],
9
+ "declaration": true,
10
+ "declarationMap": true,
11
+ "emitDeclarationOnly": false,
12
+ "rootDir": "./src",
13
+ /* Linting */
14
+ "noUnusedLocals": true,
15
+ "noUnusedParameters": true,
16
+ "erasableSyntaxOnly": true,
17
+ "noFallthroughCasesInSwitch": true,
18
+ "baseUrl": ".",
19
+ "paths": {
20
+ "@/*": [
21
+ "src/*"
22
+ ]
23
+ }
24
+ },
25
+ "include": [
26
+ "src/**/*.ts",
27
+ "test/**/*.ts"
28
+ ]
29
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,40 @@
1
+ import {defineConfig} from "vitest/config";
2
+ import vue from '@vitejs/plugin-vue'
3
+ import {resolve} from 'path'
4
+ import dts from "vite-plugin-dts"
5
+
6
+ export default defineConfig({
7
+ plugins: [vue(),
8
+ dts({
9
+ tsconfigPath: "./tsconfig.json",
10
+ outDirs: "dist",
11
+ exclude: ["src/test"]
12
+ })
13
+ ],
14
+ build: {
15
+ lib: {
16
+ entry: resolve(__dirname, 'src/index.ts'),
17
+ formats: ['es'],
18
+ fileName: () => `index.js`
19
+ },
20
+ rollupOptions: {
21
+ external: ['vue'],
22
+ output: {
23
+ globals: {
24
+ vue: 'Vue'
25
+ },
26
+ },
27
+ },
28
+ outDir: 'dist',
29
+ sourcemap: false
30
+ },
31
+ resolve: {
32
+ alias: {
33
+ '@': resolve(__dirname, 'src')
34
+ }
35
+ },
36
+ test: {
37
+ globals: true,
38
+ environment: 'jsdom',
39
+ }
40
+ })