• Stars
    star
    4,176
  • Rank 9,858 (Top 0.3 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created almost 5 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Composition API plugin for Vue 2

@vue/composition-api

Vue 2 plugin for Composition API

npm GitHub Workflow Status Minzipped size

English | 中文Composition API Docs

⚠️ With the release of Vue 2.7, 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

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 to compose your component.

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)
// use the APIs
import { ref, reactive } from '@vue/composition-api'

💡 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.

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/@vue/[email protected]"></script>

@vue/composition-api will be exposed to global variable window.VueCompositionAPI.

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

import { defineComponent } from '@vue/composition-api'

export default defineComponent({
  // type inference enabled
})

JSX/TSX

JSX is now officially supported on vuejs/jsx. You can enable it by following this document. A community maintained version can be found at babel-preset-vca-jsx by @luwanquan.

To support TSX, create a declaration file with the 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 {
    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.

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

Support      Not Supported

Ref Unwrap

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({
  list: [
    reactive({
      count: ref(0),
    }),
  ]
})
// unwrapped
a.list[0].count === 0 // true

a.list.push(
  reactive({
    count: ref(1),
  })
)
// unwrapped
a.list[1].count === 1 // true

Template Refs

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} />
  },
}
⚠️ $refs accessing workaround

⚠️ 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

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" />
  },
}

Reactive

⚠️ reactive() mutates the original object

reactive uses Vue.observable underneath which will mutate the original object.

💡 In Vue 3, it will return a new proxy object.

⚠️ set and del 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.

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 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.

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 and onTrigger are not available in WatchOptions
watch(() => {
    /* ... */
}, {
  immediate: true,
  onTrack() {}, // not available
  onTrigger() {}, // not available
})

createApp

⚠️ createApp() is global

In 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.

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: This ability is provided as a workaround Vue 2, it's not part of the 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

⚠️ shallowReadonly() will create a new object and with the same root properties, new properties added will not be readonly or reactive.

💡 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.
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 property effect set to true instead of a ReactiveEffect.

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:

function isComputed<T>(o: ComputedRef<T> | unknown): o is ComputedRef<T>
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 to data() would not work.
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.
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 for more details.

More Repositories

1

vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
TypeScript
206,615
star
2

awesome-vue

🎉 A curated list of awesome things related to Vue.js
70,860
star
3

core

🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript
43,920
star
4

vue-cli

🛠️ webpack-based tooling for Vue.js Development
JavaScript
29,747
star
5

vuex

🗃️ Centralized State Management for Vue.js.
JavaScript
28,336
star
6

devtools

⚙️ Browser devtools extension for debugging Vue.js applications.
TypeScript
24,243
star
7

vuepress

📝 Minimalistic Vue-powered static site generator
JavaScript
22,293
star
8

vue-router

🚦 The official router for Vue 2
JavaScript
19,008
star
9

pinia

🍍 Intuitive, type safe, light and flexible Store for Vue using the composition api with DevTools support
TypeScript
12,284
star
10

vitepress

Vite & Vue powered static site generator.
TypeScript
10,982
star
11

vue-hackernews-2.0

HackerNews clone built with Vue 2.0, vue-router & vuex, with server-side rendering
JavaScript
10,964
star
12

petite-vue

6kb subset of Vue optimized for progressive enhancement
TypeScript
8,689
star
13

apollo

🚀 Apollo/GraphQL integration for VueJS
TypeScript
5,980
star
14

vue-class-component

ES / TypeScript decorator for class-style Vue components.
TypeScript
5,812
star
15

vetur

Vue tooling for VS Code.
TypeScript
5,721
star
16

language-tools

⚡ High-performance Vue language tooling based-on Volar.js
TypeScript
5,403
star
17

v2.vuejs.org

📄 Documentation for Vue 2
JavaScript
5,051
star
18

vue-loader

📦 Webpack loader for Vue.js components
TypeScript
4,970
star
19

rfcs

RFCs for substantial changes / feature additions to Vue core
4,822
star
20

eslint-plugin-vue

Official ESLint plugin for Vue.js
JavaScript
4,365
star
21

vuefire

🔥 Firebase bindings for Vue.js
TypeScript
3,784
star
22

router

🚦 The official router for Vue.js
TypeScript
3,588
star
23

vue-test-utils

Component Test Utils for Vue 2
JavaScript
3,569
star
24

vue-rx

👁️ RxJS integration for Vue.js.
JavaScript
3,343
star
25

create-vue

🛠️ The recommended way to start a Vite-powered Vue project
Vue
3,297
star
26

docs

📄 Documentation for Vue 3
Vue
2,788
star
27

vue-touch

Hammer.js wrapper for Vue.js
JavaScript
2,728
star
28

vuex-router-sync

Effortlessly keep vue-router and vuex store in sync.
JavaScript
2,523
star
29

vue-hackernews

HackerNews clone with Vue.js
Vue
2,514
star
30

v2.cn.vuejs.org

🇨🇳 Chinese translation for v2.vuejs.org
JavaScript
1,865
star
31

babel-plugin-transform-vue-jsx

babel plugin for vue 2.0 jsx
JavaScript
1,844
star
32

babel-plugin-jsx

JSX for Vue 3
TypeScript
1,668
star
33

vue-syntax-highlight

💡 Sublime Text syntax highlighting for single-file Vue components
1,481
star
34

jsx-vue2

monorepo for Babel / Vue JSX related packages
JavaScript
1,450
star
35

ui

💻 UI components for official Vue organization apps
Vue
1,331
star
36

vue-docs-zh-cn

该项目已不再维护,有劳通过 Vue 官网查阅最新的文档
1,330
star
37

core-vapor

Vue Vapor is a variant of Vue that offers rendering without the Virtual DOM.
TypeScript
1,205
star
38

vueify

Browserify transform for single-file Vue components
JavaScript
1,172
star
39

vue-web-component-wrapper

(Vue 2 only) Wrap a Vue component as a web component / custom element.
JavaScript
1,036
star
40

docs-next-zh-cn

🇨🇳 Chinese translation for v3.vuejs.org
Vue
959
star
41

test-utils

Vue Test Utils for Vue 3
TypeScript
957
star
42

devtools-next

The next iteration of Vue DevTools
TypeScript
882
star
43

roadmap

🗺️ Roadmap for the Vue.js project (archive)
851
star
44

rollup-plugin-vue

Roll .vue files
TypeScript
846
star
45

repl

Vue SFC REPL as a Vue 3 component
TypeScript
799
star
46

vue-jest

Jest Vue transformer
JavaScript
741
star
47

vue-migration-helper

CLI tool to aid in migration from Vue 1.x to 2.0
JavaScript
595
star
48

vue-dev-server

A POC dev server that allows you to import `*.vue` files via native ES modules imports.
TypeScript
572
star
49

vue2-ssr-docs

Vue.js Server-Side Rendering Guide (for Vue 2)
559
star
50

vue-hot-reload-api

🌶️ Hot reload API for Vue components
JavaScript
465
star
51

vue-animated-list

A Vue.js plugin for easily animating `v-for` rendered lists.
JavaScript
462
star
52

vue-next-webpack-preview

JavaScript
427
star
53

vue-eslint-parser

The ESLint custom parser for `.vue` files.
TypeScript
422
star
54

vue-async-data

Async data loading plugin
JavaScript
417
star
55

vue-component-compiler

Compile a single file Vue component into a CommonJS module.
TypeScript
341
star
56

vue-cli-plugin-vue-next

A Vue CLI plugin for trying out vue-next (experimental)
JavaScript
339
star
57

eslint-config-vue

JavaScript
326
star
58

component-compiler-utils

Lower level utilities for compiling Vue single file components
TypeScript
318
star
59

blog

📝 The official Vue.js blog
Vue
296
star
60

vue-test-utils-jest-example

Example project using Jest + vue-test-utils together
JavaScript
296
star
61

tsconfig

Base tsconfig for Vue 3 projects.
280
star
62

vue-template-explorer

Vue template compilation explorer
Vue
263
star
63

events

Source code for the new Vue.js Events page
Vue
252
star
64

vue-codemod

Vue.js codemod scripts
TypeScript
250
star
65

jp.vuejs.org

🇯🇵 Japanese translation for vuejs.org
JavaScript
246
star
66

theme

VitePress theme for vuejs.org.
Vue
217
star
67

v3-migration-guide

Vue 2 -> Vue 3 migration guide
JavaScript
211
star
68

vue-element

register a custom element with Vue.js.
JavaScript
208
star
69

vue-curated

🖼️ The curated Vue packages list
177
star
70

Discussion

Vue.js discussion
166
star
71

vuex-observable

Consume Vuex actions as Observables using RxJS 5
JavaScript
155
star
72

vue-issue-helper

Vue
145
star
73

composition-api-converter

Automatically migrate components to the Function API
JavaScript
145
star
74

babel-preset-vue-app

Babel preset for Vue app.
JavaScript
125
star
75

art

🎨 Artworks
121
star
76

laravel-elixir-vue-2

Laravel Elixir Vue 2.0 support plugin
JavaScript
106
star
77

composition-api-rfc

Vuepress render for the Composition API RFC
JavaScript
106
star
78

vue-router-demos

Live demos for vue-router
Vue
106
star
79

eslint-plugin-vue-libs

Eslint plugin for Vue internal development
JavaScript
105
star
80

vue-test-utils-mocha-webpack-example

Example project using mocha-webpack and vue-test-utils
JavaScript
104
star
81

eslint-config-typescript

eslint-config-typescript for vue projects
JavaScript
103
star
82

babel-preset-vue

Babel preset for transforming Vue JSX.
JavaScript
87
star
83

ecosystem-ci

Vue Ecosystem CI
TypeScript
81
star
84

vue-test-utils-getting-started

Demo project for `vue-test-utils`
JavaScript
81
star
85

vue-webpack-meteor-example

Example using Vue with Meteor, while leveraging the normal Webpack + NPM workflow for your front-end.
Vue
78
star
86

vue-requests

Need a Vue.js module or looking for ideas?
70
star
87

eslint-config-airbnb

ESLint Shareable Configs for Airbnb JavaScript Style Guide in Vue.js Projects
JavaScript
67
star
88

news.vuejs.org

Vue.js News Portal
Vue
66
star
89

vue-curated-client

Official curation list client
Vue
65
star
90

eslint-config-prettier

eslint-config-prettier for vue-cli
JavaScript
61
star
91

vue-template-es2015-compiler

Support a subset of handy ES2015 features in Vue 2.0 templates.
JavaScript
60
star
92

vue-test-utils-typescript-example

Example project using TypeScript, Jest + vue-test-utils together
Vue
59
star
93

create-eslint-config

Utility to setup ESLint in Vue.js projects.
JavaScript
41
star
94

vue-ssr-html-stream

Transform stream to simplify Vue SSR streaming
HTML
40
star
95

eslint-config-standard

ESLint Shareable Configs for JavaScript Standard Style in Vue.js Projects
JavaScript
39
star
96

create-vue-templates

Snapshots of the generated templates of `npm create vue@latest`
Vue
39
star
97

it.vuejs.org

Italian translation for vuejs.org 🇮🇹
JavaScript
35
star
98

systemjs-plugin-vue

SystemJS plugin for Vue single file components
JavaScript
34
star
99

test-utils-docs

Docs for vue-test-utils-next
JavaScript
32
star
100

vue-curated-server

JavaScript
31
star