vue3的单组件编写【一】

文章目录

  • [:tiger: 单组件的编写](#:tiger: 单组件的编写)
    • [:rainbow:全新的 setup 函数](#:rainbow:全新的 setup 函数)
      • [:rocket: setup 的含义](#:rocket: setup 的含义)
      • [:rocket:setup 的参数使用](#:rocket:setup 的参数使用)
      • [:rocket: defineComponent 的作用](#:rocket: defineComponent 的作用)
    • [:rainbow: 组件的生命周期](#:rainbow: 组件的生命周期)
      • [:rocket: 升级变化](#:rocket: 升级变化)
      • [:rocket: 使用 3.x 的生命周期](#:rocket: 使用 3.x 的生命周期)
    • [:rainbow: 组件的基本写法](#:rainbow: 组件的基本写法)
      • [:rocket: 回顾 Vue 2](#:rocket: 回顾 Vue 2)
      • [:rocket: 了解 Vue 3](#:rocket: 了解 Vue 3)

🐯 单组件的编写

项目搭好了,第一个需要了解的是 Vue 组件的变化,由于这部分篇幅会非常大,所以会分成很多个小节,一部分一部分按照开发顺序来逐步了解。

因为 Vue 3 对 TypeScript 的支持真的是太完善了,并且 TypeScript 的发展趋势和市场需求度越来越高,所以接下来都将直接使用 TypeScript 进行编程。

对 TypeScript 不太熟悉的开发者,建议先阅读 快速上手 TypeScript 一章,有了一定的语言基础之后,再一边写代码一边加深印象。

🌈全新的 setup 函数

在开始编写 Vue 组件之前,需要了解两个全新的前置知识点:

  • 全新的 setup 函数,关系到组件的生命周期和渲染等问题
  • 写 TypeScript 组件离不开的 defineComponent API

🚀 setup 的含义

Vue 3 的 Composition API 系列里,推出了一个全新的 setup 函数,它是一个组件选项,在创建组件之前执行,一旦 props 被解析,并作为组合式 API 的入口点。

说的通俗一点,就是在使用 Vue 3 生命周期的情况下,整个组件相关的业务代码,都可以放在 setup 里执行。

因为在 setup 之后,其他的生命周期才会被启用。

基本语法:

typescript 复制代码
// 这是一个基于 TypeScript 的 Vue 组件
import { defineComponent } from 'vue'

export default defineComponent({
  setup(props, context) {
    // 在这里声明数据,或者编写函数并在这里执行它

    return {
      // 需要给 `<template />` 用的数据或函数,在这里 `return` 出去
    }
  },
})

可以发现在这段代码里还导入了一个 defineComponent API ,也是 Vue 3 带来的新功能,下文的defineComponent 的作用 将介绍其用法。

在使用 setup 的情况下,请牢记一点:不能再用 this 来获取 Vue 实例,也就是无法和 Vue 2 一样,通过 this.foothis.bar() 这样来获取实例上的数据,或者执行实例上的方法。

在使用 setup 的情况下 , 不能再用 this 来获取 Vue 实例;

在使用 setup 的情况下 , 不能再用 this 来获取 Vue 实例';

在使用 setup 的情况下 , 不能再用 this 来获取 Vue 实例;

🚀setup 的参数使用

setup 函数包含了两个入参:

参数 类型 含义 是否必传
props object 由父组件传递下来的数据
context object 组件的执行上下文

第一个参数 props

它是响应式的,当父组件传入新的数据时,它将被更新。

⭐️ ⭐️⭐️ 请不要解构它,这样会让数据失去响应性,一旦父组件发生数据变化,解构后的变量将无法同步更新为最新的值。

可以使用 Vue 3 全新的响应式 API toRef / toRefs 进行响应式数据转换,下文将会介绍全新的响应式 API 的用法。

第二个参数 context

context 只是一个普通的对象,它暴露三个组件的 Property :

属性 类型 作用
attrs 非响应式对象 未在 Props 里定义的属性都将变成 Attrs
slots 非响应式对象 组件插槽,用于接收父组件传递进来的模板内容
emit 方法 触发父组件绑定下来的事件

因为 context 只是一个普通对象,所以可以直接使用 ES6 解构。

平时使用可以通过直接传入 { emit } ,即可用 emit('xxx') 来代替使用 context.emit('xxx'),另外两个功能也是如此。

但是 attrsslots 请保持 attrs.xxxslots.xxx 的方式来使用其数据,不要进行解构,虽然这两个属性不是响应式对象,但对应的数据会随组件本身的更新而更新。

两个参数的具体使用,可查阅 组件之间的通信 一章详细了解。

🚀 defineComponent 的作用

defineComponent 是 Vue 3 推出的一个全新 API ,可用于对 TypeScript 代码的类型推导,帮助开发者简化掉很多编码过程中的类型声明。

比如,原本需要这样才可以使用 setup 函数:

typescript 复制代码
import { Slots } from 'vue'

// 声明 `props` 和 `return` 的数据类型
interface Data {
  [key: string]: unknown
}

// 声明 `context` 的类型
interface SetupContext {
  attrs: Data
  slots: Slots
  emit: (event: string, ...args: unknown[]) => void
}

// 使用的时候入参要加上声明, `return` 也要加上声明
export default {
  setup(props: Data, context: SetupContext): Data {
    // ...

    return {
      // ...
    }
  },
}

每个组件都这样进行类型声明,会非常繁琐,如果使用了 defineComponent , 就可以省略这些类型声明:

typescript 复制代码
import { defineComponent } from "vue"
// 使用 `defineComponent` 包裹组件的内部逻辑
export default defineComponent({
  setup(props, context) {
    // ...

    return {
      // ...
    }
  },
})

代码量瞬间大幅度减少,只要是 Vue 本身的API , defineComponent 都可以自动推导其类型,这样开发和在编写组件的过程中,只需要维护自己定义的数据类型就可以了,可专注于业务。

🌈 组件的生命周期

在了解了 Vue 3 组件的两个前置知识点后,不着急写组件,还需要先了解组件的生命周期,这个知识点非常重要,只有理解并记住组件的生命周期,才能够灵活的把控好每一处代码的执行,使程序的运行结果可以达到预期。

🚀 升级变化

从 Vue 2 升级到 Vue 3 ,在保留对 Vue 2 的生命周期支持的同时,Vue 3 也带来了一定的调整。

Vue2 的生命周期写法名称是 Options API (选项式API) , Vue3 的生命周期写法名称叫 Composition API (组合式API) 。

Vue 3 组件默认支持 Options API ,而 Vue 2 可以通过 @vue/composition-api 插件获得 Composition API 的功能支持(其中 Vue 2.7 版本内置了该插件, 2.6 及以下的版本需要单独安装)。

为了减少理解成本,笔者将从读者的使用习惯上,使用 " Vue 2 的生命周期" 代指 Options API 写法,用 " Vue 3 的生命周期" 代指 Composition API 写法。

关于 Vue 生命周期的变化,可以从下表直观地了解:

Vue 2 生命周期 Vue 3 生命周期 执行时间说明
beforeCreate setup 组件创建前执行
created setup 组件创建后执行
beforeMount onBeforeMount 组件挂载到节点上之前执行
mounted onMounted 组件挂载完成后执行
beforeUpdate onBeforeUpdate 组件更新之前执行
updated onUpdated 组件更新完成之后执行
beforeDestroy onBeforeUnmount 组件卸载之前执行
destroyed onUnmounted 组件卸载完成后执行
errorCaptured onErrorCaptured 当捕获一个来自子孙组件的异常时激活钩子函数

可以看到 Vue 2 生命周期里的 beforeCreatecreated ,在 Vue 3 里已被 setup 替代。

熟悉 Vue 2 的开发者应该都知道 Vue 有一个全局组件 <KeepAlive /> ,用于在多个组件间动态切换时缓存被移除的组件实例,当组件被包含在 <KeepAlive /> 组件里时,会多出两个生命周期钩子函数:

Vue 2 生命周期 Vue 3 生命周期 执行时间说明
activated onActivated 被激活时执行
deactivated onDeactivated 切换组件后,原组件消失前执行

⭐️ 虽然 Vue 3 依然支持 Vue 2 的生命周期,但是不建议混搭使用,前期可以继续使用 Vue 2 的生命周期作为过度阶段慢慢适应,但还是建议尽快熟悉并完全使用 Vue 3 的生命周期编写组件。

🚀 使用 3.x 的生命周期

在 vue3 的 Composition API 写法里, 每个生命周期函数都要先导入才可以使用,并且所有的生命周期函数统一放在 setup 里面运行。

如果需要达到vue2 的 beforeCreatecreated 生命周期的执行时机。 直接在 setup 里执行函数即可。

以下是几个生命周期的执行顺序对比:

typescript 复制代码
import { defineComponent, onBeforeMount, onMounted } from 'vue'

export default defineComponent({
  setup() {
    console.log(1)

    onBeforeMount(() => {
      console.log(2)
    })

    onMounted(() => {
      console.log(3)
    })

    console.log(4)
  },
})

最终将按照生命周期的顺序输出:

js 复制代码
// 1
// 4
// 2
// 3

🌈 组件的基本写法

如果想在 Vue 2 里使用 TypeScript 编写组件,需要通过 Options API 的 Vue.extend 语法,或者是另外一种风格 Class Component 的语法声明组件,其中为了更好的进行类型推导, Class Component 语法更受开发者欢迎。

但是 Class Component 语法和默认的组件语法相差较大,带来了一定的学习成本,对于平时编写 JavaScript 代码很少使用 Class 的开发者,适应时间应该也会比较长。

因此 Vue 3 在保留对 Class Component 支持的同时,推出了全新的 Function-based Component ,更贴合 JavaScript 的函数式编程风格,这也是接下来要讲解并贯穿全文使用的 Composition API 新写法。

Composition API 虽然也是一个变化比较大的改动,但其组件结构并没有特别大的变化,区别比较大的地方在于组件生命周期和响应式 API 的使用,只要掌握了这些核心功能,上手 Vue 3 非常容易!

看到这里可能有开发者心里在想:

"这几种组件写法,加上视图部分又有 Template 和 TSX 的写法之分,生命周期方面 Vue 3 对 Vue 2 的写法又保持了兼容,在 Vue 里写 TypeScript 的组合方式一只手数不过来,在入门时选择合适的编程风格就遇到了困难,可怎么办?"

不用担心!笔者将九种常见的组合方式以表格的形式进行对比, Vue 3 组件最好的写法一目了然!

🚀 回顾 Vue 2

下三种写法声明 TypeScript 组件:

适用版本 基本写法 视图写法
Vue 2 Vue.extend Template
Vue 2 Class Component Template
Vue 2 Class Component TSX

使用 TypeScript 来声明三种不同的组件,可以按照以下方式编写:

  1. 使用 Vue.extend 和模板(Template)的基本写法:
typescript 复制代码
import Vue from 'vue';

const MyComponent: Vue = Vue.extend({
  template: '<div>{{ message }}</div>',
  data() {
    return {
      message: 'Hello, Vue!'
    };
  }
});

export default MyComponent;
  1. 使用 Class Component 和模板(Template)的写法:

为了更好地获得 TypeScript 类型推导支持,通常使用 Class Component 的写法,这是 Vue 官方推出的一个装饰器插件(需要单独安装):

typescript 复制代码
import Vue from 'vue';
import Component from 'vue-class-component';

// @Component 修饰符注明了此类为一个 Vue 组件
@Component({
  // 所有的组件选项都可以放在这里
  template: '<div>{{ message }}</div>'
})

// 使用 Class 声明一个组件
export default class MyComponent extends Vue {
    
  // 初始数据可以直接声明为实例的 property
  message: string = 'Hello, Vue!';
    
  // 组件方法也可以直接声明为实例的方法
  onClick(): void {
    window.alert(this.message)
  }
}
  1. 使用 Class Component 和 TSX 的写法:
tsx 复制代码
import Vue, { VueConstructor } from 'vue';
import Component from 'vue-class-component';

// @Component 修饰符注明了此类为一个 Vue 组件
@Component
export default class MyComponent extends Vue {
  message: string = 'Hello, Vue!';

  render(h: VueConstructor['createElement']) {
    return <div>{this.message}</div>;
  }
}

可在 Vue 2 官网的 TypeScript 支持 一章了解更多配置说明。

🚀 了解 Vue 3

Vue 3 从设计初期就考虑了 TypeScript 的支持,其中 defineComponent 这个 API 就是为了解决 Vue 2 对 TypeScript 类型推导不完善等问题而推出的。

在 Vue 3 ,至少有以下六种写法可以声明 TypeScript 组件:

适用版本 基本写法 视图写法 生命周期版本 官方是否推荐
Vue 3 Class Component Template Vue 2 ×
Vue 3 defineComponent Template Vue 2 ×
Vue 3 defineComponent Template Vue 3
Vue 3 Class Component TSX Vue 2 ×
Vue 3 defineComponent TSX Vue 2 ×
Vue 3 defineComponent TSX Vue 3

其中 defineComponent + Composition API + Template 的组合是 Vue 官方最为推荐的组件声明方式,本书接下来的内容都会以这种写法作为示范案例,也推荐开发者在学习的过程中,使用该组合进行入门。

下面看看如何使用 Composition API 编写一个最简单的 Hello World 组件:

vue 复制代码
<!-- Template 代码和 Vue 2 一样 -->
<template>
  <p class="msg">{{ msg }}</p>
</template>

<!-- Script 代码需要使用 Vue 3 的新写法-->
<script lang="ts">
// Vue 3 的 API 需要导入才能使用
import { defineComponent } from 'vue'

// 使用 `defineComponent` 包裹组件代码
// 即可获得完善的 TypeScript 类型推导支持
export default defineComponent({
  setup() {
    // 在 `setup` 方法里声明变量
    const msg = 'Hello World!'

    // 将需要在 `<template />` 里使用的变量 `return` 出去
    return {
      msg,
    }
  },
})
</script>

<!-- CSS 代码和 Vue 2 一样 -->
<style scoped>
.msg {
  font-size: 14px;
}
</style>

可以看到 Vue 3 的组件也是 <template /> + <script /> + <style /> 的三段式组合,上手非常简单。

其中 Template 沿用了 Vue 2 时期类似 HTML 风格的模板写法, Style 则是使用原生 CSS 语法或者 Less 等 CSS 预处理器编写。

⭐️ 需要注意的是,在 Vue 3 的 Composition API 写法里,数据或函数如果需要在 <template /> 中使用,就必须在 setup 里将其 return 出去,而仅在 <script /> 里被调用的函数或变量,不需要渲染到模板则无需 return

相关推荐
Python私教13 分钟前
Go语言现代web开发15 Mutex 互斥锁
开发语言·前端·golang
A阳俊yi13 分钟前
Vue(13)——router-link
前端·javascript·vue.js
好看资源平台27 分钟前
前端框架对比与选择:如何在现代Web开发中做出最佳决策
前端·前端框架
4triumph29 分钟前
Vue.js教程笔记
前端·vue.js
程序员大金1 小时前
基于SSM+Vue+MySQL的酒店管理系统
前端·vue.js·后端·mysql·spring·tomcat·mybatis
清灵xmf1 小时前
提前解锁 Vue 3.5 的新特性
前端·javascript·vue.js·vue3.5
Jiaberrr1 小时前
教你如何在微信小程序中轻松实现人脸识别功能
javascript·微信小程序·小程序·人脸识别·百度ai
程序员大金1 小时前
基于SpringBoot的旅游管理系统
java·vue.js·spring boot·后端·mysql·spring·旅游
白云~️1 小时前
监听html元素是否被删除,删除之后重新生成被删除的元素
前端·javascript·html
2401_864476931 小时前
无线领夹麦克风哪个降噪好?一文搞懂麦克风什么牌子的音质效果好
javascript·git·sql·github·mssql