关键词:demo、函数式组件
入坑Vue大半年,正好赶上Vue 3.0的发布提上日程,体验版的vue-function-api也放了出来。虽然Vue 2.x还没完全搞明白,但还是想紧跟时代潮流,所以还是想先体验一下。
本来以为自己对Vue还算熟悉,但是真写起文章来,竟然不知从何说起。想了半天,这次主要是想说说生命周期、watcher、组件间传值,和Vuex、router在新API下的变化,谈谈使用感想,和一些使用时的“坑点”,烦请各位斧正。
其实大部分的坑都是因为文档没看仔细……差点就去开issue丢人了(笑)。不过后来还真的发现了一个问题,开了个issue,得到的回复是还没做。
2019.8.6 官方已经加上了onErrorCaptured()这个钩子。
阅读本文前建议先通读vue-function-api的文档,和那篇由Evan You亲自发布的最重要的RFC。此外最好对Vue-router、Vuex和2.6之后的新版本有所了解。
在开始之前,我想先说说个人感想。Vue 3.0的种种好处,这半年来已经被大肆宣扬过,我就不再重复了。底层的TypeScript让类型检查和代码提示真正得到了支持,从工程角度来说,对于协作成本的降低也是一个飞跃式的提升,可以说是“注入灵魂”了。这里说说我个人觉得的最大的亮点:函数式组件。也许用过React的人会有这个感觉,有些简单的组件可以直接抽出一个函数,就像在正常的编程语言中写函数一样,客观上直接提高了开发者的抽象和复用意识,因为这种通过函数来进行逻辑上的提取和复用是很自然的。
而在Vue 2.x里就稍微差点意思,还得专门搞个template出来,哪怕是后续支持的functional
。而且实话说Vue的逻辑是搅在一起的,比如我去后端拿数据,这个过程肯定会被放到data()
和mounted()
里;如果是基于URL去拿数据,还得加上watch()
或者activated()
来监听路由的变化;如果还需要用多个数据源拿到的数据渲染,比如父组件传来的值,就还需要props
。如果代码稍微复杂一点,或者没有下意识地去抽取组件,很容易把逻辑搅在一起。虽然说React滥用setState之类的也是这个问题吧,但因为之前说的,在React里,抽取和复用是一件很自然的事,能一定程度上避免这个问题。
这次的函数式API让我直接看到了Vue函数化的机会。看看尤大写的例子:
import { onMounted, onUnmounted, value } from 'vue-function-api'
export function useMouse () {
const x = value(0)
const y = value(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
看到了吗?这就是函数式组件。这里的组件指的不是视图层面上的组件,而是逻辑组件。这个的写法,类似于面向对象中分配职责时的行为类,让职责更加清晰,内聚也更高,也方便逻辑的复用(可以代替mixin)。毕竟Vue 3.0的设计初衷就是为了更好地组织逻辑。美中不足的,可能还是那种很简单的组件,仍然需要一个专门的SFC来组织视图……不过也许可以用render来解决这个问题。
虽然我还是对面条码心怀担忧,因为这样写会让setup()
变得很长,但是就目前来看,是利大于弊的,而且因为由一个个命名函数组合起来,可读性也还好,至少也是个过程内聚。看到这个之后,更坚定了我的信心。不过,我目前的问题是,上手是不是更难了?
(PS:写完之后,发现我和尤大的观点重合了……我之前真没看他写的。是巧合吗?)
下面进入正题。官方对vue-function-api的介绍是什么?
面向未来编程(Future-Oriented Programming),
vue-function-api
提供 Vue3 中的组件逻辑复用机制帮助开发者开发下一代 vue 应用程序,允许开发者利用 Vue3 的响应性 API 建设未来 Vue 生态。
所谓的FOP,任重而道远啊。插一句,完善的中文文档也是我更喜欢Vue的原因之一。
为了尝试这个,我决定做一个简单(也很老土)的todo-list。至于功能么,增加、删除、查询条目。为什么不做查询?因为懒。因为只是尝试,所以交互体验就不怎么考虑了。同时,为了和生产环境尽量结合,用了“牛刀”Vuex。此外,为了体现新的API state
(也许2.6的Vue.Observable
也算新API?),顺便弄了一个简单的总线bus;computed计算属性真是好东西。
为了体现逻辑,没有加CSS,所以效果图就不放出来了,辣眼睛。为了体现出自己没有写CSS,我特意删掉了SFC里所有的style标签。对心理承受能力有自信者可以自行查看(笑)。
项目demo的地址在这里,欢迎批评指正:
TypeScript版:https://github.com/HermitSun/vue3-taste-ts
JavaScript版:https://github.com/HermitSun/vue3-taste-js
另外,由于Vue 3.0采用了函数式的API,现有的生态圈恐怕会地震吧……Vuex和router的API都得改。目前使用起来还是有点不顺手。本来我想试着自己做一个,不过已经有人做了,就兴致缺缺了。不过这事还是挺有意思的,说不定会被官方采用呢?不过我想他们内部早就已经开始操作了吧……
Vue 3.0 function-based API尝鲜(二):配置与启动
Vue 3.0 function-based API尝鲜(三):包装对象
Vue 3.0 function-based API尝鲜(四):值得一提的watch
Vue 3.0 function-based API尝鲜(五):生命周期
Vue 3.0 function-based API尝鲜(六):组件间通信
Vue 3.0 function-based API尝鲜(七):This与Refs