Composition API 与 Options API 的区别你了解吗?

537 阅读3分钟

使用 Vue2.x Options API(也称选项式API)开发的项目,普遍会存在以下的问题:

  • 随着组件功能的变大,代码的关联性会大大降低,组件的阅读和理解难度会增加;
  • 逻辑过多时使用 this 指向会出现问题,比如指向不明等;
  • 代码的复用性较差;
  • TypeScript的支持有限;
  • ......

Vue3.x Composition API(也称组合式API) 的出现,便能很好的解决以上问题。

Vue3.x 版本中,使用 Composition API 的主要原因是为了更好地解决组件复杂性和代码重用性的问题。 Composition API 将组件的逻辑按照功能进行划分,将相关逻辑放在一起,使得代码更加清晰和易于阅读和理解,维护成本也大大降低。

下面贴上官网给的一张图,这张图呢,是 Vue CLI GUI 中的文件浏览器组件,这个组件主要承担了以下几个逻辑关注点:

  • 追踪当前文件夹的状态,展示其内容
  • 处理文件夹的相关操作 (打开、关闭和刷新)
  • 支持创建新文件夹
  • 可以切换到只展示收藏的文件夹
  • 可以开启对隐藏文件夹的展示
  • 处理当前工作目录中的变更

这个组件最原始的版本是由 Options API 写的,图中相同颜色部分即为组件中代码有相同的逻辑功能。

image.png

我们可以看到,处理相同逻辑关注点的代码被强制拆分在了不同的选项中,位于文件的不同部分。在一个几百行的大组件中,要读懂代码中的一个逻辑关注点,需要在文件中反复上下滚动,这并不理想。另外,如果我们想要将一个逻辑关注点抽取重构到一个可复用的工具函数中,需要从文件的多个不同部分找到所需的正确片段。

如果用 Composition API 重构这个组件,将会变成下面这个样子:

image.png

我们可以看到,组件的代码是根据逻辑功能来组织的,一个功能所定义的所有 API 都会放在一起,我们也可以将每一个功能的代码移动到一个外部文件中,不再需要为了抽象而重新组织代码,大大降低了重构成本。

下面举个简单的例子,

  1. 如果使用 Options API 实现,代码将是下面这样子的:
export default {
    data() {
        return {
            isReachBottom: false,
            clientHeight: 0,
            scrollTop: 0,
            scrollHeight: 0
        }
    },
    methods: {
        scrollHandler() {
            this.clientHeight = document.documentElement.clientHeight;
            this.scrollTop = document.documentElement.scrollTop;
            this.scrollHeight = document.documentElement.scrollHeight;
            if(this.clientHeight + this.scrollTop >= this.scrollHeight) {
                this.isReachBottom = true;
            }
        }
    },
    mounted() {
        window.addEventListener("scroll", this.scrollHandler);
    },
    beforeDestroy() {
        window.removeEventListener("scroll", this.scrollHandler);
    }
}
  1. 而如果使用 Composition API 来实现,上面的代码将变成下面这样子:
<script setup>
    import { ref, onMounted, onUnmounted } from "vue";
    
    let isReachBottom = ref(false);
    let clientHeight = ref(0);
    let scrollTop = ref(0);
    let scrollHeight = ref(0);
    
    const scrollHandler = () => {
        clientHeight.value = document.documentElement.clientHeight;
        scrollTop.value = document.documentElement.scrollTop;
        scrollHeight.value = document.documentElement.scrollHeight;
        
        if(clientHeight.value + scrollTop.value >= scrollHeight.value) {
            isReachBottom.value = true;
        }
    }
    
    onMounted(() => {
        window.addEventListener("scroll", scrollHandler)
    })
    
    onUnmounted(() => {
        window.removeEventListener("scroll", scrollHandler)
    })
    
</script>

通过以上的对比,我们可以看到使用 Composition API,逻辑更加清晰了。

总结:

  1. 在代码逻辑组织和复用性方面,Composition API 是优于 Options API 的;
  2. Composition API 中没有对 this 的使用,减少了this指向不明的情况;
  3. Composition API tree-shaking 友好,代码也更容易压缩;
  4. Composition API 提供了很好的 TypeScript 集成。