前端项目数据层面的架构应该怎么搭建(以taro+react)为例

Posted 丰柏林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端项目数据层面的架构应该怎么搭建(以taro+react)为例相关的知识,希望对你有一定的参考价值。

前沿:实际上在我前8个月的开发生涯中,比较关注的视图的展示和功能的实现。虽然说我会从项目的结构上分为

[
	components
	config
	api
	assets
	src
		page
			tsx
			ts
			scss
	util
		request
		imageList
		store
		...
]

但是这种结构仅仅是划分了里面的资源,对文件本身做了一个归类。写到后面总感觉自己的代码里面不够优雅。
一个月前杰哥给我写了一个数据和视图分离、数据分层的demo。由于当时没看明白,总觉得像java里面的抽象类,抽象接口,抽象方法之类的,然后去具体的地方实现它。

今天得空看一看,数据层的处理逻辑大概是

[
	dataSource
	infrastructure
	interfaces

	//这里同一层舍弃掉components
	//写到每个page指定页面的文件夹下
	pages
		index
			components
				Carousel
					CarouseltemProps.ts
					Carousel.tsx
					CarouselProps.ts
				Index
					IndexProps.ts
					index.tsx
			IndexViewAssembler.ts
			index.ts
			index.scss
			index.tsx
			IndexContainer.tsx
]

这里的重点在:

	dataSource
	infrastructure
	interfaces

dataSource—数据源,听起来有点像数据管理中心的意思,每个页面所需要的数据都从这里拿。

import indexDto from "../interfaces/facade/dto/indexDto";

export default interface IndexDataSource {
  loadIndex(): Promise<IndexDTO>;
}

emmmmm…
大概是一个抽象方法吧(如有错误请在评论区指正)

infrastructure—基础设置,这个听起来我有点懵,但是先看里面的结构

	local
		IndexDataSourceLoacl.ts

再看内容
IndexDataSourceLoacl.ts

import IndexDataSource from "../../datasource/IndexDataSource";
import IndexDTO from "../../interfaces/facade/dto/IndexeDTO";

export default class IndexDataSourceLocal implements IndexDataSource {

  async loadIndex(): Promise<IndexDTO> {
    const index: IndexDTO = {
      carousels: [
        {
          url: "",
          pictureURL: ""
        }
      ]
    } as IndexDTO;
    return new Promise<IndexDTO>((resolve, _) => {
      resolve(index);
    });
  }
}

emmmm…
有点明白大概是个什么意思了,大概是在这边处理本地的数据然后return出去当做一个props用,作为本地的数据所以放在local里面。
当然,针对于HTTP的建立一个HTTP文件夹写在里面就好了(我是这么理解的–有误请批评指正)

接下来是interfaces–(面向接口编程?我理解的大概这样)
然后里面结构大概是这个样子

	facade //门面模式,外观模式
		dto //data translate project
			CarouselDTO.ts //这里是一个抽象类,里面有确定的类型,为其他类服务
			IndexDTO.ts //这里面调用自定义类型CarouselDTO
		inner
			IndexServiceFacadelmpl.ts //实现下面的抽象方法
		IndexServiceFacade.ts //抽象方法

CarouselDTO.ts

export default class CarouselDTO {
  url: string;
  pictureURL: string;
}

IndexDTO.ts

import CarouselDTO from "./CarouselDTO";

export default class IndexDTO {
  carousels: CarouselDTO[];
  //这里不仅仅只能定义这一个自定义类型,也可以同时引用多个或者被外部引用
}

IndexServiceFacadelmpl.ts

import IndexServiceFacade from "../IndexServiceFacade";
import IndexDTO from "../dto/IndexDTO";
import IndexDataSource from "../../../datasource/IndexDataSource";

export default class IndexServiceFacadeImpl implements IndexServiceFacade {

  private indexDataSource: IndexDataSource;

  public constructor(indexDataSource: IndexDataSource) {
    this.indexDataSource = indexDataSource;
  }

  async fetchIndex(): Promise<IndexDTO> {
    return this.indexDataSource.loadIndex();
  }
}

IndexServiceFacade.ts

import IndexDTO from "./dto/IndexDTO";

export default interface IndexServiceFacade {
  fetchIndex(): Promise<IndexDTO>;
}

我理解的意思是先抽象出来一个要实现的数据类型,这个抽象出来的类型里面的类型是我们常用的数据类型。我们自定义的数据类型是为了减少代码耦合。
然后在外部抽象出来一个接口,接口里面是一个抽象的方法,返回的是我们刚刚自定义类型的数据。
然后在inner的IndexServiceFacadelmpl.ts里面我们去实例化这个抽象方法。

数据架构是搭建起来了,我们怎么去用呢?

让我们回到我们经常写代码的pages页面

看看pages的结构(之前上面写过,我懒得翻上去看直接贴在这)

pages
		index
			components
				Carousel
					CarouseltemProps.ts //定义自定义类型
					Carousel.tsx //banner视图,视图组件
					CarouselProps.ts //抽象自定义类型
				Index
					IndexProps.ts //抽象自定义类型
					index.tsx //视图组件
			IndexViewAssembler.ts //视图装配
			index.config.ts //页头配置
			index.scss
			index.tsx //展示组件
			IndexContainer.tsx //容器组件

重点在 IndexContainer.tsx 容器组件的数据处理
讲起来我自己都有点模糊,自己理解吧,我也还没理解够(手动狗头)

import React, {useEffect, useState} from "react";
import Index from "./components/Index";
import IndexServiceFacade from "../../interfaces/facade/IndexServiceFacade";
import IndexServiceFacadeImpl from "../../interfaces/facade/inner/IndexServiceFacadeImpl";
import IndexDataSourceLocal from "../../infrastructure/local/IndexDataSourceLocal";
import IndexDTO from "../../interfaces/facade/dto/IndexDTO";
import IndexViewAssembler from "./IndexViewAssembler";
import IndexProps from "./components/Index/IndexProps";

const IndexContainer: React.FC = () => {
  const homeServiceFacade: IndexServiceFacade = new IndexServiceFacadeImpl(new IndexDataSourceLocal());
  const [index, setIndex] = useState<IndexProps>({} as IndexProps);

  useEffect(() => () => {
    const fetchIndex = async () => {
      const indexDTO: IndexDTO = await indexServiceFacade.fetchIndex();
      const assembler: IndexViewAssembler = new IndexViewAssembler();
      const indexProps = assembler.toProps(indexDTO);
      setIndex(indexProps);
    }
    fetchIndex();
  }, []);

  return (
    <Index {...index} />
  );
};

export default IndexContainer;

index.tsx展示组件

import React from 'react';
import IndexContainer from "./IndexContainer";

const Index: React.FC = () => (<IndexContainer />);

export default Index;

以上是关于前端项目数据层面的架构应该怎么搭建(以taro+react)为例的主要内容,如果未能解决你的问题,请参考以下文章

前端工程化-基于Taro的Web端Monorepo架构改造

前端工程化-基于Taro的Web端Monorepo架构改造

前端工程化-基于Taro的Web端Monorepo架构改造

前端工程化-基于Taro的Web端Monorepo架构改造

01 Taro_Mall 开源多端小程序框架设计

前端架构之工作流