背景
众所周知 Vue3 的时代已来临, Vue3中推荐使用组合式Api, 也就是由之前的类编程转换为函数式编程,逻辑转移到setup语法糖中,由setup作为组合式API的入口点。作为函数式编程Hooks是必不可少的,因为笔者之前一直使用React,在React中 AHooks 是封装的较为全面且实用的hooks库,但是到了Vue3中一直没有找到合适的库,后来决定自己写一套Hooks库,也就是有了 V3Hooks 这个库, 接下来会拿出几个Hook来做介绍,如果这对你有帮助的话,可以给一个Star支持。
使用
接下来我们看几个常用的Hook使用
useRequest
useRequest是用于管理异步请求的Hook,针对于需求中常见的请求发起方式进行封装,加速你的日常开发,他具有以下功能:
- 自动请求/手动请求
- SWR(stale-while-revalidate)
- 缓存/预加载
- 屏幕聚焦重新请求
- 轮询
- 防抖
- 节流
- 依赖请求
- 突变
- loading delay
请求发起方式
如果service是object,useRequest会使用 Fetch 来发送网络请求
import { useRequest } from 'v3hooks';
const { data } = useRequest(
{
url: 'http://xxx.xx.com/api/userInfo',
method: 'POST'
}
);
如果service是async函数,useRequest会调用此函数来发送网络请求
import { useRequest } from 'v3hooks';
const { data } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
);
基础请求
import { useRequest } from 'v3hooks';
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
);
watchEffect(()=>{
console.log( data?.value );
})
在这个例子中, useRequest 接收了一个异步函数 ,在组件初次加载时, 自动触发该函数执行。同时 useRequest 会自动管理异步请求的 loading , data 状态。你可以通过data和loading来实现你的需求
因为返回的data为响应式,js中获取data.value需要在watchEffect中使用,而在template中使用是不需要的。
手动触发
const { data, run, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
manual: true
}
);
通过设置 options.manual = true , 则需要手动调用 run 时才会触发执行异步函数。
轮询
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
pollingInterval: 1000
}
);
通过设置 options.pollingInterval ,进入轮询模式,定时触发函数执行。
依赖请求
import { onMounted, ref } from 'vue'
const isReady = ref(false);
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
ready: isReady
}
);
onMounted(() => {
isReady.value = true;
})
只有当 options.ready 变为 true 时, 才会发起请求,基于该特性可以实现串行请求,依赖请求等。
防抖
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
debounceInterval: 1000
}
);
通过设置 options.debounceInterval ,则进入防抖模式。此时如果频繁触发 run ,则会以防抖策略进行请求。
节流
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
throttleInterval: 1000
}
);
通过设置 options.throttleInterval ,则进入节流模式。此时如果频繁触发 run ,则会以节流策略进行请求。
缓存 & SWR
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
caccacheKey: 'mock1'
}
);
如果设置了 options.cacheKey , useRequest 会将当前请求结束数据缓存起来。下次组件初始化时,如果有缓存数据,我们会优先返回缓存数据,然后在背后发送新请求,也就是 SWR 的能力。你可以通过 cacheTime 设置缓存数据回收时间,也可以通过 staleTime 设置数据保持新鲜时间。
预加载
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
caccacheKey: 'mock1'
}
);
同一个 cacheKey 的请求,是全局共享的,也就是你可以提前请求数据。后续请求会提前返回之前预加载的数据,利用该特性,可以很方便的实现预加载。
屏幕聚焦重新请求
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
refreshOnWindowFocus: true,
focusTimespan: 2000
}
);
如果你设置了 options.refreshOnWindowFocus = true ,则在浏览器窗口 refocus 和 revisible 时,会重新发起请求。你可以通过设置 options.focusTimespan 来设置请求间隔,默认无 。
突变
const { data, mutate } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
}
);
<button type="button" @click={() => mutate({code:'1',msg:'test'})}>
突变测试
</button>
你可以通过 mutate ,直接修改 data.
Loading Delay
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
loadingDelay: 300
}
);
通过设置 options.loadingDelay ,可以延迟 loading 变成 true 的时间,有效防止闪烁。
refreshDeps
开发中会经常碰到这个需求,当某些 state 变化时,我们需要重新执行异步请求,使用useRequest将很方便的实现此功能。
import { onMounted, ref } from 'vue'
const random = ref(1);
const { data, loading } = useRequest(
() => {
return axios.post(
`http://xxx.xx.com/api/userInfo`
);
},
{
refreshDeps: [ random ]
}
);
setInterval(()=>{
random.value = Math.random()
},1000)
当例子中 random 发生变化时,会重新执行 service。
useVirtualList
长列表虚拟化列表的 Hook,用于解决展示海量数据渲染时首屏渲染缓慢和滚动卡顿问题。
基础使用
<template>
<div class="hello">
<button
style="margin-top: 30px"
type="button"
@click="handleVirtualScrollTo"
>
scroll to
</button>
<div
:ref="containerProps.ref"
@scroll="containerProps.onScroll"
style="height: 300px; overflow: auto;border: 1px solid #cccccc"
>
<div :style="wrapperStyle">
<div
v-for="active in list"
:key="active"
style="
height: 59px;
border-bottom: 1px solid #cccccc;
background-color: white;
"
>
{{ active }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { useVirtualList } from "v3hooks";
export default {
setup() {
const { list, wrapperStyle, containerProps, scrollTo } = useVirtualList(
Array.from(Array(99999).keys()),
{
itemHeight: 60,
overscan: 10,
}
);
const handleVirtualScrollTo = () => {
scrollTo(22);
};
return {
list,
wrapperStyle,
containerProps,
handleVirtualScrollTo,
};
},
};
</script>
useVirtualList接受一个数组,导出一个虚拟化的list以元素配置,具体配置看Api
useTextSelection
实时获取用户当前选取的文本内容及位置的hook。
useTextSelection接受一个HTMLElement, 导出已选择的文本和位置信息。
基础使用
<template>
<div style="text-align: center">
<p ref="p"> 可选择区域: 123111111111111aaaaaaaaaaabbbbbbbbbbb eeeeeeeeeeeeeeee</p>
<p>已选择的值:{{ text }}</p>
<p>位置信息:rect: {{ rect }}</p>
<p>left: {{ rect.left }}</p>
</div>
</template>
<script lang="ts">
import { useTextSelection } from "v3hooks";
export default {
setup() {
const { text, rect } = useTextSelection();
return {
text,
rect
};
},
};
</script>
没有传值默认为document, 页面上可选择的文本都会被计算
监听特定区域文本选择
<template>
<div style="text-align: center">
<p ref="p"> 可选择区域: 123111111111111aaaaaaaaaaabbbbbbbbbbb eeeeeeeeeeeeeeee</p>
<p>已选择的值:{{ text }}</p>
<p>位置信息:rect: {{ rect }}</p>
<p>left: {{ rect.left }}</p>
</div>
</template>
<script lang="ts">
import { ref } from 'vue';
import { useTextSelection } from "v3hooks";
export default {
setup() {
const p = ref();
const { text, rect } = useTextSelection(p);
return {
text,
p,
rect
};
},
};
</script>
传值为Ref的P标签,只会监听特定区域。
useQRCode
一个用来生成二维码的 Hook 。
基础使用
<template>
<div class="hello">
<div> 二维码:</div>
<img :src="state" alt="">
</div>
</template>
<script lang="ts">
import { ref } from 'vue';
import { useQRCode } from "../../../dist/index.js";
const logo = require('../../assets/logo.png')
export default {
setup() {
const text = ref<string>('https://www.baidu.com/')
const state = useQRCode(text,{
logo: logo.default,
colorDark: '#000000'
});
setTimeout(()=>{
text.value = 'https://www.acfun.cn/'
},2000)
return {
state
};
},
};
</script>
usQRCide可以接受一个静态url,也可以是一个被Ref包裹的url,当Ref值发生变化时,二维码会跟随内容进行变化。
useNetwork
一个用来获取当前网络状态的 Hook 。
基础使用
<template>
<div class="hello" style="display:flex;align-items:flex-start;">
<p> 网络状态:{{ state }}</p>
</div>
</template>
<script lang="ts">
import { useNetwork } from "v3hooks";
export default {
setup() {
// 获取query中的a
const state = useNetwork();
// useVirtualList测试
return {
state
};
},
};
</script>
useNetwork返回网络状态信息
结尾
以上拿出了几个Hooks来给大家演示,V3Hooks中还有很多实用Hooks来供大家使用,具体使用可以查看文档,附上 GitHub链接,希望这对你有用。