引入
打开 Vue3 的官方文档,它首先会告诉你,Vue 的组件可以按两种不同的风格书写:选项式 API 和组合式
API。文档为我们提供一系列两种风格的代码参考,供我们按照偏好进行选择。
实际上,Vue3组件可不止两种写法,而是多达十几种!然而,不管是什么写法,它们都是基于同一个底层系统实现的,概念之间也是彼此相通的,只是使用的接口不同。在实际开发中,我们也不会同时使用到那么多种写法,但是这并不意味着我们不需要去了解这些写法!
如果你仔细阅读 Vue3 的文档,会发现一些示例或者 api 看起来模棱两可,不知道这些 api 到底有什么用,或者阅读 Vue
的源码时,总是能发现一些对于我们来说意图不明的逻辑,那么,你可能先要了解一些 Vue 的写法。先了解一个东西怎么用,再去分析它是怎么实现的。
看完本文章,你会收获到:
- vue 的渲染原理。
- 什么是 define***ponent、h、creatVnode。
- 渲染函数和 jsx 的区别。
- 马上能够上手 jsx。
- 轻松阅读 vue 文档的所有示例和 api。
- 轻松看懂不同的 vue 组件写法。
- 不管新手老手,都会对 Vue 有所新的认识。
- 等等…
本文章遵从循序渐进的写作顺序,从易到难,轻松上手!
setup 语法糖
setup 语法糖应该是最常用的写法了。在 Vue3 中,我们想封装一个组件,最习惯的做法还是新建一个 Vue
文件,并将组件代码写在文件中。具体是:页面结构写在 template 中,页面逻辑写在 script 中,页面样式写在 style 中。
总之,我们将与该组件相关的代码都写在一起、放在一个文件中单独维护,在需要该组件的地方引入使用。
这里我们使用了 setup 语法糖,直接在 script 中书写我们的 setup 内部的逻辑。
<template>
<div>{
{
name }}</div>
</template>
<script setup lang="ts">
import {
ref } from "vue";
const name = ref("天气好");
</script>
<style scoped></style>
在 App. vue 中引入并使用:
// App.vue
<template>
<User />
</template>
<script setup lang="ts">
import User from "./User.vue";
</script>
<style scoped></style>
注:后续写法尽管形式不同,但它们最终的目的都是导出一个组件,所以对于组件使用方来说(这里是 App.
vue),怎么使用这个组件的代码都是不变的,所以将不再重复此代码。
Vue2 选项式写法
Vue2 经典写法
这种写法也是比较经典的。和 setup 语法糖写法类似。我们需要新建一个 vue
文件来存储我们的组件代码,然后在需要使用该组件的地方对其进行引入。区别在于,我们需要在 script 中导出一个 Vue 实例。
这里我们导出的其实是一个普通对象,该对象包含 data、methods 等属性。这个对象的属性都是可选的,即 option,翻译回来即“选项”。
<template>
<div>{
{
name }}</div>
</template>
<script lang="ts">
export default {
data: () => {
return {
name: "天气好",
};
},
};
</script>
<style></style>
define***ponent 辅助函数
尽管我们在 script 语言块中导出的默认对象会被 vue 编译器当成 vue 实例,但不管怎么看,它依旧只是一个 plain
object。在定义组件实例方面,vue 提供了一个名为 define***ponent 辅助接口。
<template>
<div>{
{
name }}</div>
</template>
<script lang="ts">
import {
define***ponent } from "vue";
export default define***ponent({
data: () => {
return {
name: "天气好",
};
},
});
</script>
<style></style>
尽管这个接口也不能改变我们导出的是一个普通对象的事实,但是它可以为我们的实例提供强大的类型推导。我们可以把它看成是一个返回 vue实例的工厂函数,让我们的代码看起来更加规范。
Vue3 选项式写法
在 Vue3 中,官方引入了新的选项 setup,这是 Vue3 选项式写法和 Vue2 写法的主要区别。setup
选项的意义在于它允许我们在选项式的写法中引用和使用组合式的 api,比如 onMounted、ref、reactive
等。但对于我们来说,它对于我们有益的地方还是基于它封装起来的 setup 语法糖用起来很方便。
<template>
<div>{
{
name }}</div>
</template>
<script lang="ts">
export default {
setup() {
return {
name: "天气好",
};
},
};
</script>
<style></style>
使用 define***ponent 时,它能够提示我们 setup 将会接收到什么参数:
<template