吸取其他框架的优点改造前端架构(Decorator装饰器vue中使用,横向切面实现防抖节流,缓存等功能)

203 阅读2分钟

前端现在扮演的角色越来越重,从Java手中夺取一部分,现在有横向进军桌面的移动端,所谓是框架百家争鸣,但最终还是JS,今天就看看vue框架的嫁衣。

本文涉及到装饰器的使用,横向切面在轻松优雅的实现各种功能包括,防抖节流,数据缓存,本地缓存,loading等功能,个人认为以后趋势。也涉及到fetch的封装,具体细节,下节细说。

api的装饰

Java有DDD开发模式,相对比以前的mvc更加注重了模块化,功能化,前端的话没必要这么复杂,但是还是要做些嫁衣和模块化开发:

@Controller({ path: "/param/api/v1/publ", token: "no" })
export class ParamApi {
  @Get("/enums/{enumTypeId}")
  public async paramApi(params: MyRequest) {
    return request(params)
  }
  @Put("/camp/ballot/application/{applicationId}/sequence")
  public async changeChoiceSeqApi(params: MyRequest) {
    return request(params)
  }
  @Delete("/balloting/application/{applicationId}/choices/{choiceId}")
  public async deleteChoiceApi(params: MyRequest) {
    return request(params)
  }
  @Post({ path: "/publ/registerWithEmail", timeout: 60000 })
  public async registerApi(params: MyRequest) {
    return request(params)
  }

这样的写法条例清晰,每个接口和Java对应,每个接口做什么事情什么意思清清楚楚(post,get,delete),如果Java有修改,这边一一对应不会乱。接下来就是request:

const server = fetch.create({
  baseURL: "/rest",
  headers: {
    channel: "**"
  }
})

server.interceptors.request.use(config => {
  const token = getKeyValue({ key: "accessToken" })
  if (token && config.token != "no") {
    config.headers["Authorization"] = token
  }
  config.headers["Accept-Language"] = getKeyValue({ key: "language" })
  return config
})

server.interceptors.response.use(undefined, err => {
  const config = err.config
  if (!config || !config.retry) return Promise.reject(err)
  config._retryCount = config._retryCount || 0
  if (config._retryCount >= config.retry) return Promise.reject(err)
  config._retryCount += 1
  return server.request(config)
})

这里采用了fetch来访问和操纵 HTTP,这里可以添加headers,设置接口重试,可以处理无感知token refresh,可以解析返回值然后做特殊处理等,每块都是各自的功能。到这api层差不多了。

store层装饰

store层做中转,相当于Java的service层,做些功能性等操作:

@Module({ dynamic: true, store, name: "common", namespaced: true })
class Common extends VuexModule implements CommonState {
  public file = ""
  public sliderCache: any = {
    facility: {},
    programme: {}
  }
  public routeCache: unknown = []

  @Action
  @Loading
  @Throttle(100)
  @Debounce
  @CacheSession({ key: "#facility.waterReviewData", value: "waterReviewData" })
  async upload(param: MyRequest) {
    return await fileApi.uploadApi(param)
  }
  @Mutation
  @CacheImmediately({ key: "#common.routeCache", value: "routeCache" })
  public SET_ROUTE_CACHE(data: any) {
    this.routeCache = data
  }

这里的可以做好多事情,防抖节流,是否需要loading,是否需要缓存到localStorage,是否需要缓存sessionStorage,只需要加一个注解就可以,无入侵式,需要什么加什么,清楚明了。

业务层

  getCategoryEnums(): void {
    ParamModule.getParam({
      path: { enumTypeId: "pgm_application_category" }
    })
      .then(checkCode)
      .then((res: any) => {
        this.categoryList = res
        this.getShoppingCartCategory()
      })
  }

业务层也很清晰,是路径传参还是问号传参一看就知道。

这些是总结其他框架的优化,还有很多,这一期先到这,只是单纯分享,认不认同无所谓