为什么软件开发过程中可以用result api,为什么2022年前端不能做一个业务进一步复用呢?

407 阅读4分钟

在08年以前谷歌还没推出chromenode.js的时候,还有微软没有推出XHR概念的时候。web开发还是服务器渲染的TABLE布局显示。

在08后之后谷歌发布了chrome和node.js还有安卓手机系统之后。客户端的设备就越来越多了。如果还是采取第一种的方式,系统的复用性就大大减半。这个时候就有人提出了result api的方案解决数据复用性。也就有了如今的开发模式。

大多数的阅读者都在反应,能不能给dome。我分享的文章多数是思路问题,实现的过程有很多方式...程序员应该具备的能力是思路,而不是所谓的“精通原理”。懂原理虽然是好,但是你看源码的实际意义也不只不过是为了看作者的思路。我见过很多背原理很精通的,但缺没有想到把这些思路用在什么业务场景进行设计的人实在太多。这一类定义为码农还是搬运工好呢?

image.png

这是在js还没成为流行的趋势的时候形成的一种模式。但是如今已经是2020年了,几乎一个端JS都能做完的事情。为了统一,国内的方案的都是基于一门自己的核心语言做完基础栈,然后通过这个语言进行编译成对应的开发平台进行代码复用。以React Native,Taro为例子。

image.png

现在的解决方案都是这样。那么到了使用者是如何去做的呢?

image.png

由于前端是一个奇葩的世界,我不知道这些UI框架还能坚持几年。从历史来看Jquery在06年发布,08发行了angularjs,10年React,11年Angular2。这时间线来看,jQuery的霸主地位也维持了4年左右吧。而且随着Web Components不断完善,你很难确保未来工程化,未来再打包上做优化,可能会有一批新的非编译Web Components的兴起,比如polymer,svelte框架。又比如为前端的即将到来一般的企业应该如何快速迁移呢?如果按照上图的模块,和重构是没有什么区别了。

这个时候我就在想一个问题,能不能再抽象一层,提出这个概念的人是字节跳动的ArcoDesign,但是在我半个月的阅读源码思路的时候,发现并没有实现handle的抽象。我来说说我的思路吧,这模式只是适合中小产业做迁移。比如React迁移Vue。因为一般的企业更不没有资金去做类似Flutter,Taro等编译型框架!!!

image.png

动手就干。

先看看模块路径

image.png

React 先用回调实现简单的思路

//App.tsx
function App() {

    const [data, setData] = useState(0);
    
    const clickButton = useCallback(() => {
        getTest(data, (res) => {
            setData(res)
        })
    }, [data])

    return (
        <>
            <button className="bg-red-400 border-red-400 rounded-md p-2 text-white shadow-md m-8"
                onClick={clickButton}
            >
                Get Test {data}
            </button>
        </>
    );
}

export default App;
// handle.js
import { TestModel } from "../entity";
import { TestService } from "../service";

export function getTest(data: any, setData: Function) {
    TestService<TestModel>().then(test => {
        console.log(test.version)
        setData(data + 1)
    })
}
// server.js
import { TestMock } from "../mock"

export function TestService<T>(): Promise<T> {
    return new Promise((resolve, reject) => {
        const mock = TestMock;
        resolve(mock)
    })
}

image.png

VUE实现

我们再看看 VUE能不能这么实现,vue已经4年没怎么用了,我直接用Vue3的hooks版本吧。(其实我更想使用NG来实现...不过还好Vue的ts,去掉babel和ng类似。)

//代码有点长。。。
<template>
  <div class="hello">
    <button
      className="bg-red-400 border-red-400 rounded-md p-2 text-white shadow-md m-8"
      @click="clickButton"
    >
      Get Test {{ data }}
    </button>
  </div>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { getTest } from "../handles/index";

@Options({
  props: {
    msg: String,
  },
  data() {
    return {
      data: 0,
    };
  },
  methods: {
    clickButton() {
      getTest(this.data, (res: number) => {
        this.data = res;
      });
    },
  },
})
export default class HelloWorld extends Vue {
  msg!: string;
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

image.png

为了更好的扩展,当然不能使用回调进行操作啦!。

一般的前端会使用Promise进行操作。当然不是使用Promise,如果你是一个追求高可用的程序员,这个时候会考虑的肯定是Redux,Mobx来进行管理。但是这些都需要有一个store进行操作。入口注入sotre。我就不太喜欢了。

我这里使用rxjs和单列进行管理,我不太喜欢约束开发。

修个后React

function App() {

    const [data, setData] = useState(0);

    useEffect(() => {
        TestSubjectFactory.getInstace().$name.asObservable().subscribe(res => {
            setData(res)
        })
    }, [])

    const clickButton = useCallback(() => {
        getTest(data)
    }, [data])

    return (
        <>
            <button className="bg-red-400 border-red-400 rounded-md p-2 text-white shadow-md m-8"
                onClick={clickButton}
            >
                Get Test {data}
            </button>
        </>
    );
}

export default App;

修改后的 VUE

<template>
  <div class="hello">
    <button
      className="bg-red-400 border-red-400 rounded-md p-2 text-white shadow-md m-8"
      @click="clickButton"
    >
      Get Test {{ data }}
    </button>
  </div>
</template>

<script lang="ts">
import { Options, Vue } from "vue-class-component";
import { getTest } from "../handles/index";
import { TestSubjectFactory } from "../service/index";

@Options({
  props: {
    msg: String,
  },
  data() {
    return {
      data: 0,
    };
  },
  methods: {
    clickButton() {
      getTest(this.data);
    },
  },
  created() {
    TestSubjectFactory.getInstace()
      .$name.asObservable()
      .subscribe((res) => {
        this.data = res;
      });
  },
})
export default class HelloWorld extends Vue {
  msg!: string;
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

当然这只是设计上的参考,但是基于这个思路你又会想到做什么事情呢?关注我让你学会更多的维护性思路。

至于代码基础那些资源,你们还是看其他文章喷我的那些博主吧,他们分享的内容居多是教学上的基础资源。