@vue/composition-api provides a way to use Vue 3.0's Composition api in Vue 2.x.
npm
npm install @vue/composition-api --saveyarn
yarn add @vue/composition-apiCDN
<script src="https://unpkg.com/@vue/composition-api/dist/vue-composition-api.umd.js"></script>By using the global variable window.vueCompositionApi
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.
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 createComponent:
import { createComponent } from '@vue/composition-api';
const Component = createComponent({
// type inference enabled
});
const Component = {
// this will NOT have type inference,
// because TypeScript can't tell this is options for a Vue component.
};๐ 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.
// file: shim-tsx.d.ts
import Vue, { VNode } from 'vue';
import { ComponentRenderProxy } from '@vue/composition-api';
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends ComponentRenderProxy {}
interface ElementAttributesProperty {
$props: any; // specify the property name to use
}
interface IntrinsicElements {
[elem: string]: any;
}
}
}Unwrap is not working with Array index.
const state = reactive({
list: [ref(0)],
});
// no unwrap, `.value` is required
state.list[0].value === 0; // true
state.list.push(ref(1));
// no unwrap, `.value` is required
state.list[1].value === 1; // trueconst 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; // trueconst b = reactive({
list: [
{
count: ref(0), // no unwrap!!
},
],
});
// no unwrap for `count`, `.value` is required
b.list[0].count.value === 0; // trueconst a = reactive({
count: ref(0),
});
const b = reactive({
list: [a],
});
// unwrapped
b.list[0].count === 0; // true
b.list.push(
reactive({
count: ref(1),
})
);
// unwrapped
b.list[1].count === 1; // trueThis is an limitation of using Vue.observable in Vue 2.
Vue 3 will return an new proxy object.
onTrack and onTrigger are not available in WatchOptions.
โ Support ย ย ย ย โ Not Supported
โ
String ref && return it from setup():
<template>
<div ref="root"></div>
</template>
<script>
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,
};
},
};
</script>โ
String ref && return it from setup() && Render Function / 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); // <div/>
});
return {
root,
};
},
render() {
// with JSX
return () => <div ref="root" />;
},
};โ Function ref:
<template>
<div :ref="el => root = el"></div>
</template>
<script>
export default {
setup() {
const root = ref(null);
return {
root,
};
},
};
</script>โ Render Function / JSX in setup():
export default {
setup() {
const root = ref(null);
return () =>
h('div', {
ref: root,
});
// with JSX
return () => <div ref={root} />;
},
};If you really want to use template refs in this case, you can access vm.$refs via SetupContext.refs.
โ ๏ธ Warning: TheSetupContext.refswon't exist inVue 3.0.@vue/composition-apiprovide it as a workaround here.
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); // <div/>
});
return () =>
h('div', {
ref: 'root',
});
// with JSX
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[] };
}
}