Vue 3.0 新特性及使用方法

介绍

2020年9月19日凌晨,尤雨溪大大正式发布了 Vue.js 3.0 版本,代号:One Piece。此框架新的主要版本提供了更好的性能、更小的捆绑包体积、更好的 TypeScript 集成、用于处理大规模用例的新 API,并为框架未来的长期迭代奠定了坚实的基础。

3.0 版本的开发周期长达两年多,期间产生了 30+ RFCs、2600+ commits、628 pull requests,以及核心仓库之外的大量开发和文档工作。

Vue 3.0 的发布标志着此框架整体上已处于可用状态。尽管框架的某些子项目可能仍需要进一步的开发才能达到稳定状态(特别是 devtools 中的路由和 Vuex 集成),不过现在仍然是开始使用 Vue 3 启动新项目的合适时机。官方还鼓励库作者现在可以开始升级项目以支持 Vue 3。

what is RFC?

RFC(Request For Comments) - 即请求评议,旨在为新功能进入框架提供一致且受控的路径。

The "RFC" (request for comments) process is intended to provide a consistent and controlled path for new features to enter the framework.
Many changes, including bug fixes and documentation improvements can be implemented and reviewed via the normal GitHub pull request workflow.
Some changes though are "substantial", and we ask that these be put through a bit of a design process and produce a consensus among the Vue core team and the community.

RFC 为新功能的引入提供了统一可控的途径,利于在Vue核心团队和社区中进行方案的讨论和优化,最终达成共识。

The RFC life-cycle

An RFC goes through the following stages:

  • Pending: when the RFC is submitted as a PR.
  • Active: when an RFC PR is merged and undergoing implementation.
  • Landed: when an RFC's proposed changes are shipped in an actual release.
  • Rejected: when an RFC PR is closed without being merged.

如何参与

提出RFC pull request前,先在issue中讨论该问题,然后提出RFC PR,PR中包含一个 RFC的markdown文件(非实际代码),经过讨论后核心团队最终将决定是否接受或拒绝该RFC。RFC的提出者并不一定需要自己去实现它(当然欢迎实现)。

Vue RFCs 仓库

创建Vue3.0项目

  • 通过脚手架 vite 安装:
npm init vite-app hello-vue3 # OR yarn create vite-app hello-vue3

Vite is an opinionated web dev build tool that serves your code via native ES Module imports during dev and bundles it with Rollup for production.

Vite目前仅支持 Vue 3.x以上,这意味着你不能使用不兼容Vue 3的组件库

目前基于Vue的第三方组件库兼容Vue 3的情况:

Ant Design Vue:支持 Vue 3.0 的 2.0.0 测试版已发布

ElementUI:尚未支持

MintUI:尚未支持

iView(ViewUI):尚未支持

Vue2-leaflet:很明显不支持

  • 通过脚手架 vue-cli 安装:

首先全局更新最新版的 Vue CLI,4.5.0以上版本支持 Vue3:


npm install -g @vue/cli # OR yarn global add @vue/cli
vue create hello-vue3
# select vue 3 preset

Vue2.x 项目升级为 Vue3.x项目

最简单的方法,就是使用vue-cli 3.0,创建一个新的项目,然后将原有的项目源码拷到新的项目中。

Vue3中兼容Vue2中定义组件的写法,所以只需要将入口文件 main.js 中创建Vue实例的代码替换为使用Vue3中新引入的 createApp方法,来创建应用程序实例的方式即可。

Vue 2 main.js:

import Vue from 'vue'
import App from './App.vue'

new Vue({
    render: h => h(App),
}).$mount('#app')

Vue 3 main.js:

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

值得注意的Vue3 新特性

Composition API(组合 API):

当组件变得越来越大时,逻辑关注点的列表也会增长。这可能会导致组件难以阅读和理解,且碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。

如果能够将与同一个逻辑关注点相关的代码配置在一起会更好,于是 Composition API 应运而生。

使用Composition api的位置被称为setup

setup组件选项

setup 组件选项在创建组件之前执行,一旦 props 被解析,并充当合成 API 的入口点。

注意:由于在执行 setup 时尚未创建组件实例,因此在 setup 选项中没有 this。这意味着,除了 props 之外,你将无法访问组件中声明的任何属性——本地状态、计算属性或方法。

// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted } from 'vue'

// in our component
export default {
    setup (props) {
      const repositories = ref([]) // 定义一个变量
      const getUserRepositories = async () => { // 定义一个方法
        repositories.value = await fetchUserRepositories(props.user)
      }

      onMounted(getUserRepositories) // 生命周期钩子 当实例mounted后调用getUserRepositories方法

      return {
        repositories, // 返回一个data
        getUserRepositories // 返回一个method
      }
    }
}

单文件组件 Composition API 语法糖 ( // 使用了 Composition API 语法糖:

单文件组件状态驱动的 CSS 变量 (

单文件组件

Vue 3的重大改变

引入createApp

背景:

从技术上讲,Vue 2 没有“app”的概念,我们定义的应用程序只是通过 new Vue() 创建的根 Vue 实例。从同一个 Vue 构造函数创建的每个根实例共享相同的全局配置,因此全局配置使得在测试期间很容易意外地污染其他测试用例。用户需要仔细存储原始全局配置,并在每次测试后恢复 (例如重置 Vue.config.errorHandler)。有些 API 像 Vue.use 以及 Vue.mixin 甚至连恢复效果的方法都没有,这使得涉及插件的测试特别棘手。

createApp:

import { createApp } from 'vue'

const app = createApp({})

调用 createApp 返回一个应用实例,应用程序实例暴露当前全局 API 的子集,任何全局改变 Vue 行为的 API 现在都会移动到应用实例上,以下是当前全局 API 及其相应实例 API 的表:

[图片上传失败...(image-c4a9d6-1601349914900)]

所有其他不全局改变行为的全局 API 现在被命名为 exports。

全局和内部API已重构为可 tree-shakable

Tree shaking 是一个通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code) 行为的术语。
它依赖于ES2015中的 import 和 export 语句,用来检测代码模块是否被导出、导入,且被 JavaScript 文件使用。
在现代 JavaScript 应用程序中,我们使用模块打包(如webpack或Rollup)将多个 JavaScript 文件打包为单个文件时自动删除未引用的代码。这对于准备预备发布代码的工作非常重要,这样可以使最终文件具有简洁的结构和最小化大小。

2.x 语法:

// 全局 API Vue.nextTick() 不能tree-shaking
import Vue from 'vue'

Vue.nextTick(() => {
  // 一些和DOM有关的东西
})

3.x语法:

全局 API 现在只能作为 ES 模块构建的命名导出进行访问,如果模块绑定器支持 tree-shaking,则 Vue 应用程序中未使用的全局 api 将从最终捆绑包中消除,从而获得最佳的文件大小。

import { nextTick } from 'vue'

nextTick(() => {
  // 一些和DOM有关的东西
})

受影响的API:

  • Vue.nextTick
  • Vue.observable (用Vue.reactive替换)
  • Vue.version
  • Vue.compile
  • Vue.set
  • Vue.delete

组件上 v-model 用法已更改

  • 自定义v-model时,prop和事件默认名称已更改:
    prop: value -> modelValue
    event: input -> update:modelValue
  • .sync和组件的model选项已移除,可用v-model作为替代
  • 现在可以在同一个组件上使用多个 v-model 进行双向绑定;
  • 现在可以自定义 v-model 修饰符
    比如自定义v-model.capitalize,绑定为字符串第一个字母的大写