Created
August 21, 2023 11:05
-
-
Save MrZhouZh/08a460d1504811c4ab2b4e5b478b2c13 to your computer and use it in GitHub Desktop.
Practice of composition api with Vue3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// api/index.ts | |
export type SubmitApiResult = { | |
text: string | |
status: 'ok' | |
} | |
export function submitApi(text: string) { | |
return new Promise<SubmitApiResult>((resolve, reject) => { | |
setTimeout(() => { | |
if (Math.random() > 0.5) { | |
resolve({ | |
text, | |
status: 'ok' | |
}) | |
} else { | |
reject(new Error('O..ops! something wrong.')) | |
} | |
}, 1500) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts"> | |
// Vue SFC Playground: https://play.vuejs.org/#eNqdV8tu4zYU/RWOFmMFcKUMgtm4itq0TdEp2k6QBOgiyoKRKFsJRap8OAk8/vdePvSM7ACjjSXe9+G5l/QuuGiaaKtJsAoSmYuqUUgSpRtEMVufZ4GSWZBmrKobLhTaIUFKtEel4DVagNmiE/3K68avR7H5MF5BnLGcM6lQLdfo3JgnUomKrdNw8QehlKN/uaDFh8VJxpLYZQDx4EORuqFYEfhCKNl8Snc762S/T2L4sqsVa7RC2x9qXhAK2YLcpmsMBIrdm83MvCdx5zNYQmWQWFmto0fJGZS/M8pZkIN2RYn42qgKEs+CFbISI8OQ7/Ofdk0JTZbter4h+dPM+qN8MWtZcCWIJGJLsqCTKSzWRDnx5c0/5AXeOyHUoyloHxFeE8mpNjk6tV80KyDtgZ7N9ovdHcD7Vl6+KMJkW5RJ1GjurX4WwG4ZoA6V3qd7Fp1Zu4ztAUUDF5f4gRIZa0kutOLX5D9NpIqUBFQ9O9RrQ4A914fYM0esjFmri6b6XbPkN6zwEl1hgWuJABDCCokwe727T4FXYRRFjZWtvM4JOk/RFbirJLHGllUVU0SUOAe3faa+3rZYynEBgP20Qg+cU4LBzCxzdqPznEgJgrAAhysT3obZ8qoAOPqUe9+wTZqqd7K/A1wSHyxdzlWc3hvn5MWCVWqWm4zRGPBjQUJXQ8lWs949Z7gDAgp8i07GTkbLM4WlHkDX8LsWSCiwxFSSZQ8h7PR5Gw19+9brrpyqYVfvSbiIf3XugCuhN4CxMVLVByocccRumk/WPOMA0RZTTcCgbZFWSWnBAMKBn15qnkhtCAuh1Sfu26cv/+PH/sMYTBwNwoFwLNtPg5YVg05/DcNpVe9UZ4Ge922ZPEjibuxiaWAGQoLa/ARoQx2fAHbmZMGP80Oglw6ayjt23DON49IctY9bSm5TANZm7YcADAY/DW7T0XC4hclwrL180LAgJYawPQ0tgr4rxpmNGoEWnrJjBx1zu3iA6jtpDz+GW02LCWnf0Hbs9DhpBt4mJDlIEFp0pABK4KaKK1aQF8cAj6vdxRv9UFcKOrTbQx9cwcBaIXc3cCtSYaVhni/4E5wGNuR0h2TrLRyan7Q+fXaMPHe4TeKnoWk/TrcwnQR5JLmaAgK3oduqJlyrebCqEoV/Y7WJBGYFr0EnRafR5y6HcSfaUOGMqIXA03f6jLGYSqczYY+IGaKzGZgaQ4PIpRBchIuvUcQb+QFJXhO1McR+Fhx6d3EydTqgwRJ9+nx62pIBft0oaK9933uZhGaPY9SJx8dbpxnFRy8dw0vFuIOPe+iH1tDDhC/LnnIDb0O+d1deGEcR5etwYWKZ660tzo2EO396te7uoQ/GhYRdHLD0RuCo5qwbwiVR+WZg2c6pzgDo5lrM3LrfEN9m1HWSOY6MAvC3ax6j100Cpin188rE7fMLFxhjYMuh02+IhdlyOPwHzJpE6Y47T6ojfwlgxhfVFuUUSwncyjn1V3/3JJuz9MuihqYCJOx2M8JgR3fmo4fR/Z04Gxo2gsBfiqoEpy478Ote4D5sKzCoGjvQHBo+aKUAypXfXJvUIFQWoJ9zWuVPIGjhBtfuJYmddVtaDLWN/7JAh+3/B85IeEY= | |
import { ref } from 'vue'; | |
// import { useAutoRequest } from './composables/useAutoRequest.ts' | |
import { useAutoLoading } from './composables/useAutoLoading.ts' | |
import { SubmitApiResult, submitApi } from './api/index.ts' | |
// const [loading, submit] = useAutoRequest(submitApi) | |
const [commonLoading, fetch] = useAutoLoading() | |
const result = ref<SubmitApiResult>() | |
function onSubmit() { | |
result.value = null | |
fetch(submitApi('aaa')).then(res => { | |
console.log({ res }) | |
result.value = res | |
}) | |
} | |
</script> | |
<template> | |
<div class="col"> | |
<h3>I'm test component {{ commonLoading }}</h3> | |
<pre v-if="result">result: {{ result }}</pre> | |
<button :loading="commonLoading" @click="onSubmit">Submit</button> | |
</div> | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// composables/useAutoLoading.ts | |
import type { Ref } from "vue"; | |
import { ref } from "vue"; | |
type AutoLoadingResult = [ | |
Ref<boolean>, | |
<T>(requestPromise: Promise<T>) => Promise<T> | |
] | |
export function useAutoLoading(defaultLoading = false): AutoLoadingResult { | |
const ld = ref(defaultLoading) | |
function run<T>(requestPromise: Promise<T>): Promise<T> { | |
ld.value = true | |
return requestPromise.finally(() => { | |
ld.value = false | |
}) | |
} | |
return [ld, run] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// composables/useAutoRequest.ts | |
import type { Ref } from 'vue' | |
import { ref } from 'vue' | |
type ApiFun<Data, Params extends any[]> = (...params: Params) => Promise<Data> | |
interface AutoRequestOptions { | |
loading?: boolean | |
onSuccess?: (data: any) => void | |
} | |
type AutoRequestResult<Data, Params extends any[]> = [Ref<boolean>, ApiFun<Data, Params>] | |
export function useAutoRequest<Data, Params extends any[]>( | |
fn: ApiFun<Data, Params>, | |
options?: AutoRequestOptions | |
): AutoRequestResult<Data, Params>{ | |
const { loading = false, onSuccess } = options || { loading: false } | |
const requestLoading = ref(loading) | |
const run: ApiFun<Data, Params> = (...params) => { | |
requestLoading.value = true | |
return fn(...params) | |
.then(res => { | |
onSuccess && onSuccess(res) | |
return res | |
}) | |
.finally(() => { | |
requestLoading.value = false | |
}) | |
} | |
return [requestLoading, run] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Vue SFC Playground: https://play.vuejs.org/#eNqdV8tu4zYU/RWOFmMFcKUMgtm4itq0TdEp2k6QBOgiyoKRKFsJRap8OAk8/vdePvSM7ACjjSXe9+G5l/QuuGiaaKtJsAoSmYuqUUgSpRtEMVufZ4GSWZBmrKobLhTaIUFKtEel4DVagNmiE/3K68avR7H5MF5BnLGcM6lQLdfo3JgnUomKrdNw8QehlKN/uaDFh8VJxpLYZQDx4EORuqFYEfhCKNl8Snc762S/T2L4sqsVa7RC2x9qXhAK2YLcpmsMBIrdm83MvCdx5zNYQmWQWFmto0fJGZS/M8pZkIN2RYn42qgKEs+CFbISI8OQ7/Ofdk0JTZbter4h+dPM+qN8MWtZcCWIJGJLsqCTKSzWRDnx5c0/5AXeOyHUoyloHxFeE8mpNjk6tV80KyDtgZ7N9ovdHcD7Vl6+KMJkW5RJ1GjurX4WwG4ZoA6V3qd7Fp1Zu4ztAUUDF5f4gRIZa0kutOLX5D9NpIqUBFQ9O9RrQ4A914fYM0esjFmri6b6XbPkN6zwEl1hgWuJABDCCokwe727T4FXYRRFjZWtvM4JOk/RFbirJLHGllUVU0SUOAe3faa+3rZYynEBgP20Qg+cU4LBzCxzdqPznEgJgrAAhysT3obZ8qoAOPqUe9+wTZqqd7K/A1wSHyxdzlWc3hvn5MWCVWqWm4zRGPBjQUJXQ8lWs949Z7gDAgp8i07GTkbLM4WlHkDX8LsWSCiwxFSSZQ8h7PR5Gw19+9brrpyqYVfvSbiIf3XugCuhN4CxMVLVByocccRumk/WPOMA0RZTTcCgbZFWSWnBAMKBn15qnkhtCAuh1Sfu26cv/+PH/sMYTBwNwoFwLNtPg5YVg05/DcNpVe9UZ4Ge922ZPEjibuxiaWAGQoLa/ARoQx2fAHbmZMGP80Oglw6ayjt23DON49IctY9bSm5TANZm7YcADAY/DW7T0XC4hclwrL180LAgJYawPQ0tgr4rxpmNGoEWnrJjBx1zu3iA6jtpDz+GW02LCWnf0Hbs9DhpBt4mJDlIEFp0pABK4KaKK1aQF8cAj6vdxRv9UFcKOrTbQx9cwcBaIXc3cCtSYaVhni/4E5wGNuR0h2TrLRyan7Q+fXaMPHe4TeKnoWk/TrcwnQR5JLmaAgK3oduqJlyrebCqEoV/Y7WJBGYFr0EnRafR5y6HcSfaUOGMqIXA03f6jLGYSqczYY+IGaKzGZgaQ4PIpRBchIuvUcQb+QFJXhO1McR+Fhx6d3EydTqgwRJ9+nx62pIBft0oaK9933uZhGaPY9SJx8dbpxnFRy8dw0vFuIOPe+iH1tDDhC/LnnIDb0O+d1deGEcR5etwYWKZ660tzo2EO396te7uoQ/GhYRdHLD0RuCo5qwbwiVR+WZg2c6pzgDo5lrM3LrfEN9m1HWSOY6MAvC3ax6j100Cpin188rE7fMLFxhjYMuh02+IhdlyOPwHzJpE6Y47T6ojfwlgxhfVFuUUSwncyjn1V3/3JJuz9MuihqYCJOx2M8JgR3fmo4fR/Z04Gxo2gsBfiqoEpy478Ote4D5sKzCoGjvQHBo+aKUAypXfXJvUIFQWoJ9zWuVPIGjhBtfuJYmddVtaDLWN/7JAh+3/B85IeEY=