广州北大青鸟计算机职业培训学校
互联网技术培训、软件技术培训、大数据培训、云计算培训、数据分析培训信息网
当前位置:网站首页 > 软件专业 > 前端开发专业 > 正文

Web前端开发|怎么封装几个Vue3中很有用的组合式API?_惠州前端培训学校

作者:hz_admin01发布时间:2022-05-02分类:前端开发专业浏览:1010


导读:Web前端开发|怎么封装几个Vue3中很有用的组合式API?下面惠州北大青鸟老师给大家解答一下,希望对大家有帮助。

Web前端开发|怎么封装几个Vue3中很有用的组合式API?下面惠州北大青鸟老师给大家解答一下,希望对大家有帮助。

本文将介绍如何使用vue3来封装一些比较有用的组合api,主要包括背景、实现思路以及一些思考。

就我自己的感觉而言,Hook与CompositionAPI概念是很类似的,事实上在react大部分可用的Hook都可以使用Vue3再实现一遍。

为了拼写方便,下文内容均使用Hook代替CompositionAPI。

1、useRequest

背景

使用hook来封装一组数据的操作是很容易的,例如下面的useBook

functionuseApi(api){

constloading=ref(false)

constresult=ref(null)

consterror=ref(null)

constfetchResource=(params)=>{

loading.value=truereturnapi(params).then(data=>{

//按照约定,api返回的结果直接复制给resultresult.value=data}

).catch(e=>{error.value=e}

).finally(()=>{

loading.value=false

})}

return{

loading,

error,

result,

fetchResource

}

}

然后修改上面的useBook方法

functionfetchUserList(){

returnnewPromise((resolve)=>{

setTimeout(()=>{

constpayload={

code:200,data:[11,22,33],msg:'success'

}

resolve(payload)},1000)

})}

functionuseUser(){

const{

loading,

error,

result,

fetchResource,

}

=useApi((params)=>{

//封装请求返回值returnfetchUserList(params).then(res=>{

console.log(res)

if(res.code===200){

returnres.

data

}

return[]

})})//

...}

思考

处理网络请求是前端工作中十分常见的问题,处理上面列举到的加载、错误处理等,还可以包含去抖、节流、轮询等各种情况,还有离开页面时取消未完成的请求等,都是可以在useRequest中进一步封装的

useEventBus

EventBus在多个组件之间进行事件通知的场景下还是比较有用的,通过监听事件和触发事件,可以在订阅者和发布者之间解耦,实现一个常规的eventBus也比较简单。

//事件总线,全局单例constbus=newEventBus()exportdefaultfunctionuseEventBus(){

letinstance={

eventMap:newMap(),

//复用eventBus事件收集相关逻辑on:bus.on,once:bus.once,

//清空eventMapclear(){this.eventMap.forEach((list,key)=>{

list.forEach(cb=>{

bus.off(key,cb)

})})

eventMap.clear()

}}leteventMap=newMap()

//劫持两个监听方法,收集当前组件对应的事件conston=(key,cb)=>{

instance.on(key,cb)

bus.on(key,cb)

}

constonce=(key,cb)=>{

instance.once(key,cb)

bus.once(key,cb)}

//组件卸载时取消相关的事件onUnmounted(()=>{

instance.clear()

})return{

on,

once,

off:bus.off.bind(bus),

emit:bus.emit.bind(bus)

}}

这样,当组价卸载时也会通过instance.clear移除该组件注册的相关事件,比起手动在每个组件onUnmounted时手动取消要方便很多。

思考

这个思路可以运用在很多需要在组件卸载时执行清理操作的逻辑,比如:

dom事件注册addEventListener和removeEventListener。

计时器setTimeout和clearTimeout。

网络请求request和abort。

从这个封装也可以看见组合API一个非常明显的优势:尽可能地抽象公共逻辑,而无需关注每个组件具体的细节。

useModel

背景

当掌握了Hook(或者CompositionAPI)之后,感觉万物皆可hook,总是想把数据和操作这堆数据的方法封装在一起,比如下面的计数器。

import{

createStore

}

from'vuex'conststore=createStore(

{

state:{

count:0

},mutations:{

setCount(state,payload){

state.count=payload

}}})

然后重新实现useCounter。

constmap=newWeakMap()exportdefaultfunctionuseModel(hook){

if(!map.get(hook)){

letans=hook()map.set(hook,ans)

}returnmap.get(hook)

}

然后包装一下useCounter。

functionreducer(state,action){

//根据action进行处理//返回新的state

}constinitialState={

}

const{

state,dispatch

}=useReducer(reducer,initialState);

实现

借助于Vue的数据响应系统,我们甚至不需要实现任何发布和订阅逻辑。

importuseReducerfrom'./index'functionreducer(state,action){

switch(action.type){

case"reset":returninitialState;case"increment":return{

count:state.count+1

};

case"decrement":return{count:state.count-1};}}functionuseStore(){returnuseReducer(reducer,initialState);}

我们希望是维护一个全局的store,因此可以使用上面的useModel

<template><div><button@click="dispatch({

type:'decrement'

})">-</button><span>{

{

state.count

}}</span><button@click="dispatch({type:'increment'})">+</button></div></template><script>exportdefault{name:"useReducer",setup(){

const{

state,dispatch

}=useStore()return{state,dispatch

}}}

</script>

看起来跟我们上面useModel的例子并没有什么区别,主要是暴露了通用的dispatch方法,在reducer处维护状态变化的逻辑,而不是在每个useCounter中自己维护修改数据的逻辑。

思考

当然这个redux是非常简陋的,包括中间件、combineReducers、connect等方法均为实现,但也为我们展示了一个最基本的redux数据流转过程。

useDebounce与useThrottle

背景

前端很多业务场景下都需要处理节流或去抖的场景,节流函数和去抖函数本身没有减少事件的触发次数,而是控制事件处理函数的执行来减少实际逻辑处理过程,从而提高浏览器性能。

一个去抖的场景是:在搜索框中根据用户输入的文本搜索关联的内容并下拉展示,由于input是一个触发频率很高的事件,一般需要等到用户停止输出文本一段时间后才开始请求接口查询数据。

先来实现最原始的业务逻辑。

<template><div><inputtype="text"v-model="keyword"></div></template><script>import{

useAssociateSearch

}from"../useDebounce";exportdefault{

name:"useDebounce",setup(){

const{

keyword

}=useAssociateSearch()return{

keyword

}}}

</script>

与useApi同理,我们可以将这个debounce的逻辑抽象出来,,封装成一个通用的useDebounce。

实现useDebounce

貌似不需要我们再额外编写任何代码,直接将debounce方法重命名为useDebounce即可,为了凑字数,我们还是改装一下,同时增加cancel方法。

exportfunctionuseThrottle(cb,duration=100){

letstart=+newDate()returnfunction(){

letargs=argumentsletcontext=thisletnow=+newDate()if(now-start>=duration){

cb.apply(context,args)start=now

}}}

思考

从去抖/节流的形式可以看出,某些hook与我们之前的工具函数并没有十分明显的边界。是将所有代码统一hook化,还是保留原来引入工具函数的风格,这是一个需要思考和实践的问题。

总结

本文主要展示了几种Hook的封装思路和简单实现。

useRequest用于统一管理网络请求相关状态,而无需在每次网络请求中重复处理loading、error等逻辑。

useEventBus实现了在组件卸载时自动取消当前组件监听的事件,无需重复编写onUnmounted代码,这个思路也可以用于DOM事件、定时器、网络请求等注册和取消。

useModel实现了在多个组件共享同一个hook状态,展示了一种除vuex、provide/inject函数之外跨组件共享数据的方案。

useReducerreduxuseModel

useDebounce与useThrottle,实现了去抖和节流,并思考了hook化的代码风格与常规的util代码风格,以及是否有必要将所有的东西都hook化。

想了解更多关于前端的资讯,可以来惠州北大青鸟新方舟校区了解一下。

标签:惠州前端培训学校惠州前端基础惠州前端培训北大青鸟IT计算机学校北大青鸟IT软件学校前端北大青鸟IT学校惠州北大青鸟北大青鸟


前端开发专业排行
标签列表
网站分类
文章归档
最近发表