※Vue资源收集※ Vue2老项目的新生 —— @vue/composition-api

378 阅读3分钟

Vue 生态资源系列文章更新中,后续将陆续整理更新vue生态下优秀的资源,欢迎大家关注

※Vue资源收集系列※ 媲美Rect ahooks ! Vue Hooks 库收集 —— VueUse

是什么

这是一个为Vue2 2.7版本以下 提供 组合式 API 的 插件.

什么是组合式 API 文档

使用场景

Vue2版本的存续时间较长,造成了大量项目基于vue2开发和维护,在系统功能的野蛮生长中,vue文件越来越大,选项式API导致众多逻辑混在一起,无法进行有效的区分组合,导致代码可维护性差,这也是为什么Vue3会推出组合式API的原因

为什么要有组合式 API?

在Vue版本无法低成本升级的情况下,如果想使用组合式API对老项目进行优化,那么此插件将是很好的选择。

安装

NPM

npm install @vue/composition-api
# or
yarn add @vue/composition-api

在使用 @vue/composition-api 前,必须先通过 Vue.use() 进行安装。之后才可使用新的 组合式 API 进行组件开发。

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
// 使用 API
import { ref, reactive } from '@vue/composition-api'

💡 当迁移到 Vue 3 时,只需简单的将 @vue/composition-api 替换成 vue 即可。你现有的代码几乎无需进行额外的改动。

CDN

在 Vue 之后引入 @vue/composition-api ,插件将会自动完成安装。

<script src="https://cdn.jsdelivr.net/npm/vue@2.6"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/composition-api@1.7.1"></script>

@vue/composition-api 将会暴露在全局变量 window.VueCompositionAPI 中。

const { ref, reactive } = VueCompositionAPI

TypeScript 支持

本插件要求使用 TypeScript 4.2 或以上版本

为了让 TypeScript 在 Vue 组件选项中正确地进行类型推导,我们必须使用 defineComponent 来定义组件:

import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  // 类型推断启用
})

JSX/TSX

JSX 现已在 vuejs/jsx 中官方支持。你可以根据这篇文档开启支持。你也可以使用由 @luwanquan 维护的社区版本 babel-preset-vca-jsx

对于 TSX 支持,请在你的项目中创建如下声明文件:

// file: shim-tsx.d.ts
import Vue, { VNode } from 'vue';
import { ComponentRenderProxy } from '@vue/composition-api';

declare global {
  namespace JSX {
    interface Element extends VNode {}
    interface ElementClass extends ComponentRenderProxy {}
    interface ElementAttributesProperty {
      $props: any; // specify the property name to use
    }
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}

SSR

尽管 Vue 3 暂时没有给出确定的 SSR 的 API,这个插件实现了 onServerPrefetch 生命周期钩子函数。这个钩子允许你使用传统 API 中的 serverPrefetch 函数。

import { onServerPrefetch } from '@vue/composition-api'

export default {
  setup(props, { ssrContext }) {
    const result = ref()

    onServerPrefetch(async () => {
      result.value = await callApi(ssrContext.someId)
    })

    return {
      result,
    }
  },
}

浏览器兼容性

@vue/composition-api 支持所有现代浏览器以及IE11+。对于更低版本的IE浏览器你需要安装WeakMap polyfill (例如使用 core-js库)。

限制

✅ 支持     ❌ 不支持

Ref 自动展开 (unwrap)

❌ 不要 在数组中使用含有 ref 的普通对象

✅ 在数组中,应该 总是将 ref 存放到 reactive 对象中

模板 Refs

✅ 在模板中使用字符串 ref && 从 setup() 返回 ref

✅ 在render()中使用字符串 ref && 从 setup() 返回 ref

❌ 函数式 ref

❌ 在 setup() 中返回的渲染函数 / JSX

⚠️ $refs 访问的变通方案

Reactive

⚠️ reactive() 会返回一个修改过的原始的对象

⚠️ set 和 del 添加与刪除响应式属性变通方案

Watch

❌ 不支持 onTrack 和 onTrigger 选项

createApp

⚠️ createApp() 是全局的

createElement / h

⚠️ createElement / h 变通方案

shallowReadonly

⚠️ shallowReadonly() 会返回一个新的浅拷贝对象,在此之后新加的字段将不会获得只读或响应式状态。

readonly

⚠️ readonly() 只提供类型层面的只读。

props

⚠️ 当使用 toRefs 访问深层属性对象 (如 toRefs(props.foo) 时将会得到不正确的警告。
⚠️ isReactive(props.foo) 将会返回 false。

computed().effect

⚠️ computed() 拥有一个被设置为 true 的 effect 属性,用来代替 ReactiveEffect

缺失的 API

以下在 Vue 3 新引入的 API ,在本插件中暂不适用:

  • onRenderTracked
  • onRenderTriggered
  • isProxy

在 data() 中使用组合式 API

❌ 在 data() 中使用 refreactive 或其他组合式 API 将不会生效

emit 选项

❌ emit 仅因在类型定义中对齐 Vue3 的选项而提供,不会有任何效果。

性能影响

由于 Vue 2 的公共 API 的限制,@vue/composition-api 不可避免地引入了额外的性能开销。除非在极端情况下,否则这并不会对你造成影响。

你可以查看这个 跑分结果 了解更多信息。

特殊说明

⚠️ 随着 Vue 2.7的发布,它内置了Composition API,你不再需要这个插件了。因此,这个插件已经进入维护模式,将只支持Vue 2.6 或更早的版本。本项目将在 2022 年底达到生命终点(EOL)。