对于 Composition API 的一些理解

Composition API 是 vue3.0 新推出的一种逻辑复用方案,官网是这么说的

用组件的选项 (data、computed、methods、watch) 组织逻辑在大多数情况下都有效。然而,当我们的组件变得更大时,逻辑关注点的列表也会增长。这可能会导致组件难以阅读和理解,尤其是对于那些一开始就没有编写这些组件的人来说。这种碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。如果我们能够将与同一个逻辑关注点相关的代码配置在一起会更好。而这正是 Composition API 使我们能够做到的。

想要充分理解这段话,我们首先要知道 vue 模板语法存在的问题
先写个简单的 demo
// simple.vue
export default {
    props: ['id'],
    data() {
        return {
            list: []
        };
    },
    created() {
        this.getList(this.id);
    },
    watch: {
        id(newId) {
            this.getList(newId);
        }
    },
    methods: {
        getList(id) {
            this.$api.post('url', id).then(res => {
                this.list = res.list;
            });
        }
    }
};
可以看出,创建组件时接受一个 id 去请求 list 数据,当 id 变更时重新发起请求。很常见的业务逻辑,但这种写法导致的问题已经出现,我们想要将此逻辑优雅地进行复用已不可能,因为此逻辑已经和组件本身的选项耦合在了一起。
 
在此之前,vue 的解决方案是使用 mixins,我们可以将此逻辑抽象为一个对象去混入到别的组件之中,就像这样
// complex.vue
let simple = {......};
export default {
    mixins: [simple]
};
似乎还是很简洁不是吗,可是一个组件可能存在着很多逻辑复用的场景,那么你的组件就会变成这样
// complex.vue
import simple from './simple.js';
import simple2 from './simple2.js';
import simple3 from './simple3.js';
export default {
    mixins: [simple, simple2, simple3]
};
mixins 可以很好地保障逻辑的复用,不会写任何多余重复的代码,但其弊端是会导致数据的流向变得难以追踪,通俗地讲就是加大了你对于此种代码的理解难度。

作为一名维护者,第一次接触到 complex 这个组件时,你不仅要把 complex 的代码阅读一遍,还要把 simple 、simple2、simple3 的代码通读一遍,不然一不小心,就会触及到以往的功能,而原因仅仅是你定义了一个重复名称的变量 —— minxins 在合并时发生冲突,是以组件自身的数据优先的,而这完全属于意料外的问题。我只想加个简单的小功能,我并不关注这个组件本身复用了多少别的业务逻辑。

到这里,再回过头看看开头给出的官网的话,是不是有了更深的理解呢。
 
而以我对于 vue 的理解,作者将 html、js、css 融入到一个组件之中,固定地采用一系列选项,就是想为开发者屏蔽掉很多考虑和负担,这也大大加强了我们开发及维护时的便利性,而 mixins 很明显与这一理念冲突,这也就能理解作者当初试图弃用模板语法时的心态了,我们现在有了更好的解决方案 —— Composition API。

还是这个 demo,我们用新的语法去改写
// simple.js
import { ref, watchEffect } from 'vue';
export default function simple(id) {
    let list = ref([]);
    const getList = id => {
        this.$api.post('url', id).then(res => {
            list.value = res.list;
        });
    };
    watchEffect(() => {
        getList(id.value);
    });
    return { list };
}
此时 simple 已经是一个函数了,所以我们在 complex 组件中应该这样引入
// complex.vue
import simple from './simple.js';
export default {
    props: ['id'],
    setup(props) {
        let { list } = simple(props.id);
        return { list };
    }
};
基于 vue3.0 给出的新语法,list 已通过 ref 变成响应式的数据,而 watchEffect 又帮助我们观测传入的 props.id。当 props 传入的 id 发生变动时,则会触发 simple 里的 getList 方法,产生 list 数据的更新, 再由 complex 组件重新渲染页面,十分清晰明了,也正如官网所说,逻辑关注点相同的代码将很容易配置在一起。

而且有再多的逻辑复用也不怕,因为我们此时已将 mixins 语法 以函数的形式取代掉了,变量名称冲突的问题将迎刃而解,也顺带解决了 mixins 导致的数据流向不清晰的问题,组件的数据来源,一目了然。
// complex.vue
import simple from './simple.js';
import simple2 from './simple2.js';
import simple3 from './simple3.js';
export default {
    setup(props) {
        let { list } = simple(props);
        let { list2 } = simple2(props);
        let { list3 } = simple3(props);
        return { list, list2, list3 };
    }
};
以上就是本人对于 Composition API 的一些理解,若有新的心得体会,我会继续补充。
 
原文地址:https://www.cnblogs.com/chh1995/p/13715733.html