Vue Composition API
Vue 2 plugin for Composition API in Vue 3.
![GitHub Workflow Status](https://img.shields.io/github/workflow/status/vuejs/composition-api/Build%20&%20Test)
English | 中文文档 / Composition API RFC
Note: the primary goal of this package is to allow the community to experiment with the API and provide feedback before it's finalized. The implementation may contain minor inconsistencies with the RFC as the latter gets updated. We do not recommend using this package for production yet at this stage.
Navigation
Installation
npm
npm install @vue/composition-api
yarn
yarn add @vue/composition-api
CDN
<script src="https://unpkg.com/@vue/composition-api/dist/vue-composition-api.umd.js"></script>
By using the global variable window.vueCompositionApi
Usage
You must install @vue/composition-api
via Vue.use()
before using other APIs:
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
After installing the plugin you can use the Composition API to compose your component.
TypeScript
This plugin requires TypeScript version >3.5.1. If you are using vetur, make sure to set vetur.useWorkspaceDependencies
to true
.
To let TypeScript properly infer types inside Vue component options, you need to define components with defineComponent
:
import { defineComponent } from '@vue/composition-api';
const Component = defineComponent({
});
const Component = {
};
TSX
:rocket: An Example Repository with TS and TSX support is provided to help you start.
To support TSX, create a declaration file with following content in your project.
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;
}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
Limitations
Ref
Unwrap
Unwrap
is not working with Array index.
Should not store ref
as a direct child of Array
:
const state = reactive({
list: [ref(0)],
});
state.list[0].value === 0;
state.list.push(ref(1));
state.list[1].value === 1;
Should not use ref
in a plain object when working with Array
:
const a = {
count: ref(0),
};
const b = reactive({
list: [a],
});
b.list[0].count.value === 0;
const b = reactive({
list: [
{
count: ref(0),
},
],
});
b.list[0].count.value === 0;
Should always use ref
in a reactive
when working with Array
:
const a = reactive({
count: ref(0),
});
const b = reactive({
list: [a],
});
b.list[0].count === 0;
b.list.push(
reactive({
count: ref(1),
})
);
b.list[1].count === 1;
Using reactive
will mutate the origin object
This is an limitation of using Vue.observable
in Vue 2.
Vue 3 will return an new proxy object.
watch()
API
onTrack
and onTrigger
are not available in WatchOptions
.
Template Refs
:white_check_mark:
Support :x: Not Supported
:white_check_mark:
String ref && return it from setup()
:
<template>
<div ref="root"></div>
</template>
<script>
export default {
setup() {
const root = ref(null);
onMounted(() => {
console.log(root.value);
});
return {
root,
};
},
};
</script>
:white_check_mark:
String ref && return it from setup()
&& Render Function / JSX:
export default {
setup() {
const root = ref(null);
onMounted(() => {
console.log(root.value);
});
return {
root,
};
},
render() {
return () => <div ref="root" />;
},
};
:x: Function ref:
<template>
<div :ref="el => root = el"></div>
</template>
<script>
export default {
setup() {
const root = ref(null);
return {
root,
};
},
};
</script>
:x: Render Function / JSX in setup()
:
export default {
setup() {
const root = ref(null);
return () =>
h('div', {
ref: root,
});
return () => <div ref={root} />;
},
};
If you really want to use template refs in this case, you can access vm.$refs
via SetupContext.refs
.
:warning: Warning: The SetupContext.refs
won't exist in Vue 3.0
. @vue/composition-api
provide it as a workaround here.
export default {
setup(initProps, setupContext) {
const refs = setupContext.refs;
onMounted(() => {
console.log(refs.root);
});
return () =>
h('div', {
ref: 'root',
});
return () => <div ref="root" />;
},
};
You may also need to augment the SetupContext
when working with TypeScript:
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
declare module '@vue/composition-api/dist/component/component' {
interface SetupContext {
readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] };
}
}
:x: Reactive APIs in data()
Passing ref
, reactive
or other reactive apis to data()
would not work.
export default {
data() {
return {
a: ref(1)
}
},
};
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.
import { onServerPrefetch } from '@vue/composition-api';
export default {
setup (props, { ssrContext }) {
const result = ref();
onServerPrefetch(async () => {
result.value = await callApi(ssrContext.someId);
});
return {
result,
};
},
};