1.7.2 • Published 8 months ago

@vue/composition-api v1.7.2

Weekly downloads
92,707
License
MIT
Repository
github
Last release
8 months ago

@vue/composition-api

用于提供 组合式 API 的 Vue 2 插件.

npm GitHub Workflow Status

English | 中文 ・ 组合式 API 文档

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

安装

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'

:bulb: 当迁移到 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.2"></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库)。

限制

:white_check_mark: 支持     :x: 不支持

Ref 自动展开 (unwrap)

const a = {
  count: ref(0),
}
const b = reactive({
  list: [a], // `a.count` 不会自动展开!!
})

// `count` 不会自动展开, 须使用 `.value`
b.list[0].count.value === 0 // true
const b = reactive({
  list: [
    {
      count: ref(0), // 不会自动展开!!
    },
  ],
})

// `count` 不会自动展开, 须使用 `.value`
b.list[0].count.value === 0 // true
const a = reactive({
  count: ref(0),
})
const b = reactive({
  list: [a],
})
// 自动展开
b.list[0].count === 0 // true

b.list.push(
  reactive({
    count: ref(1),
  })
)
// 自动展开
b.list[1].count === 1 // true

模板 Refs

<template>
  <div ref="root"></div>
</template>

<script>
  export default {
    setup() {
      const root = ref(null)

      onMounted(() => {
        // 在初次渲染后 DOM 元素会被赋值给 ref
        console.log(root.value) // <div/>
      })

      return {
        root,
      }
    },
  }
</script>
export default {
  setup() {
    const root = ref(null)

    onMounted(() => {
      // 在初次渲染后 DOM 元素会被赋值给 ref
      console.log(root.value) // <div/>
    })

    return {
      root,
    }
  },
  render() {
    // 使用 JSX
    return () => <div ref="root" />
  },
}
<template>
  <div :ref="el => root = el"></div>
</template>

<script>
  export default {
    setup() {
      const root = ref(null)

      return {
        root,
      }
    },
  }
</script>
export default {
  setup() {
    const root = ref(null)

    return () =>
      h('div', {
        ref: root,
      })

    // 使用 JSX
    return () => <div ref={root} />
  },
}

:warning: 警告: SetupContext.refs 并非 Vue 3.0 的一部分, @vue/composition-api 将其暴露在 SetupContext 中只是临时提供一种变通方案。

如果你依然选择在 setup() 中写 render 函数,那么你可以使用 SetupContext.refs 来访问模板引用,它等价于 Vue 2.x 中的 this.$refs:

export default {
  setup(initProps, setupContext) {
    const refs = setupContext.refs
    onMounted(() => {
      // 在初次渲染后 DOM 元素会被赋值给 ref
      console.log(refs.root) // <div/>
    })

    return () =>
      h('div', {
        ref: 'root',
      })

    // 使用 JSX
    return () => <div ref="root" />
  },
}

如果项目使用了 TypeScript,你还需要扩展 SetupContext 类型:

import Vue from 'vue'

declare module '@vue/composition-api' {
  interface SetupContext {
    readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] }
  }
}

Reactive

此行为与 Vue 2 中的 Vue.observable 一致

:bulb: 在 Vue 3 中,reactive() 会返回一个新的的代理对象

⚠️ 警告: setdel 并非 Vue 3 的一部分。由于 Vue 2.x 响应式系统的限制, 我们在这里提供它们作为一种变通方案。 在 Vue 2中,你将需要调用set 去追踪object上新的属性 (与Vue.set类似,但用于由 Composition API 创建的reactive objects)。在 Vue 3 中,你只需要像对待普通对象一样直接为属性赋值即可。

同样地, 在 Vue 2 中你将需要调用del确保响应式对象中属性的删除将触发视图更新 (与Vue.delete类似,但用于由 Composition API 创建的reactive objects)。在Vue3中,你只需要通过调用 delete foo.bar 来删除它们。

import { reactive, set, del } from '@vue/composition-api'

const a = reactive({
  foo: 1
})

// 添加新的响应式属性
set(a, 'bar', 1)

// 刪除属性并触发响应式更新
del(a, 'bar')

Watch

watch(
  () => {
    /* ... */
  },
  {
    immediate: true,
    onTrack() {}, // 不可用
    onTrigger() {}, // 不可用
  }
)

createApp

在 Vue3 中,引入了 createApp() 来隔离不同应用实例的上下文(plugin, components 等)。 由于 Vue2 的设计,在这个插件中,我们提供 createApp() 作为一个向前兼容的 API ,它只是全局的一个别名。

const app1 = createApp(RootComponent1)
app1.component('Foo', Foo) // 相当于 Vue.component('Foo', Foo)
app1.use(VueRouter) // 相当于 Vue.use(VueRouter)

const app2 = createApp(RootComponent2)
app2.component('Bar', Bar) // 相当于 Vue.component('Bar', Bar)

createElement / h

在 Vue2中 createElement / h 只能通过 render() 函数访问。要在 render()之外使用它, 你可以显式地给它绑定一个组件实例。

:warning: 警告: 此功能是作为 Vue 2 的变通方法提供的,它不是 Vue 3 API 的一部分。

import { h as _h } from '@vue/composition-api'

export default {
  setup() {
    const vm = getCurrentInstance()
    const h = _h.bind(vm)

    return () =>
      h('div', {
        ref: 'root',
      })
  },
}

shallowReadonly

:bulb: 在 Vue 3 中,shallowReadonly() 会返回一个新的的代理对象

readonly

readonly() 只在类型层面提供和 Vue 3 的对齐。在其返回值或其属性上使用 isReadonly() 检查的结果将无法保证。

props

// use this instead
const { foo } = toRefs(props)
const a = foo.value.bar

} })

</details>

### `computed().effect`

<details>
<summary>
⚠️ <code>computed()</code> 拥有一个被设置为 <code>true</code> 的 <code>effect</code> 属性,用来代替 <code>ReactiveEffect<T></code>。
</summary>

由于实现上的不同, 在 `@vue/composition-api` 中没有 `ReactiveEffect` 这种概念。 因此, `effect` 为 `true` 只是为了能够区分 computed 和 refs: 

```ts
function isComputed<T>(o: ComputedRef<T> | unknown): o is ComputedRef<T>
function isComputed(o: any): o is ComputedRef {
  return !!(isRef(o) && o.effect)
}

缺失的 API

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

  • onRenderTracked
  • onRenderTriggered
  • isProxy

data() 中使用组合式 API

export default {
  data() {
    return {
      // 在模版中会成为 { a: { value: 1 } }
      a: ref(1),
    }
  },
}

emit 选项

defineComponent({
  emit: {
    // 无效
    submit: (eventOption) => {
      if (...) {
        return true
      } else {
        console.warn('Invalid submit event payload!')
        return false
      }
    }
  }
})

性能影响

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

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

vue2-number-rollfirefly-library@synaps-io-pre-prod/vue3-verifyayynn-uichat-test-uni-2@glennliao/uni-xcr-components@ambita/design-system@jaydubb12/lightswitch-coressm-alert-buttonanet20-storybookdodder-admin1xiaotan-v-linkage@efs/vue-componentsquasar-app-extension-three-sixtylj-codestep-components@kinokos/hara-rin@kinokos/view@clownegg/componentsthw-uiclouddb-console-shared-componentsvue-isc-libraryspaceone-design-systemspaceone-consolespaceone-ds@onelly/corevue2-viteweiling-addtagweiling-operaion-taginsight-pack-ts-b@airbit/ui-core@learnlink/gucci@jaydubb12/lightswitch-shopifysyns-ribbon-vue@airbit/air-design-systemmh-bm-componentswc-syns-ribbon@zitrus/componentsfront-admin-vue3vue-hotspot3vue-hotspot2vue-wangsong2-hotspotvue-wangsong3-hotspot@learnlink/componentspwc-frontend-componentrobinapp-vue-sdk@skoda-dms/component-libvue-debug-logtemplate-firm-pc0ikontrol-component-librarywb-common@branchito/wc@cmss/clouddb-console-shared-componentsquick-app@v1narth/fieldgdbpmn-jsscene-components-search-boxscene-components-search-box-testtj-virtualized-tree@bheimberg/field@ued_fpi/element-prototypes@ued_fpi/element-settings-formlamasign-components-librarydp-bz-commonrobin.io-vuerobin.vue-sdkscene-component-search-box-test-libscene-components-lib-betascene-components-lib-beta-testscene-components-search-box-test-lib@aapokiiso/fillarivahti-web-frontendweiling-material-componentpublish-to-npm-v3shawnz-work-flow-enginecr-vue-uiplatformindex@ambita/infoland-mflexyl-baseuildesign-desktopsdk-263-phonewaytohealth-inboxesc-uiartusview1@infinitebrahmanuniverse/nolb-_vue_@coveyz/admin-boxpds-formmakingpds-components@mega-apps/lowcode@everything-registry/sub-chunk-994@dev.ducnv/g2plot-vuexiaoyuer-uixlwal-vue2eli-compelement-pro-crudelement-pro-crud-modeltwoelement-pro-toolkitelement-base-zhjessc-component-libessc-util-lib
1.7.2

8 months ago

1.7.1

2 years ago

1.7.0

2 years ago

1.6.3

2 years ago

1.6.2

2 years ago

1.6.1

2 years ago

1.6.0

2 years ago

1.5.0

2 years ago

1.4.9

2 years ago

1.4.8

2 years ago

1.4.7

2 years ago

1.4.6

2 years ago

1.4.5

2 years ago

1.4.4

2 years ago

1.4.3

2 years ago

1.4.2

2 years ago

1.4.1

2 years ago

1.4.0

2 years ago

1.4.0-beta.0

2 years ago

1.3.3

2 years ago

1.3.2

2 years ago

1.3.1

2 years ago

1.3.0

2 years ago

1.2.4

3 years ago

1.2.3

3 years ago

1.2.2

3 years ago

1.2.0

3 years ago

1.2.1

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.0.6

3 years ago

1.1.0-beta.7

3 years ago

1.1.0-beta.6

3 years ago

1.1.0

3 years ago

1.0.5

3 years ago

1.1.0-beta.5

3 years ago

1.0.4

3 years ago

1.1.0-beta.4

3 years ago

1.0.3

3 years ago

1.1.0-beta.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.1.0-beta.2

3 years ago

1.1.0-beta.1

3 years ago

1.0.0

3 years ago

1.0.0-rc.14

3 years ago

1.0.0-rc.13

3 years ago

1.0.0-rc.12

3 years ago

1.0.0-rc.11

3 years ago

1.0.0-rc.10

3 years ago

1.0.0-rc.9

3 years ago

1.0.0-rc.8

3 years ago

1.0.0-rc.7

3 years ago

1.0.0-rc.6

3 years ago

1.0.0-rc.5

3 years ago

1.0.0-rc.4

3 years ago

1.0.0-rc.3

3 years ago

1.0.0-rc.2

3 years ago

1.0.0-rc.1

3 years ago

1.0.0-beta.26

3 years ago

1.0.0-beta.25

3 years ago

1.0.0-beta.24

3 years ago

1.0.0-beta.23

3 years ago

1.0.0-beta.22

3 years ago

1.0.0-beta.21

3 years ago

1.0.0-beta.20

3 years ago

1.0.0-beta.19

3 years ago

1.0.0-beta.18

4 years ago

1.0.0-beta.17

4 years ago

1.0.0-beta.16

4 years ago

1.0.0-beta.15

4 years ago

1.0.0-beta.14

4 years ago

1.0.0-beta.13

4 years ago

1.0.0-beta.12

4 years ago

1.0.0-beta.11

4 years ago

1.0.0-beta.10

4 years ago

1.0.0-beta.9

4 years ago

1.0.0-beta.8

4 years ago

1.0.0-beta.7

4 years ago

1.0.0-beta.6

4 years ago

1.0.0-beta.5

4 years ago

1.0.0-beta.4

4 years ago

1.0.0-beta.3

4 years ago

1.0.0-beta.2

4 years ago

1.0.0-beta.1

4 years ago

0.6.7

4 years ago

0.6.6

4 years ago

0.6.5

4 years ago

0.6.4

4 years ago

0.6.3

4 years ago

0.6.2

4 years ago

0.6.1

4 years ago

0.6.0

4 years ago

0.5.0

4 years ago

0.4.0

4 years ago

0.3.4

4 years ago

0.3.3

4 years ago

0.3.2

5 years ago

0.3.1

5 years ago

0.3.0

5 years ago

3.0.0

5 years ago

0.2.1

5 years ago

0.2.0

5 years ago

0.1.0

5 years ago