Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/vuejs/composition-api
Composition API plugin for Vue 2
https://github.com/vuejs/composition-api
Last synced: 7 days ago
JSON representation
Composition API plugin for Vue 2
- Host: GitHub
- URL: https://github.com/vuejs/composition-api
- Owner: vuejs
- License: mit
- Created: 2019-06-25T08:45:13.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2023-08-15T11:08:15.000Z (over 1 year ago)
- Last Synced: 2024-10-29T10:46:01.548Z (2 months ago)
- Language: TypeScript
- Homepage: https://composition-api.vuejs.org/
- Size: 1.6 MB
- Stars: 4,192
- Watchers: 70
- Forks: 343
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-starred-test - vuejs/composition-api - Composition API plugin for Vue 2 (TypeScript)
- awesome-vue-3 - composition-api - Vue2 plugin for the Composition API. (Packages)
README
# @vue/composition-api
Vue 2 plugin for **Composition API**
[![npm](https://img.shields.io/npm/v/@vue/composition-api)](https://www.npmjs.com/package/@vue/composition-api)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/vuejs/composition-api/test.yml)](https://github.com/vuejs/composition-api/actions?query=workflow%3A%22Build+%26+Test%22)
[![Minzipped size](https://badgen.net/bundlephobia/minzip/@vue/composition-api)](https://bundlephobia.com/result?p=@vue/composition-api)English | [中文](./README.zh-CN.md) ・ [**Composition API Docs**](https://v3.vuejs.org/guide/composition-api-introduction.html)
> ⚠️ With the release of [Vue 2.7](https://blog.vuejs.org/posts/vue-2-7-naruto.html), which has Composition API built-in, **you no longer need this plugin**. Thereby this plugin has entered maintenance mode and will only support Vue 2.6 or earlier. This project will reach End of Life by the end of 2022.
## Installation
### NPM
```bash
npm install @vue/composition-api
# or
yarn add @vue/composition-api
```You must install `@vue/composition-api` as a plugin via `Vue.use()` before you can use the [Composition API](https://composition-api.vuejs.org/) to compose your component.
```js
import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'Vue.use(VueCompositionAPI)
``````js
// use the APIs
import { ref, reactive } from '@vue/composition-api'
```> :bulb: When you migrate to Vue 3, just replacing `@vue/composition-api` to `vue` and your code should just work.
### CDN
Include `@vue/composition-api` after Vue and it will install itself automatically.
```html
```
`@vue/composition-api` will be exposed to global variable `window.VueCompositionAPI`.
```ts
const { ref, reactive } = VueCompositionAPI
```## TypeScript Support
> TypeScript version **>4.2** is required
To let TypeScript properly infer types inside Vue component options, you need to define components with `defineComponent`
```ts
import { defineComponent } from '@vue/composition-api'export default defineComponent({
// type inference enabled
})
```### JSX/TSX
JSX is now officially supported on [vuejs/jsx](https://github.com/vuejs/jsx). You can enable it by following [this document](https://github.com/vuejs/jsx/tree/dev/packages/babel-preset-jsx#usage). A community maintained version can be found at [babel-preset-vca-jsx](https://github.com/luwanquan/babel-preset-vca-jsx) by [@luwanquan](https://github.com/luwanquan).
To support TSX, create a declaration file with the following content in your project.
```ts
// 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
Even if there is no definitive Vue 3 API for SSR yet, this plugin implements the `onServerPrefetch` lifecycle hook that allows you to use the `serverPrefetch` hook found in the classic API.
```js
import { onServerPrefetch } from '@vue/composition-api'export default {
setup(props, { ssrContext }) {
const result = ref()onServerPrefetch(async () => {
result.value = await callApi(ssrContext.someId)
})return {
result,
}
}
}
```## Browser Compatibility
`@vue/composition-api` supports all modern browsers and IE11+. For lower versions IE you should install `WeakMap` polyfill (for example from `core-js` package).
## Limitations
> :white_check_mark: Support :x: Not Supported
### `Ref` Unwrap
❌ Should NOT use
ref
in a plain object when working withArray
```js
const a = {
count: ref(0),
}
const b = reactive({
list: [a], // `a.count` will not unwrap!!
})// no unwrap for `count`, `.value` is required
b.list[0].count.value === 0 // true
``````js
const b = reactive({
list: [
{
count: ref(0), // no unwrap!!
},
],
})// no unwrap for `count`, `.value` is required
b.list[0].count.value === 0 // true
```✅ Should always use
ref
in areactive
when working withArray
```js
const a = reactive({
list: [
reactive({
count: ref(0),
}),
]
})
// unwrapped
a.list[0].count === 0 // truea.list.push(
reactive({
count: ref(1),
})
)
// unwrapped
a.list[1].count === 1 // true
```### Template Refs
✅ String ref && return it from
setup()
```html
export default {
setup() {
const root = ref(null)onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(root.value) // <div/>
})return {
root,
}
},
}```
✅ String ref && return it from
setup()
&& Render Function / JSX```jsx
export default {
setup() {
const root = ref(null)onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(root.value) //
})return {
root,
}
},
render() {
// with JSX
return () =>
},
}
```❌ Function ref
```html
export default {
setup() {
const root = ref(null)return {
root,
}
},
}```
❌ Render Function / JSX in
setup()
```jsx
export default {
setup() {
const root = ref(null)return () =>
h('div', {
ref: root,
})// with JSX
return () =>
},
}
```⚠️
$refs
accessing workaround
> :warning: **Warning**: The `SetupContext.refs` won't exist in `Vue 3.0`. `@vue/composition-api` provide it as a workaround here.
If you really want to use template refs in this case, you can access `vm.$refs` via `SetupContext.refs`
```jsx
export default {
setup(initProps, setupContext) {
const refs = setupContext.refs
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(refs.root) //
})return () =>
h('div', {
ref: 'root',
})// with JSX
return () =>
},
}
```### Reactive
⚠️
reactive()
mutates the original object`reactive` uses `Vue.observable` underneath which will ***mutate*** the original object.
> :bulb: In Vue 3, it will return a new proxy object.
⚠️
set
anddel
workaround for adding and deleting reactive properties> ⚠️ Warning: `set` and `del` do NOT exist in Vue 3. We provide them as a workaround here, due to the limitation of [Vue 2.x reactivity system](https://vuejs.org/v2/guide/reactivity.html#For-Objects).
>
> In Vue 2, you will need to call `set` to track new keys on an `object`(similar to `Vue.set` but for `reactive objects` created by the Composition API). In Vue 3, you can just assign them like normal objects.
>
> Similarly, in Vue 2 you will need to call `del` to [ensure a key deletion triggers view updates](https://vuejs.org/v2/api/#Vue-delete) in reactive objects (similar to `Vue.delete` but for `reactive objects` created by the Composition API). In Vue 3 you can just delete them by calling `delete foo.bar`.```ts
import { reactive, set, del } from '@vue/composition-api'const a = reactive({
foo: 1
})// add new reactive key
set(a, 'bar', 1)// remove a key and trigger reactivity
del(a, 'bar')
```### Watch
❌
onTrack
andonTrigger
are not available inWatchOptions
```js
watch(() => {
/* ... */
}, {
immediate: true,
onTrack() {}, // not available
onTrigger() {}, // not available
})
```### `createApp`
⚠️
createApp()
is globalIn Vue 3, `createApp()` is introduced to provide context(plugin, components, etc.) isolation between app instances. Due the design of Vue 2, in this plugin, we provide `createApp()` as a forward compatible API which is just an alias of the global.
```ts
const app1 = createApp(RootComponent1)
app1.component('Foo', Foo) // equivalent to Vue.component('Foo', Foo)
app1.use(VueRouter) // equivalent to Vue.use(VueRouter)const app2 = createApp(RootComponent2)
app2.component('Bar', Bar) // equivalent to Vue.component('Bar', Bar)
```### `createElement` / `h`
⚠️
createElement
/h
workaround
`createElement` / `h` in Vue 2 is only accessable in `render()` function. To use it outside of `render()`, you can explicitly bind a component instance to it.
> :warning: **Warning**: This ability is provided as a workaround Vue 2, it's not part of the Vue 3 API.
```jsx
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`
⚠️
shallowReadonly()
will create a new object and with the same root properties, new properties added will not be readonly or reactive.> :bulb: In Vue 3, it will return a new proxy object.
### `readonly`
⚠️
readonly()
provides only type-level readonly check.`readonly()` is provided as API alignment with Vue 3 on type-level only. Use
isReadonly()
on it or it's properties can not be guaranteed.### `props`
⚠️
toRefs(props.foo)
will incorrectly warn when accessing nested levels of props.
⚠️isReactive(props.foo)
will return false.```ts
defineComponent({
setup(props) {
const { bar } = toRefs(props.foo) // it will `warn`// use this instead
const { foo } = toRefs(props)
const a = foo.value.bar
}
})
```### `computed().effect`
⚠️
computed()
has a propertyeffect
set totrue
instead of aReactiveEffect
.Due to the difference in implementation, there is no such concept as a `ReactiveEffect` in `@vue/composition-api`. Therefore, `effect` is merely `true` to enable differentiating computed from refs:
```ts
function isComputed(o: ComputedRef | unknown): o is ComputedRef
function isComputed(o: any): o is ComputedRef {
return !!(isRef(o) && o.effect)
}
```### Missing APIs
The following APIs introduced in Vue 3 are not available in this plugin.
- `onRenderTracked`
- `onRenderTriggered`
- `isProxy`### Reactive APIs in `data()`
❌ Passing
ref
,reactive
or other reactive apis todata()
would not work.```jsx
export default {
data() {
return {
// will result { a: { value: 1 } } in template
a: ref(1),
}
},
}
```### `emits` Options
❌
emits
option is provided in type-level only, in order to align with Vue 3's type interface. Does NOT have actual effects on the code.```ts
defineComponent({
emits: {
// has no effects
submit: (eventOption) => {
if (...) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
}
})
```### Performance Impact
Due the limitation of Vue2's public API. `@vue/composition-api` inevitably introduces some performance overhead. Note that in most scenarios, this shouldn't be the source of performance issues.
You can check the [benchmark results](https://antfu.github.io/vue-composition-api-benchmark-results/) for more details.