Logo

高效开发:VueUse常用Hook的应用与实践

avatar dave 26 Aug 2024

VueUse 是一个面向 Vue 3 的功能丰富的工具库,提供了众多 Composition API 函数,旨在简化开发过程中常见任务的处理。以下是其一些实用的 Hook 及其应用实例,演示如何通过这些工具提升开发效率:

useStorage

利用useStorage可以更简便地进行本地存储操作,并实现响应式数据存取。

使用前:

window.localStorage.setItem('rememberUserName', 'true');
const remember = window.localStorage.getItem('rememberUserName');
if (remember === 'true') {
  // ...
}

window.addEventListener('storage', () => {
  // ...
}, false);

使用后:

const remember = useStorage('rememberUserName', '', window.localStorage);
remember.value = true;
if (remember.value) {
  // ...
}

watch(
  () => remember.value,
  (newVal) => {
    // ...
  }
);

useAsyncState

useAsyncState适用于处理异步操作,如 API 数据请求,并在数据返回前显示加载状态。

使用前:

type StateType = string[];
const state = ref<StateType>();
const isLoading = ref(false);
async function fetchData() {
  isLoading.value = true;
  try {
    const { data } = await request.get<StateType>('tags');
    state.value = data;
  } finally {
    isLoading.value = false;
  }
}

使用后:

type StateType = string[];
async function fetchData() {
  const { data } = await request.get<StateType>('tags');
  return data;
}
const { state, isLoading } = useAsyncState(fetchData, [] as StateType);

有时候我们可能只需要在执行异步任务时获取当前任务loading状态,可以基于useAsyncState做一下封装。

const useAsync = <Data>(
  promise: Promise<Data> | ((...args: any[]) => Promise<Data>),
  initialState?: Data
) => {
  return useAsyncState(promise, initialState, { immediate: false });
};

async function handleFormSubmit() {
  await request.post('form');
}
const { execute: formSubmitExec, isLoading: formSubmitLoading } = useAsync(handleFormSubmit);
formSubmitExec();

useMounted

useMounted检测组件挂载状态,常用于在组件和相关功能就绪后执行某些操作。

const isMounted = useMounted();
const funcReady = ref(false);

watch(
  () => [isMounted.value, funcReady.value],
  () => {
    if (isMounted.value && funcReady.value) {
      // ...
    }
  }
)

useBreakpoints

useBreakpoints基于断点的响应式设计,根据屏幕大小执行特定逻辑。

const { smallerOrEqual } = useBreakpoints({
  'sm': 640,
  'md': 1024,
  'lg': 1280,
  'xl': 1536,
  '2xl': 1920,
});
const isSmallScreen = smallerOrEqual('sm');

watch(
  () => isSmallScreen.value,
  (newVal) => {
    if (newVal) {
      // ...
    }
  }
)

useStepper

useStepper实现分步骤表单或向导。

const {
  goToPrevious,
  goToNext,
  isFirst,
  isLast,
  current,
} = useStepper([
   'step-1',
   'step-2',
   'step-3'
]);

function handleSubmit() {
  // ...
}

HTML 示例:

<div class="step-1" v-if="current === 'step-1'">
  step-1
</div>
<div class="step-1" v-if="current === 'step-2'">
  step-2
</div>
<div class="step-1" v-if="current === 'step-3'">
  step-3
</div>
<button v-if="!isFirst" @click="goToPrevious">上一步</button>
<button v-if="isLast" @click="handleSubmit">提交</button>
<button v-else @click="goToNext">下一步</button>

useFileDialog

useFileDialog简化文件选择对话框的使用,尤其是在处理文件输入样式重置时。

const { open, onChange } = useFileDialog({
  accept: '.jpeg,.jpg,.png',
  multiple: false,
  reset: true,
});

onChange(files => {
  // ...
})

HTML 示例:

<button @click="open()">选择文件</button>

useScrollLock

useScrollLock防止页面滚动,如在弹窗打开时。

const el = ref<HTMLElement | null>(null)
const isLocked = useScrollLock(el);

function onDialogOpen() {
  el.value = document.querySelector('.scroll-container');
  isLocked.value = true;
}

useScroll

useScroll监控元素的滚动事件,如实现滚动到底部加载更多内容.

const el = ref<HTMLElement | null>(null)
onMounted(() => {
  el.value = document.querySelector('.scroll-container');
});
const scrollState = useScroll(el, {
  offset: {
    bottom: 50,
  },
  onScroll() {
    if (scrollState.arrivedState.bottom) {
      // ...
    }
  }
});

useClipboard

useClipboard简化复制到剪切板的操作。

const { copy, copied } = useClipboard();

HTML 示例:

<span v-if="copied">Copied</span>
<button @click="copy()">Copy</button>

以上是 VueUse 常用 Hook 的一些应用实例,通过这些例子可以看出,VueUse 极大地简化了 Vue 3 中常见的功能实现,使得代码更加简洁,逻辑更清晰,从而提升开发效率。

Tags
Vue
VueUse