稍微聊聊vue3的函数式编程
发布于 3 年前 作者 banyungong 1271 次浏览 来自 问答
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

今天没有需求push,阅读了一下vue3的 function API相关的RFC,地址:https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md

最开始读的时候我是有点惊讶的,因为我一度认为这样的改动会对vue原有的编写习惯造成一定的冲击,但读到最后,我觉得这部分的改动是相当有趣并且相当值得去思考的。
因此在这里和大家稍微探讨一下函数式编程的事情吧(欢迎大家讨论,如有错误请指正,不喜勿喷哈)。

首先来看一下DEMO

<template>
  <div>
    <span>count is {{ count }}</span>
    <span>plusOne is {{ plusOne }}</span>
    <button @click="increment">count++</button>
  </div>
</template>

<script>
import { value, computed, watch, onMounted } from 'vue'

export default {
  setup() {
    // reactive state
    const count = value(0)
    // computed state
    const plusOne = computed(() => count.value + 1)
    // method
    const increment = () => { count.value++ }
    // watch
    watch(() => count.value * 2, val => {
      console.log(`count * 2 is ${val}`)
    })
    // lifecycle
    onMounted(() => {
      console.log(`mounted`)
    })
    // expose bindings on render context
    return {
      count,
      plusOne,
      increment
    }
  }
}
</script>

如果换成我们目前的写法,大概是这个样子:

<template>
    <div>
        <span>count is {{ count }}</span>
        <span>plusOne is {{ plusOne }}</span>
        <button @click="increment">count++</button>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                count: 0
            };
        },
        methods: {
            increment: function () {
                this.count++;
            }
        },
        computed: {
            plusOne: function () {
                return this.count + 1;
            }
        },
        watch: {
            count: function (val) {
                console.log(`count * 2 is ${val * 2}`)
            }
        },
        mounted() {
            console.log(`mounted`);
        }
    };
</script>

对比一下,我们不难发现:
vue2是将mounted,data,computed,watch之类的方法作为一个对象的属性进行导出。
vue3新增了一个名为setup的入口函数,value, computed, watch, onMounted等方法都需要从外部import。
刚看到这里的时候我认为这会给原有的vue编写习惯造成一定的冲击,虽然在RFC中提到了vue3会完全兼容vue2,但是从旧有的写法迁移到最新的写法终归还是需要一定的时间与精力的(毕竟经历过从swift2到swift3再到swift4的阵痛)

不过这样函数式的编程有什么好处呢?
我个人理解主要是:

函数式编程为组件的编写提供了更高的灵活度与可读性,并且更符合一个前端编写者的习惯(或者叫做“编程直觉”)。

在vue2中,watch、computed、data、method等API都是直接作为对象的属性,传给vue实例的。这意味着,我们开发者在开发时,脑中需要给这个对象的不同属性(data、method、mounted之类的)建立联系。但一旦代码规模变大,这种联系就非常吃力了,这集中表现在大型vue组件代码的可读性很低。我想,每个维护过1000+行vue组件的开发者都会有所体会

而在vue3中,我们可以像写一个方法一样去写这个组件的JS逻辑部分,使用import来按需引入。这样的好处显而易见,首先就是我们需要写的代码量少了,其次就是我们可以封装更多的子函数、引用更多的公共函数去维护我们的代码,第三就是代码的可读性变高了。(当然,我们的打包体积也会变小)

这里再给大家举个例子:
一个100行的Object(vue2式写法)和一个不到100行的function(vue3式写法),哪个维护性更好?哪个可读性更好?显而易见是后者。

另外,第一眼看到函数式编程的时候,我脑子中的第一个想法就是:“woc!这不就变成另一个react了嘛”。后来将RFC深入读了下,才发现并不是这样。

个人理解:vue和react最大的区别有两个,一是双向数据绑定 VS 单向数据流,二是模板语法 VS JSX。

虽然vue3在函数式编程方面,使其在一些API的使用、组件JS层的逻辑上更像react,但是其模板语法的根基是没有变的。就个人理解,模板语法相较于JSX,可能没有那么灵活,可能也会增加一定的代码量,但其最大的好处是可读性极强,并且实现了组件的“逻辑层”和“视图层”的解耦。而react则是另一个极端,使用JSX将逻辑和视图完全耦合在了一起,虽然赋予了极高的灵活性,但也带来了一定的问题——如果编写组件的时候比较放飞自我,那么后期阅读组件以及维护的成本会直线上升。

所以vue还是那个vue,react还是那个react。

以上

回到顶部