Skip to content

Commit 485ccac

Browse files
committed
feat: support component
1 parent 112fd55 commit 485ccac

File tree

6 files changed

+190
-5
lines changed

6 files changed

+190
-5
lines changed

docs/demo/useMouse/demo.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
<p>Client - x: {{ mouse.clientX }}, y: {{ mouse.clientY }}</p>
44
<p>Page - x: {{ mouse.pageX }}, y: {{ mouse.pageY }}</p>
55
<p>Screen - x: {{ mouse.screenX }}, y: {{ mouse.screenY }}</p>
6+
<UseMouse v-slot="{ clientX, clientY }">
7+
<p>component use: {{ clientX }}, y: {{ clientY }}</p>
8+
</UseMouse>
69
</div>
710
</template>
811

912
<script lang="ts" setup>
10-
import { useMouse } from 'vue-hooks-plus'
13+
import { useMouse, UseMouse } from 'vue-hooks-plus'
1114
const mouse = useMouse()
1215
</script>

docs/demo/useMouse/demo1.vue

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,39 @@
2121
{{ mouse.elementH }}
2222
</p>
2323
</div>
24+
25+
<h3>UseMouse Component</h3>
26+
<UseMouse>
27+
<template #default="{ elementX, elementY,elementPosX,elementPosY,elementW,elementH }">
28+
<p>Mouse In Element - x: {{ elementX }}, y: {{ elementY }}</p>
29+
<p> Element Position - x: {{ elementPosX }}, y: {{ elementPosY }} </p>
30+
<p>
31+
Element Dimensions - width: {{ elementW }}, height:
32+
{{ elementH }}
33+
</p>
34+
</template>
35+
<template #target>
36+
<div
37+
ref="domRef"
38+
:style="{
39+
width: '200px',
40+
height: '200px',
41+
backgroundColor: 'gray',
42+
opacity: 0.85,
43+
color: 'white',
44+
lineHeight: '200px',
45+
textAlign: 'center',
46+
}"
47+
>
48+
element
49+
</div>
50+
</template>
51+
</UseMouse>
2452
</template>
2553

2654
<script lang="ts" setup>
2755
import { ref } from 'vue'
28-
import { useMouse } from 'vue-hooks-plus'
56+
import { useMouse, UseMouse } from 'vue-hooks-plus'
2957
const domRef = ref(null)
3058
const mouse = useMouse(domRef)
3159
</script>

docs/demo/useRequest/demo.vue

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
<template>
22
<div>name:{{ loading ? 'loading' : data }}</div>
3+
<h3>UseRequest component</h3>
4+
<use-request-query :service="() => getUsername({ desc: desc })" :refresh-deps="[desc]">
5+
<template #default="{data}">
6+
<div>name:{{ data }}</div>
7+
</template>
8+
<template #loading>
9+
<div>loading</div>
10+
</template>
11+
<template #error>
12+
<div>error</div>
13+
</template>
14+
</use-request-query>
315
</template>
416

517
<script lang="ts" setup>
6-
import { useRequest } from 'vue-hooks-plus'
18+
import { onMounted, ref } from 'vue'
19+
import { useRequest, createUseRequestQueryComponent } from 'vue-hooks-plus'
720
21+
const desc = ref('good')
22+
const UseRequestQuery = createUseRequestQueryComponent<string>()
823
function getUsername(params: { desc: string }): Promise<string> {
924
return new Promise(resolve => {
1025
setTimeout(() => {
@@ -13,8 +28,15 @@
1328
})
1429
}
1530
16-
const { data, loading } = useRequest(() => getUsername({ desc: 'good' }), {
31+
const { data, loading } = useRequest(() => getUsername({ desc: desc.value }), {
1732
debugKey: 'demo',
18-
initialData:"000"
33+
initialData: '000',
34+
refreshDeps: [desc],
35+
})
36+
37+
onMounted(() => {
38+
setTimeout(() => {
39+
desc.value = 'good1111'
40+
}, 3000)
1941
})
2042
</script>

packages/hooks/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ import useWebSocket from './useWebSocket'
5353
import useElementBounding from './useElementBounding'
5454
import useResizeObserver from './useResizeObserver'
5555
import useMutationObserver from './useMutationObserver'
56+
import { UseMouse } from './useMouse/component'
57+
import createUseRequestQueryComponent from './useRequest/component-use/UseRequest'
5658

5759
export {
5860
useRequest,
@@ -109,4 +111,6 @@ export {
109111
useWebSocket,
110112
useElementBounding,
111113
useResizeObserver,
114+
UseMouse,
115+
createUseRequestQueryComponent
112116
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { computed, defineComponent, ref, SlotsType, cloneVNode, isVNode } from "vue";
2+
import useMouse from ".";
3+
4+
export const UseMouse = defineComponent({
5+
name: "UseMouse",
6+
slots: Object as SlotsType<{
7+
default: (props: ReturnType<typeof useMouse>["value"]) => any,
8+
target?: () => any
9+
}>,
10+
setup(_, { slots }) {
11+
const targetRef = ref();
12+
// @ts-ignore
13+
const data = useMouse(targetRef);
14+
return () => {
15+
const targetVNode = slots.target?.();
16+
let target = null;
17+
if (targetVNode && targetVNode.length === 1 && isVNode(targetVNode[0])) {
18+
target = cloneVNode(targetVNode[0], { ref: targetRef });
19+
}
20+
return [
21+
target,
22+
slots.default && slots.default(computed(() => data.value).value)
23+
];
24+
};
25+
},
26+
});
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { defineComponent, PropType, computed, SlotsType, unref, watch } from "vue";
2+
import useRequest from "../useRequest";
3+
import type {
4+
UseRequestService,
5+
UseRequestOptions,
6+
UseRequestPlugin,
7+
} from "../types";
8+
9+
// 泛型工厂
10+
function createUseRequestQueryComponent<TData = any, TParams extends unknown[] = any[]>() {
11+
// 先定义组件
12+
const Comp = defineComponent({
13+
name: "UseRequest",
14+
props: {
15+
service: {
16+
type: Function as PropType<UseRequestService<TData, TParams>>,
17+
required: true,
18+
},
19+
20+
initialData: {
21+
type: String,
22+
default: () => undefined,
23+
},
24+
ready: {
25+
// 支持 initialData
26+
type: Object as PropType<
27+
UseRequestOptions<TData, TParams>['ready']
28+
>,
29+
default: () => ({
30+
ready: false,
31+
}),
32+
},
33+
refreshDeps: {
34+
type: Array as PropType<any[]>,
35+
default: () => [],
36+
},
37+
plugins: {
38+
type: Array as PropType<UseRequestPlugin<TData, TParams>[]>,
39+
default: () => [],
40+
},
41+
},
42+
slots: Object as SlotsType<{
43+
default: (props: Pick<ReturnType<typeof useRequest<TData, TParams>>, "data">) => any,
44+
loading: () => any,
45+
error: (props: { error: ReturnType<typeof useRequest<TData, TParams>>["error"]['value'] }) => any,
46+
target?: () => any
47+
}>,
48+
setup(props, { slots }) {
49+
50+
// 支持响应式 props
51+
const service = computed(() => unref(props.service));
52+
const plugins = computed(() => unref(props.plugins));
53+
54+
55+
// 让 props 转为响应式
56+
const ready = computed(() => props.ready);
57+
const refreshDeps = computed(() => props.refreshDeps);
58+
59+
60+
// useRequest 的返回类型会自动推断
61+
const result = useRequest(service.value, {
62+
// @ts-ignore
63+
initialData: props.initialData,
64+
// @ts-ignore
65+
ready,
66+
// @ts-ignore
67+
refreshDeps,
68+
}, plugins.value);
69+
70+
watch(
71+
refreshDeps,
72+
() => {
73+
result.refresh();
74+
},
75+
{ immediate: true, deep: true }
76+
);
77+
78+
return () => {
79+
if (result.loading.value && slots.loading) {
80+
return slots.loading();
81+
}
82+
if (result.error.value && slots.error) {
83+
return slots.error({ error: result.error.value });
84+
}
85+
if (!result.loading.value && !result.error.value && slots.default) {
86+
87+
return slots.default({
88+
// @ts-ignore
89+
data: result.data.value
90+
});
91+
}
92+
return null;
93+
};
94+
},
95+
});
96+
97+
// 用类型断言给组件加上 slots 类型声明
98+
return Comp
99+
}
100+
101+
// 导出泛型组件工厂
102+
export default createUseRequestQueryComponent;

0 commit comments

Comments
 (0)