@morlz/composition-api
v0.3.2-rc4
Published
Provide logic composition capabilities for Vue.
Downloads
24
Maintainers
Readme
Vue Composition API
@vue/composition-api
provides a way to use Vue 3.0
's Composition api in Vue 2.x
.
Navigation
Installation
npm
npm install @vue/composition-api --save
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 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.
};
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.
// 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;
}
}
}
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)],
});
// 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; // true
Should not use ref
in a plain object when working with Array
:
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
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 a reactive
when working with Array
:
const 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; // true
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(() => {
// the DOM element will be assigned to the ref after initial render
console.log(root.value); // <div/>
});
return {
root,
};
},
};
</script>
:white_check_mark:
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" />;
},
};
: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,
});
// 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: Warning: The
SetupContext.refs
won't exist inVue 3.0
.@vue/composition-api
provide 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[] };
}
}