From 7e6598cddebfc2c7ec307838b3eae8a1fcc0ce8b Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Sat, 20 Jun 2020 21:26:40 +0800
Subject: [PATCH 01/14] docs: update readme
---
README.md | 89 ++++++++++++++++++++++++-------------------------------
1 file changed, 38 insertions(+), 51 deletions(-)
diff --git a/README.md b/README.md
index 5af16bab..ab4d7de7 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,19 @@
-# Vue Composition API
+# @vue/composition-api
-Vue 2 plugin for **Composition API** in Vue 3.
+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/workflow/status/vuejs/composition-api/Build%20&%20Test)](https://github.com/vuejs/composition-api/actions?query=workflow%3A%22Build+%26+Test%22)
-English | [**中文文档**](./README.zh-CN.md) / [**Composition API RFC**](https://composition-api.vuejs.org/)
+English | [中文](./README.zh-CN.md) · [**Composition API Docs**](https://composition-api.vuejs.org/)
+
-**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](#Installation)
-- [Usage](#Usage)
-- [TypeScript](#TypeScript)
- - [TSX](#tsx)
-- [Limitations](#Limitations)
-- [Changelog](https://github.com/vuejs/composition-api/blob/master/CHANGELOG.md)
-
-# Installation
-
-**npm**
+## Installation
```bash
npm install @vue/composition-api
-```
-
-**yarn**
-
-```bash
+# or
yarn add @vue/composition-api
```
@@ -41,9 +23,9 @@ yarn add @vue/composition-api
```
-By using the global variable `window.vueCompositionApi`
+The package will be exposed to global variable `window.vueCompositionApi`
-# Usage
+## Usage
You must install `@vue/composition-api` via `Vue.use()` before using other APIs:
@@ -54,28 +36,28 @@ import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
```
-After installing the plugin you can use the [Composition API](https://vue-composition-api-rfc.netlify.com/) to compose your component.
+After installing the plugin you can use the [Composition API](https://composition-api.vuejs.org/) to compose your component.
-# TypeScript
+## TypeScript Support
-**This plugin requires TypeScript version >3.5.1. If you are using vetur, make sure to set `vetur.useWorkspaceDependencies` to `true`.**
+> TypeScript version **>3.5.1** 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';
-const Component = defineComponent({
+const ComponentA = defineComponent({
// type inference enabled
-});
+})
-const Component = {
+const ComponentB = {
// this will NOT have type inference,
// because TypeScript can't tell this is options for a Vue component.
-};
+}
```
-## TSX
+### TSX
:rocket: An Example [Repository](https://github.com/liximomo/vue-composition-api-tsx-example) with TS and TSX support is provided to help you start.
@@ -102,13 +84,23 @@ declare global {
}
```
-# Limitations
+## Limitations
+
+> :white_check_mark:
+> Support :x: Not Supported
+
+### Performance Impact
+
+Due the the limitation of Vue2's public API. `@vue/composition-api` inevitably introduced some extract costs. This should not concern you in most of the cases.
-## `Ref` Unwrap
+You can check the [benchmarks](https://antfu.github.io/vue-composition-api-benchmark-results/) that comparing with Vue 2's option API and vue-next.
-`Unwrap` is not working with Array index.
-### **Should not** store `ref` as a **direct** child of `Array`:
+### `Ref` Unwrap
+
+:x: `Unwrap` is not working with Array index.
+
+#### **Should NOT** store `ref` as a **direct** child of `Array`:
```js
const state = reactive({
@@ -122,7 +114,7 @@ state.list.push(ref(1));
state.list[1].value === 1; // true
```
-### **Should not** use `ref` in a plain object when working with `Array`:
+#### **Should NOT** use `ref` in a plain object when working with `Array`:
```js
const a = {
@@ -149,7 +141,7 @@ const b = reactive({
b.list[0].count.value === 0; // true
```
-### **Should** always use `ref` in a `reactive` when working with `Array`:
+#### **Should** always use `ref` in a `reactive` when working with `Array`:
```js
const a = reactive({
@@ -170,23 +162,18 @@ b.list.push(
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.
+### :warning: `reactive` ***mutates*** the original object
----
+`reactive` uses `Vue.observable` underneath which will ***mutate*** the original object.
-## `watch()` API
+> :bulb: Vue 3 will return an new proxy object.
-`onTrack` and `onTrigger` are not available in `WatchOptions`.
----
+### `watch()` API
-## Template Refs
+:x: `onTrack` and `onTrigger` are not available in `WatchOptions`.
-> :white_check_mark:
-> Support :x: Not Supported
+### Template Refs
:white_check_mark:
String ref && return it from `setup()`:
From 1878f00478e0befc1d35874167a71d71dd436753 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Sat, 20 Jun 2020 21:54:01 +0800
Subject: [PATCH 02/14] docs: update
---
README.md | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
index ab4d7de7..fb02202f 100644
--- a/README.md
+++ b/README.md
@@ -7,8 +7,6 @@ Vue 2 plugin for **Composition API**
English | [中文](./README.zh-CN.md) · [**Composition API Docs**](https://composition-api.vuejs.org/)
-
-
## Installation
```bash
@@ -27,22 +25,21 @@ The package will be exposed to global variable `window.vueCompositionApi`
## Usage
-You must install `@vue/composition-api` via `Vue.use()` before using other APIs:
+You must install `@vue/composition-api` 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';
+import Vue from 'vue'
+import VueCompositionApi from '@vue/composition-api'
-Vue.use(VueCompositionApi);
+Vue.use(VueCompositionApi)
```
-After installing the plugin you can use the [Composition API](https://composition-api.vuejs.org/) to compose your component.
## TypeScript Support
> TypeScript version **>3.5.1** is required
-To let TypeScript properly infer types inside Vue component options, you need to define components with `defineComponent`:
+To let TypeScript properly infer types inside Vue component options, you need to define components with `defineComponent`
```ts
import { defineComponent } from '@vue/composition-api';
@@ -91,9 +88,9 @@ declare global {
### Performance Impact
-Due the the limitation of Vue2's public API. `@vue/composition-api` inevitably introduced some extract costs. This should not concern you in most of the cases.
+Due the the limitation of Vue2's public API. `@vue/composition-api` inevitably introduced some extract costs.
-You can check the [benchmarks](https://antfu.github.io/vue-composition-api-benchmark-results/) that comparing with Vue 2's option API and vue-next.
+You can check the [benchmark results](https://antfu.github.io/vue-composition-api-benchmark-results/) for more details.
### `Ref` Unwrap
@@ -295,7 +292,7 @@ import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
-declare module '@vue/composition-api/dist/component/component' {
+declare module '@vue/composition-api' {
interface SetupContext {
readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] };
}
From 01a036f4598b6a698826558a63451c48badd7778 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Sun, 21 Jun 2020 23:53:48 +0800
Subject: [PATCH 03/14] docs: update CDN guide, resolve #161
---
README.md | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index fb02202f..2273bdc4 100644
--- a/README.md
+++ b/README.md
@@ -9,13 +9,29 @@ English | [中文](./README.zh-CN.md) · [**Composition API Docs**](https://comp
## Installation
+### NPM
+
```bash
npm install @vue/composition-api
# or
yarn add @vue/composition-api
```
-**CDN**
+You must install `@vue/composition-api` 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
+// in components
+import { ref, reactive } from '@vue/composition-api'
+```
+
+### CDN
```html
@@ -23,15 +39,14 @@ yarn add @vue/composition-api
The package will be exposed to global variable `window.vueCompositionApi`
-## Usage
-
-You must install `@vue/composition-api` 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'
+// install the plugin
+Vue.use(vueCompositionApi.default)
+```
-Vue.use(VueCompositionApi)
+```js
+// use the APIs
+const { ref, reactive } = vueCompositionApi
```
From 1c52d2f8a32e8119d0ea8dff693eb86932ae0d29 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Mon, 22 Jun 2020 01:32:27 +0800
Subject: [PATCH 04/14] chore: update JSX/TSX doc, close #91
---
README.md | 27 ++-------------------------
1 file changed, 2 insertions(+), 25 deletions(-)
diff --git a/README.md b/README.md
index 2273bdc4..8da2553e 100644
--- a/README.md
+++ b/README.md
@@ -69,32 +69,9 @@ const ComponentB = {
}
```
-### TSX
+### JSX/TSX
-:rocket: An Example [Repository](https://github.com/liximomo/vue-composition-api-tsx-example) with TS and TSX support is provided to help you start.
-
-To support TSX, create a declaration file with 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 {
- // 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;
- }
- }
-}
-```
+To make JSX/TSX work with `@vue/composition-api`, check out [babel-preset-vca-jsx](https://github.com/luwanquan/babel-preset-vca-jsx) by [@luwanquan](https://github.com/luwanquan).
## Limitations
From 65b4ca7bda210a9e62aaa3415b49def519746798 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Mon, 22 Jun 2020 13:43:20 +0800
Subject: [PATCH 05/14] docs: clean up
---
README.md | 106 +++++++++++++++++++++++++++---------------------------
1 file changed, 53 insertions(+), 53 deletions(-)
diff --git a/README.md b/README.md
index 2273bdc4..f78efedf 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@ const { ref, reactive } = vueCompositionApi
To let TypeScript properly infer types inside Vue component options, you need to define components with `defineComponent`
```ts
-import { defineComponent } from '@vue/composition-api';
+import { defineComponent } from '@vue/composition-api'
const ComponentA = defineComponent({
// type inference enabled
@@ -77,8 +77,8 @@ To support TSX, create a declaration file with following content in your project
```ts
// file: shim-tsx.d.ts
-import Vue, { VNode } from 'vue';
-import { ComponentRenderProxy } from '@vue/composition-api';
+import Vue, { VNode } from 'vue'
+import { ComponentRenderProxy } from '@vue/composition-api'
declare global {
namespace JSX {
@@ -87,10 +87,10 @@ declare global {
// tslint:disable no-empty-interface
interface ElementClass extends ComponentRenderProxy {}
interface ElementAttributesProperty {
- $props: any; // specify the property name to use
+ $props: any // specify the property name to use
}
interface IntrinsicElements {
- [elem: string]: any;
+ [elem: string]: any
}
}
}
@@ -117,13 +117,13 @@ You can check the [benchmark results](https://antfu.github.io/vue-composition-ap
```js
const state = reactive({
list: [ref(0)],
-});
+})
// no unwrap, `.value` is required
-state.list[0].value === 0; // true
+state.list[0].value === 0 // true
-state.list.push(ref(1));
+state.list.push(ref(1))
// no unwrap, `.value` is required
-state.list[1].value === 1; // true
+state.list[1].value === 1 // true
```
#### **Should NOT** use `ref` in a plain object when working with `Array`:
@@ -131,13 +131,13 @@ state.list[1].value === 1; // true
```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
+b.list[0].count.value === 0 // true
```
```js
@@ -147,10 +147,10 @@ const b = reactive({
count: ref(0), // no unwrap!!
},
],
-});
+})
// no unwrap for `count`, `.value` is required
-b.list[0].count.value === 0; // true
+b.list[0].count.value === 0 // true
```
#### **Should** always use `ref` in a `reactive` when working with `Array`:
@@ -158,20 +158,20 @@ b.list[0].count.value === 0; // true
```js
const a = reactive({
count: ref(0),
-});
+})
const b = reactive({
list: [a],
-});
+})
// unwrapped
-b.list[0].count === 0; // true
+b.list[0].count === 0 // true
b.list.push(
reactive({
count: ref(1),
})
-);
+)
// unwrapped
-b.list[1].count === 1; // true
+b.list[1].count === 1 // true
```
### :warning: `reactive` ***mutates*** the original object
@@ -198,18 +198,18 @@ String ref && return it from `setup()`:
```
@@ -219,22 +219,22 @@ String ref && return it from `setup()` && Render Function / JSX:
```jsx
export default {
setup() {
- const root = ref(null);
+ const root = ref(null)
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
- console.log(root.value); //
- });
+ console.log(root.value) //
+ })
return {
root,
- };
+ }
},
render() {
// with JSX
- return () => ;
+ return () =>
},
-};
+}
```
:x: Function ref:
@@ -247,13 +247,13 @@ export default {
```
@@ -262,17 +262,17 @@ export default {
```jsx
export default {
setup() {
- const root = ref(null);
+ const root = ref(null)
return () =>
h('div', {
ref: root,
- });
+ })
// with JSX
- return () => ;
+ return () =>
},
-};
+}
```
If you really want to use template refs in this case, you can access `vm.$refs` via `SetupContext.refs`.
@@ -282,34 +282,34 @@ If you really want to use template refs in this case, you can access `vm.$refs`
```js
export default {
setup(initProps, setupContext) {
- const refs = setupContext.refs;
+ const refs = setupContext.refs
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
- console.log(refs.root); //
- });
+ console.log(refs.root) //
+ })
return () =>
h('div', {
ref: 'root',
- });
+ })
// with JSX
- return () => ;
+ return () =>
},
-};
+}
```
You may also need to augment the `SetupContext` when working with TypeScript:
```ts
-import Vue from 'vue';
-import VueCompositionApi from '@vue/composition-api';
+import Vue from 'vue'
+import VueCompositionApi from '@vue/composition-api'
-Vue.use(VueCompositionApi);
+Vue.use(VueCompositionApi)
declare module '@vue/composition-api' {
interface SetupContext {
- readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] };
+ readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] }
}
}
```
@@ -319,19 +319,19 @@ declare module '@vue/composition-api' {
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';
+import { onServerPrefetch } from '@vue/composition-api'
export default {
setup (props, { ssrContext }) {
- const result = ref();
+ const result = ref()
onServerPrefetch(async () => {
- result.value = await callApi(ssrContext.someId);
- });
+ result.value = await callApi(ssrContext.someId)
+ })
return {
result,
- };
+ }
},
-};
+}
```
From ff0143e42e39dd29452f36ec97b9a4b99ca6cda4 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Mon, 22 Jun 2020 23:02:40 +0800
Subject: [PATCH 06/14] docs: guide users to use versioned CDN (#397)
---
README.md | 15 +++++++++++----
README.zh-CN.md | 14 ++++----------
package.json | 4 +++-
scripts/update-readme.js | 29 +++++++++++++++++++++++++++++
4 files changed, 47 insertions(+), 15 deletions(-)
create mode 100644 scripts/update-readme.js
diff --git a/README.md b/README.md
index 782eeb37..a6364eca 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ npm install @vue/composition-api
yarn add @vue/composition-api
```
-You must install `@vue/composition-api` via `Vue.use()` before you can use the [Composition API](https://composition-api.vuejs.org/) to compose your component.
+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'
@@ -27,17 +27,24 @@ Vue.use(VueCompositionApi)
```
```js
-// in components
+// 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
+Add the following lines in your `` to import Vue and `@vue/composition-api`.
+
+
```html
-
+
+
```
+
-The package will be exposed to global variable `window.vueCompositionApi`
+`@vue/composition-api` will be exposed to global variable `window.vueCompositionApi` and you have to install it before using the APIs.
```js
// install the plugin
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 157ab140..c790c759 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -11,15 +11,6 @@ Vue 2 插件用于提供 Vue 3 中的 **组合式 API**.
---
-# 导航
-
-- [安装](#安装)
-- [使用](#使用)
-- [TypeScript](#TypeScript)
- - [TSX](#tsx)
-- [限制](#限制)
-- [更新日志](https://github.com/vuejs/composition-api/blob/master/CHANGELOG.md)
-
# 安装
**npm**
@@ -36,9 +27,12 @@ yarn add @vue/composition-api
**CDN**
+
```html
-
+
+
```
+
通过全局变量 `window.vueCompositionApi` 来使用。
diff --git a/package.json b/package.json
index ddb0d457..d6205506 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
},
"main": "dist/vue-composition-api.js",
"umd:main": "dist/vue-composition-api.umd.js",
+ "browser": "dist/vue-composition-api.umd.js",
"module": "dist/vue-composition-api.module.js",
"typings": "dist/index.d.ts",
"author": {
@@ -31,10 +32,11 @@
"test": "yarn test-dts && yarn test-unit",
"test-unit": "cross-env NODE_ENV=test jest",
"test-dts": "tsc -p ./test-dts/tsconfig.json && yarn build && tsc -p ./test-dts/tsconfig.build.json",
+ "update-readme": "node ./scripts/update-readme.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"prepublish": "yarn test",
"postpublish": "yarn release-gh",
- "version": "yarn changelog && git add CHANGELOG.md",
+ "version": "yarn changelog && yarn update-readme && git add CHANGELOG.md README.*",
"release": "yarn version && git push --follow-tags && yarn publish --non-interactive",
"release-gh": "conventional-github-releaser -p angular"
},
diff --git a/scripts/update-readme.js b/scripts/update-readme.js
new file mode 100644
index 00000000..364b5a9c
--- /dev/null
+++ b/scripts/update-readme.js
@@ -0,0 +1,29 @@
+const { promises: fs } = require('fs')
+const path = require('path')
+const { version } = require('../package.json')
+
+const files = ['../README.md', '../README.zh-CN.md']
+
+const MakeLinks = (version, vueVersion = '2.6') =>
+ `
+\`\`\`html
+
+
+\`\`\`
+`
+
+;(async () => {
+ const links = MakeLinks(version)
+
+ for (const file of files) {
+ const filepath = path.resolve(__dirname, file)
+ const raw = await fs.readFile(filepath, 'utf-8')
+
+ const updated = raw.replace(
+ /([\s\S]*)/g,
+ `${links}`
+ )
+
+ await fs.writeFile(filepath, updated, 'utf-8')
+ }
+})()
From b11f14cce6137a2ab735bb606170f8968b124749 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Mon, 22 Jun 2020 23:38:04 +0800
Subject: [PATCH 07/14] docs: update
---
README.md | 36 ++++++++++++++++--------------------
1 file changed, 16 insertions(+), 20 deletions(-)
diff --git a/README.md b/README.md
index a6364eca..206cd254 100644
--- a/README.md
+++ b/README.md
@@ -35,7 +35,7 @@ import { ref, reactive } from '@vue/composition-api'
### CDN
-Add the following lines in your `` to import Vue and `@vue/composition-api`.
+Include `@vue/composition-api` after Vue and it will install itself automatically.
```html
@@ -44,15 +44,9 @@ Add the following lines in your `` to import Vue and `@vue/composition-api
```
-`@vue/composition-api` will be exposed to global variable `window.vueCompositionApi` and you have to install it before using the APIs.
+`@vue/composition-api` will be exposed to global variable `window.vueCompositionApi`.
-```js
-// install the plugin
-Vue.use(vueCompositionApi.default)
-```
-
-```js
-// use the APIs
+```ts
const { ref, reactive } = vueCompositionApi
```
@@ -66,14 +60,9 @@ To let TypeScript properly infer types inside Vue component options, you need to
```ts
import { defineComponent } from '@vue/composition-api'
-const ComponentA = defineComponent({
+export default defineComponent({
// type inference enabled
})
-
-const ComponentB = {
- // this will NOT have type inference,
- // because TypeScript can't tell this is options for a Vue component.
-}
```
### JSX/TSX
@@ -259,11 +248,18 @@ export default {
}
```
-If you really want to use template refs in this case, you can access `vm.$refs` via `SetupContext.refs`.
+
+$refs
accessing workaround
+
+
+
> :warning: **Warning**: The `SetupContext.refs` won't exist in `Vue 3.0`. `@vue/composition-api` provide it as a workaround here.
-```js
+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
@@ -287,9 +283,6 @@ You may also need to augment the `SetupContext` when working with TypeScript:
```ts
import Vue from 'vue'
-import VueCompositionApi from '@vue/composition-api'
-
-Vue.use(VueCompositionApi)
declare module '@vue/composition-api' {
interface SetupContext {
@@ -298,6 +291,9 @@ declare module '@vue/composition-api' {
}
```
+
+
+
## 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.
From a1792de1f5ff9f2e4d45fadeadebee7b04d71b93 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Tue, 23 Jun 2020 13:06:08 +0800
Subject: [PATCH 08/14] BREAKING CHANGE: drop createComponent (#398)
---
src/component/component.ts | 40 ------------------------------
src/component/index.ts | 1 -
src/index.ts | 1 -
test/types/defineComponent.spec.ts | 35 --------------------------
4 files changed, 77 deletions(-)
diff --git a/src/component/component.ts b/src/component/component.ts
index 8751a22b..c08d657e 100644
--- a/src/component/component.ts
+++ b/src/component/component.ts
@@ -119,43 +119,3 @@ export function defineComponent<
export function defineComponent(options: any) {
return options as any
}
-
-// overload 1: object format with no props
-export function createComponent(
- options: ComponentOptionsWithoutProps
-): VueProxy
-// overload 2: object format with array props declaration
-// props inferred as { [key in PropNames]?: any }
-// return type is for Vetur and TSX support
-export function createComponent<
- PropNames extends string,
- RawBindings = Data,
- PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
->(
- // prettier-ignore
- options: (
- ComponentOptionsWithArrayProps) &
- Omit, keyof ComponentOptionsWithProps>
-): VueProxy, RawBindings>
-// overload 3: object format with object props declaration
-// see `ExtractPropTypes` in ./componentProps.ts
-export function createComponent<
- Props,
- RawBindings = Data,
- PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
->(
- // prettier-ignore
- options: (
- // prefer the provided Props, otherwise infer it from PropsOptions
- HasDefined extends true
- ? ComponentOptionsWithProps
- : ComponentOptionsWithProps) &
- Omit, keyof ComponentOptionsWithProps>
-): VueProxy
-// implementation, deferring to defineComponent, but logging a warning in dev mode
-export function createComponent(options: any) {
- if (__DEV__) {
- Vue.util.warn('`createComponent` has been renamed to `defineComponent`.')
- }
- return defineComponent(options)
-}
diff --git a/src/component/index.ts b/src/component/index.ts
index a880a467..21217b8b 100644
--- a/src/component/index.ts
+++ b/src/component/index.ts
@@ -1,6 +1,5 @@
export {
Data,
- createComponent,
defineComponent,
SetupFunction,
SetupContext,
diff --git a/src/index.ts b/src/index.ts
index c891f3d1..bea3a2f5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -24,7 +24,6 @@ export default plugin
export { default as createElement } from './createElement'
export { SetupContext }
export {
- createComponent,
defineComponent,
ComponentRenderProxy,
PropType,
diff --git a/test/types/defineComponent.spec.ts b/test/types/defineComponent.spec.ts
index d4fe4b31..21f6e62f 100644
--- a/test/types/defineComponent.spec.ts
+++ b/test/types/defineComponent.spec.ts
@@ -1,5 +1,4 @@
import {
- createComponent,
defineComponent,
createElement as h,
ref,
@@ -217,38 +216,4 @@ describe('defineComponent', () => {
})
})
})
-
- describe('retro-compatible with createComponent', () => {
- it('should still work and warn', () => {
- const warn = jest
- .spyOn(global.console, 'error')
- .mockImplementation(() => null)
- const Child = createComponent({
- props: { msg: String },
- setup(props) {
- return () => h('span', props.msg)
- },
- })
-
- const App = createComponent({
- setup() {
- const msg = ref('hello')
- return () =>
- h('div', [
- h(Child, {
- props: {
- msg: msg.value,
- },
- }),
- ])
- },
- })
- const vm = new Vue(App).$mount()
- expect(vm.$el.querySelector('span').textContent).toBe('hello')
- expect(warn.mock.calls[0][0]).toMatch(
- '[Vue warn]: `createComponent` has been renamed to `defineComponent`.'
- )
- warn.mockRestore()
- })
- })
})
From 23e90f56d1757d1940f20346e6c5f06e8be2343d Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Tue, 23 Jun 2020 13:06:42 +0800
Subject: [PATCH 09/14] BREAKING CHANGE: rename createElement to h (#400)
---
src/apis/computed.ts | 4 ++--
src/apis/inject.ts | 4 ++--
src/apis/lifecycle.ts | 8 ++++++--
src/apis/watch.ts | 4 ++--
src/createElement.ts | 6 +++---
src/helper.ts | 4 ++--
src/index.ts | 10 ++++------
src/runtimeContext.ts | 2 +-
src/setup.ts | 4 ++--
test/setup.spec.js | 2 +-
test/setupContext.spec.js | 2 +-
test/templateRefs.spec.js | 2 +-
test/types/defineComponent.spec.ts | 2 +-
test/v3/runtime-core/apiLifecycle.spec.ts | 2 +-
14 files changed, 29 insertions(+), 27 deletions(-)
diff --git a/src/apis/computed.ts b/src/apis/computed.ts
index bdc2c856..7edda5c7 100644
--- a/src/apis/computed.ts
+++ b/src/apis/computed.ts
@@ -1,4 +1,4 @@
-import { getCurrentVue, getCurrentVM } from '../runtimeContext'
+import { getCurrentVue, getCurrentInstance } from '../runtimeContext'
import { createRef, Ref } from '../reactivity'
import { defineComponentInstance } from '../helper'
import { warn } from '../utils'
@@ -22,7 +22,7 @@ export function computed(options: Option): WritableComputedRef
export function computed(
options: Option['get'] | Option
): ComputedRef | WritableComputedRef {
- const vm = getCurrentVM()
+ const vm = getCurrentInstance()
let get: Option['get'], set: Option['set'] | undefined
if (typeof options === 'function') {
get = options
diff --git a/src/apis/inject.ts b/src/apis/inject.ts
index 9b8e533b..82f504cc 100644
--- a/src/apis/inject.ts
+++ b/src/apis/inject.ts
@@ -1,7 +1,7 @@
import { ComponentInstance } from '../component'
import { currentVMInFn } from '../helper'
import { hasOwn, warn } from '../utils'
-import { getCurrentVM } from '../runtimeContext'
+import { getCurrentInstance } from '../runtimeContext'
const NOT_FOUND = {}
export interface InjectionKey extends Symbol {}
@@ -48,7 +48,7 @@ export function inject(
return defaultValue
}
- const vm = getCurrentVM()
+ const vm = getCurrentInstance()
if (vm) {
const val = resolveInject(key, vm)
if (val !== NOT_FOUND) {
diff --git a/src/apis/lifecycle.ts b/src/apis/lifecycle.ts
index 62457d1b..b7467fc4 100644
--- a/src/apis/lifecycle.ts
+++ b/src/apis/lifecycle.ts
@@ -1,6 +1,10 @@
import { VueConstructor } from 'vue'
import { ComponentInstance } from '../component'
-import { getCurrentVue, setCurrentVM, getCurrentVM } from '../runtimeContext'
+import {
+ getCurrentVue,
+ setCurrentVM,
+ getCurrentInstance,
+} from '../runtimeContext'
import { currentVMInFn } from '../helper'
const genName = (name: string) => `on${name[0].toUpperCase() + name.slice(1)}`
@@ -26,7 +30,7 @@ function injectHookOption(
function wrapHookCall(vm: ComponentInstance, fn: Function) {
return (...args: any) => {
- let preVm = getCurrentVM()
+ let preVm = getCurrentInstance()
setCurrentVM(vm)
try {
return fn(...args)
diff --git a/src/apis/watch.ts b/src/apis/watch.ts
index a4b94633..0639439c 100644
--- a/src/apis/watch.ts
+++ b/src/apis/watch.ts
@@ -2,7 +2,7 @@ import { ComponentInstance } from '../component'
import { Ref, isRef, isReactive } from '../reactivity'
import { assert, logError, noopFn, warn, isFunction } from '../utils'
import { defineComponentInstance } from '../helper'
-import { getCurrentVM, getCurrentVue } from '../runtimeContext'
+import { getCurrentInstance, getCurrentVue } from '../runtimeContext'
import { WatcherPreFlushQueueKey, WatcherPostFlushQueueKey } from '../symbols'
import { ComputedRef } from './computed'
@@ -95,7 +95,7 @@ function getWatchEffectOption(options?: Partial): WatchOptions {
}
function getWatcherVM() {
- let vm = getCurrentVM()
+ let vm = getCurrentInstance()
if (!vm) {
if (!fallbackVM) {
fallbackVM = defineComponentInstance(getCurrentVue())
diff --git a/src/createElement.ts b/src/createElement.ts
index 42ee20a8..cf3e8c35 100644
--- a/src/createElement.ts
+++ b/src/createElement.ts
@@ -7,7 +7,9 @@ type CreateElement = Vue['$createElement']
let fallbackCreateElement: CreateElement
-const createElement: CreateElement = function createElement(...args: any) {
+export const createElement: CreateElement = function createElement(
+ ...args: any
+) {
if (!currentVM) {
warn('`createElement()` has been called outside of render function.')
if (!fallbackCreateElement) {
@@ -20,5 +22,3 @@ const createElement: CreateElement = function createElement(...args: any) {
return currentVM.$createElement.apply(currentVM, args)
} as any
-
-export default createElement
diff --git a/src/helper.ts b/src/helper.ts
index 97040c04..be5ba135 100644
--- a/src/helper.ts
+++ b/src/helper.ts
@@ -1,10 +1,10 @@
import Vue, { VNode, ComponentOptions, VueConstructor } from 'vue'
import { ComponentInstance } from './component'
-import { currentVue, getCurrentVM } from './runtimeContext'
+import { currentVue, getCurrentInstance } from './runtimeContext'
import { warn } from './utils'
export function currentVMInFn(hook: string): ComponentInstance | null {
- const vm = getCurrentVM()
+ const vm = getCurrentInstance()
if (__DEV__ && !vm) {
warn(
`${hook} is called when there is no active component instance to be ` +
diff --git a/src/index.ts b/src/index.ts
index bea3a2f5..2833d88d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,5 @@
import Vue, { VueConstructor } from 'vue'
-import { Data, SetupFunction, SetupContext } from './component'
+import { Data, SetupFunction } from './component'
import { currentVue } from './runtimeContext'
import { install } from './install'
import { mixin } from './setup'
@@ -21,17 +21,15 @@ if (currentVue && typeof window !== 'undefined' && window.Vue) {
}
export default plugin
-export { default as createElement } from './createElement'
-export { SetupContext }
+export { createElement as h } from './createElement'
+export { getCurrentInstance } from './runtimeContext'
export {
defineComponent,
ComponentRenderProxy,
PropType,
PropOptions,
+ SetupContext,
} from './component'
-// For getting a hold of the interal instance in setup() - useful for advanced
-// plugins
-export { getCurrentVM as getCurrentInstance } from './runtimeContext'
export * from './apis/state'
export * from './apis/lifecycle'
diff --git a/src/runtimeContext.ts b/src/runtimeContext.ts
index f6894377..a0b7b503 100644
--- a/src/runtimeContext.ts
+++ b/src/runtimeContext.ts
@@ -17,7 +17,7 @@ export function setCurrentVue(vue: VueConstructor) {
currentVue = vue
}
-export function getCurrentVM(): ComponentInstance | null {
+export function getCurrentInstance(): ComponentInstance | null {
return currentVM
}
diff --git a/src/setup.ts b/src/setup.ts
index bcb93b7d..365d2c51 100644
--- a/src/setup.ts
+++ b/src/setup.ts
@@ -6,7 +6,7 @@ import {
Data,
} from './component'
import { Ref, isRef, isReactive, markRaw } from './reactivity'
-import { getCurrentVM, setCurrentVM } from './runtimeContext'
+import { getCurrentInstance, setCurrentVM } from './runtimeContext'
import { resolveSlots, createSlotProxy } from './helper'
import { hasOwn, isPlainObject, assert, proxy, warn, isFunction } from './utils'
import { ref } from './apis/state'
@@ -112,7 +112,7 @@ function activateCurrentInstance(
fn: (vm_: ComponentInstance) => any,
onError?: (err: Error) => void
) {
- let preVm = getCurrentVM()
+ let preVm = getCurrentInstance()
setCurrentVM(vm)
try {
return fn(vm)
diff --git a/test/setup.spec.js b/test/setup.spec.js
index 5d0ad820..8199af57 100644
--- a/test/setup.spec.js
+++ b/test/setup.spec.js
@@ -2,7 +2,7 @@ const Vue = require('vue/dist/vue.common.js')
const {
ref,
computed,
- createElement: h,
+ h,
provide,
inject,
reactive,
diff --git a/test/setupContext.spec.js b/test/setupContext.spec.js
index 017af58b..1d33cb55 100644
--- a/test/setupContext.spec.js
+++ b/test/setupContext.spec.js
@@ -1,5 +1,5 @@
const Vue = require('vue/dist/vue.common.js')
-const { ref, watch, createElement: h } = require('../src')
+const { h } = require('../src')
describe('setupContext', () => {
it('should have proper properties', () => {
diff --git a/test/templateRefs.spec.js b/test/templateRefs.spec.js
index 8745a82c..10bbc566 100644
--- a/test/templateRefs.spec.js
+++ b/test/templateRefs.spec.js
@@ -1,5 +1,5 @@
const Vue = require('vue/dist/vue.common.js')
-const { ref, watchEffect, watch, createElement: h } = require('../src')
+const { ref, watchEffect } = require('../src')
describe('ref', () => {
it('should work', (done) => {
diff --git a/test/types/defineComponent.spec.ts b/test/types/defineComponent.spec.ts
index 21f6e62f..709fda70 100644
--- a/test/types/defineComponent.spec.ts
+++ b/test/types/defineComponent.spec.ts
@@ -1,6 +1,6 @@
import {
defineComponent,
- createElement as h,
+ h,
ref,
SetupContext,
PropType,
diff --git a/test/v3/runtime-core/apiLifecycle.spec.ts b/test/v3/runtime-core/apiLifecycle.spec.ts
index f952bdc4..418c282a 100644
--- a/test/v3/runtime-core/apiLifecycle.spec.ts
+++ b/test/v3/runtime-core/apiLifecycle.spec.ts
@@ -4,7 +4,7 @@ import {
onBeforeMount,
onMounted,
ref,
- createElement as h,
+ h,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
From 4c4213d07d89dc43c255e302f4339f7b3a7220c7 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Tue, 23 Jun 2020 13:08:14 +0800
Subject: [PATCH 10/14] BREAKING CHANGE: Change umd exported name to
`VueCompositionAPI` (#399)
---
README.md | 6 +++---
README.zh-CN.md | 10 +++++-----
rollup.config.js | 2 +-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index 206cd254..acc76fbd 100644
--- a/README.md
+++ b/README.md
@@ -21,9 +21,9 @@ You must install `@vue/composition-api` as a plugin via `Vue.use()` before you c
```js
import Vue from 'vue'
-import VueCompositionApi from '@vue/composition-api'
+import VueCompositionAPI from '@vue/composition-api'
-Vue.use(VueCompositionApi)
+Vue.use(VueCompositionAPI)
```
```js
@@ -44,7 +44,7 @@ Include `@vue/composition-api` after Vue and it will install itself automaticall
```
-`@vue/composition-api` will be exposed to global variable `window.vueCompositionApi`.
+`@vue/composition-api` will be exposed to global variable `window.VueCompositionAPI`.
```ts
const { ref, reactive } = vueCompositionApi
diff --git a/README.zh-CN.md b/README.zh-CN.md
index c790c759..ce805743 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -34,7 +34,7 @@ yarn add @vue/composition-api
```
-通过全局变量 `window.vueCompositionApi` 来使用。
+通过全局变量 `window.VueCompositionAPI` 来使用。
# 使用
@@ -42,9 +42,9 @@ yarn add @vue/composition-api
```js
import Vue from 'vue';
-import VueCompositionApi from '@vue/composition-api';
+import VueCompositionAPI from '@vue/composition-api';
-Vue.use(VueCompositionApi);
+Vue.use(VueCompositionAPI);
```
安装插件后,您就可以使用新的 [Composition API](https://vue-composition-api-rfc.netlify.com/) 来开发组件了。
@@ -294,9 +294,9 @@ export default {
```ts
import Vue from 'vue';
-import VueCompositionApi from '@vue/composition-api';
+import VueCompositionAPI from '@vue/composition-api';
-Vue.use(VueCompositionApi);
+Vue.use(VueCompositionAPI);
declare module '@vue/composition-api/dist/component/component' {
interface SetupContext {
diff --git a/rollup.config.js b/rollup.config.js
index 679708c9..6dea1609 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -54,7 +54,7 @@ function genConfig({ outFile, format, mode }) {
vue: 'Vue',
},
exports: 'named',
- name: format === 'umd' ? 'vueCompositionApi' : undefined,
+ name: format === 'umd' ? 'VueCompositionAPI' : undefined,
},
external: ['vue'],
onwarn,
From 56332c174493b6c3cbca4c7517068b60e4f4600d Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Tue, 23 Jun 2020 13:12:03 +0800
Subject: [PATCH 11/14] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index acc76fbd..c7da5b54 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ Include `@vue/composition-api` after Vue and it will install itself automaticall
`@vue/composition-api` will be exposed to global variable `window.VueCompositionAPI`.
```ts
-const { ref, reactive } = vueCompositionApi
+const { ref, reactive } = VueCompositionAPI
```
From a6af7d487a6faf04174a50d7049defe3872a1de3 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Sun, 28 Jun 2020 11:07:39 +0800
Subject: [PATCH 12/14] docs: update Chinese README
---
README.md | 13 +-
README.zh-CN.md | 350 +++++++++++++++++++++++++++++++-----------------
2 files changed, 231 insertions(+), 132 deletions(-)
diff --git a/README.md b/README.md
index ebc92d76..d88b7b81 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,6 @@ Include `@vue/composition-api` after Vue and it will install itself automaticall
```ts
const { ref, reactive } = VueCompositionAPI
```
-
## TypeScript Support
@@ -95,8 +94,7 @@ export default {
## Limitations
-> :white_check_mark:
-> Support :x: Not Supported
+> :white_check_mark: Support :x: Not Supported
### `Ref` Unwrap
@@ -107,15 +105,6 @@ export default {
❌ Should NOT store ref
as a direct child of Array
-You can check the [benchmark results](https://antfu.github.io/vue-composition-api-benchmark-results/) for more details.
-
-
-### `Ref` Unwrap
-
-:x: `Unwrap` is not working with Array index.
-
-#### **Should NOT** store `ref` as a **direct** child of `Array`:
-
```js
const state = reactive({
list: [ref(0)],
diff --git a/README.zh-CN.md b/README.zh-CN.md
index ce805743..3eab32a2 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -1,31 +1,43 @@
-# Vue Composition API
+# @vue/composition-api
Vue 2 插件用于提供 Vue 3 中的 **组合式 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/workflow/status/vuejs/composition-api/Build%20&%20Test)](https://github.com/vuejs/composition-api/actions?query=workflow%3A%22Build+%26+Test%22)
-[**English**](./README.md) | 中文文档 / [**组合式 API RFC**](https://composition-api.vuejs.org/zh)
+[English](./README.md) | 中文 ・ [**组合式 API 文档**](https://composition-api.vuejs.org/zh)
-**请注意:此插件的主要目的是让社区尝试新的API并在其最终确定之前提供反馈。随着RFC的更新,该实现可能包含与RFC有细微的不一致。现阶段,我们暂不建议将此插件用于生产环境。**
----
+## 安装
-# 安装
-
-**npm**
+### NPM
```bash
-npm install @vue/composition-api --save
+npm install @vue/composition-api
+# or
+yarn add @vue/composition-api
```
-**yarn**
+在使用 `@vue/composition-api` 前,必须先先通过 `Vue.use()` 进行安装后方可使用使用新的 [**组合式 API**](https://composition-api.vuejs.org/zh) 进行组件开发。
-```bash
-yarn add @vue/composition-api
+```js
+import Vue from 'vue'
+import VueCompositionAPI from '@vue/composition-api'
+
+Vue.use(VueCompositionAPI)
```
-**CDN**
+```js
+// 使用 API
+import { ref, reactive } from '@vue/composition-api'
+```
+
+> :bulb: 当迁移到 Vue 3 时,只需简单的将 `@vue/composition-api` 替换成 `vue` 即可。你现有的代码几乎无需进行额外的改动。
+
+
+### CDN
+
+在 Vue 之后引入 `@vue/composition-api` ,插件将会自动完成安装。
```html
@@ -34,96 +46,95 @@ yarn add @vue/composition-api
```
-通过全局变量 `window.VueCompositionAPI` 来使用。
-
-# 使用
+`@vue/composition-api` 将会暴露在全局变量 `window.VueCompositionAPI` 中。
-在使用任何 `@vue/composition-api` 提供的能力前,必须先通过 `Vue.use()` 进行安装:
-
-```js
-import Vue from 'vue';
-import VueCompositionAPI from '@vue/composition-api';
-
-Vue.use(VueCompositionAPI);
+```ts
+const { ref, reactive } = VueCompositionAPI
```
-安装插件后,您就可以使用新的 [Composition API](https://vue-composition-api-rfc.netlify.com/) 来开发组件了。
+## TypeScript 支持
-# TypeScript
-
-**本插件要求使用 TypeScript 3.5.1 以上版本,如果你正在使用 `vetur`,请将 `vetur.useWorkspaceDependencies` 设为 `true`。**
+> 本插件要求使用 TypeScript **3.5.1** 或以上版本
为了让 TypeScript 在 Vue 组件选项中正确地推导类型,我们必须使用 `defineComponent` 来定义组件:
```ts
-import { defineComponent } from '@vue/composition-api';
-
-const Component = defineComponent({
- // 启用类型推断
-});
+import { defineComponent } from '@vue/composition-api'
-const Component = {
- // 无法进行选项的类型推断
- // TypeScript 无法知道这是一个 Vue 组件的选项对象
-};
+export default defineComponent({
+ // 类型推断启用
+})
```
-## TSX
+### JSX/TSX
-:rocket: 这里有一个配置好 TS/TSX 支持的[示例仓库](https://github.com/liximomo/vue-composition-api-tsx-example)来帮助你快速开始.
+要使得 `@vue/composition-api` 支持 JSX/TSX,请前往查看由 [@luwanquan](https://github.com/luwanquan) 开发的 Babel 插件[babel-preset-vca-jsx](https://github.com/luwanquan/babel-preset-vca-jsx)。
-要支持 TSX,请创建一个类型定义文件并提供正确的 JSX 定义。内容如下:
+## SSR
-```ts
-// 文件: `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; // 定义要使用的属性名称
- }
- interface IntrinsicElements {
- [elem: string]: any;
+尽管 Vue 3 暂时没有给出确定的 SSR 的 API,这个插件实现了 `onServerPrefetch` 生命周期钩子函数。这个钩子允许你使用在传统 API 中的 `serverPrefetch` 函数。
+
+```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,
}
- }
+ },
}
```
-# 限制
+## 限制
+
+> :white_check_mark: 支持 :x: 不支持
+
-## `Ref` 自动展开 (unwrap)
+### `Ref` 自动展开 (unwrap)
数组索引属性无法进行自动展开:
-### **不要**使用 `Array` 直接存取 `ref` 对象:
+
+
+
+❌ 不要 使用数组直接存取 ref
对象
+
```js
const state = reactive({
list: [ref(0)],
-});
+})
// 不会自动展开, 须使用 `.value`
-state.list[0].value === 0; // true
+state.list[0].value === 0 // true
-state.list.push(ref(1));
+state.list.push(ref(1))
// 不会自动展开, 须使用 `.value`
-state.list[1].value === 1; // true
+state.list[1].value === 1 // true
```
-### **不要**在数组中使用含有 `ref` 的普通对象:
+
+
+
+
+
+❌ 不要 在数组中使用含有 ref
的普通对象
+
+
```js
const a = {
count: ref(0),
-};
+}
const b = reactive({
list: [a], // `a.count` 不会自动展开!!
-});
+})
// `count` 不会自动展开, 须使用 `.value`
b.list[0].count.value === 0; // true
@@ -136,51 +147,47 @@ const b = reactive({
count: ref(0), // 不会自动展开!!
},
],
-});
+})
// `count` 不会自动展开, 须使用 `.value`
b.list[0].count.value === 0; // true
```
-### **应该**总是将 `ref` 存放到 `reactive` 对象中:
+
+
+
+
+
+✅ 在数组中,应该 总是将 ref
存放到 reactive
对象中
+
```js
const a = reactive({
count: ref(0),
-});
+})
const b = reactive({
list: [a],
-});
+})
// 自动展开
-b.list[0].count === 0; // true
+b.list[0].count === 0 // true
b.list.push(
reactive({
count: ref(1),
})
-);
+)
// 自动展开
b.list[1].count === 1; // true
```
-### `reactive` 会返回一个修改过的原始的对象
-
-此行为与 Vue 2 中的 `Vue.observable` 一致
-> Vue 3 中会返回一个新的的代理对象.
-
----
-
-## `watch()` API
-
-不支持 `onTrack` 和 `onTrigger` 选项。
+
----
+### 模板 Refs
-## 模板 Refs
-
-> :white_check_mark: 支持 :x: 不支持
-
-:white_check_mark: 字符串 ref && 从 `setup()` 返回 ref:
+
+
+✅ 字符串 ref && 从 setup()
返回 ref
+
```html
@@ -190,45 +197,59 @@ b.list[1].count === 1; // true
```
-:white_check_mark: 字符串 ref && 从 `setup()` 返回 ref && 渲染函数 / JSX:
+
+
+
+
+
+
+✅ 字符串 ref && 从 setup()
返回 ref && 渲染函数 / JSX
+
```jsx
export default {
setup() {
- const root = ref(null);
+ const root = ref(null)
onMounted(() => {
// 在初次渲染后 DOM 元素会被赋值给 ref
- console.log(root.value); //
- });
+ console.log(root.value) //
+ })
return {
root,
- };
+ }
},
render() {
// 使用 JSX
- return () => ;
+ return () =>
},
-};
+}
```
-:x: 函数 ref:
+
+
+
+
+
+❌ 函数 ref
+
+
```html
@@ -238,69 +259,158 @@ export default {
```
-:x: 渲染函数 / JSX:
+
+
+
+
+
+❌ 在 setup()
中的渲染函数 / JSX
+
```jsx
export default {
setup() {
- const root = ref(null);
+ const root = ref(null)
return () =>
h('div', {
ref: root,
- });
+ })
// 使用 JSX
- return () => ;
+ return () =>
},
-};
+}
```
-如果你依然选择在 `setup()` 中写 `render` 函数,那么你可以使用 `SetupContext.refs` 来访问模板引用,它等价于 Vue 2.x 中的 `this.$refs`:
+
+
+
+
+⚠️ $refs
访问的变通方案
+
+
> :warning: **警告**: `SetupContext.refs` 并不属于 `Vue 3.0` 的一部分, `@vue/composition-api` 将其曝光在 `SetupContext` 中只是临时提供一种变通方案。
+如果你依然选择在 `setup()` 中写 `render` 函数,那么你可以使用 `SetupContext.refs` 来访问模板引用,它等价于 Vue 2.x 中的 `this.$refs`:
+
```js
export default {
setup(initProps, setupContext) {
- const refs = setupContext.refs;
+ const refs = setupContext.refs
onMounted(() => {
// 在初次渲染后 DOM 元素会被赋值给 ref
console.log(refs.root); //
- });
+ })
return () =>
h('div', {
ref: 'root',
- });
+ })
// 使用 JSX
- return () => ;
+ return () =>
},
-};
+}
```
如果项目使用了 TypeScript,你还需要扩展 `SetupContext` 类型:
```ts
-import Vue from 'vue';
-import VueCompositionAPI from '@vue/composition-api';
-
-Vue.use(VueCompositionAPI);
+import Vue from 'vue'
-declare module '@vue/composition-api/dist/component/component' {
+declare module '@vue/composition-api' {
interface SetupContext {
- readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] };
+ readonly refs: { [key: string]: Vue | Element | Vue[] | Element[] }
}
}
```
+
+
+
+### Reactive
+
+
+
+⚠️ reactive()
会返回一个修改过的原始的对象
+
+
+此行为与 Vue 2 中的 `Vue.observable` 一致
+
+> :bulb: 在 Vue 3 中,`reactive()` 会返回一个新的的代理对象.
+
+
+
+
+### Watch
+
+
+
+❌ 不支持 onTrack
和 onTrigger
选项
+
+
+```js
+watch(() => {
+ /* ... */
+}, {
+ immediate: true,
+ onTrack() {}, // 不可用
+ onTrigger() {}, // 不可用
+})
+```
+
+
+
+
+### 缺失的 API
+
+以下在 Vue 3 新引入的 API ,在本插件中暂不适用:
+
+- `readonly`
+- `shallowReadonly`
+- `defineAsyncComponent`
+- `onRenderTracked`
+- `onRenderTriggered`
+- `customRef`
+- `isProxy`
+- `isReadonly`
+- `isVNode`
+
+
+### 在 `data()` 中使用组合式 API
+
+
+
+❌ 在 data()
中使用 ref
, reactive
或其他组合式 API 将不会生效
+
+
+```jsx
+export default {
+ data() {
+ return {
+ // 在模版中会成为 { a: { value: 1 } }
+ a: ref(1)
+ }
+ },
+}
+```
+
+
+
+
+### 性能影响
+
+用于 Vue 2 所提供的公共 API 的限制,`@vue/composition-api` 不可避免地引入了额外的性能开销。在非极端情况下,这并不会对你造成影响。
+
+你可以查看这个 [跑分结果](https://antfu.github.io/vue-composition-api-benchmark-results/) 了解更多信息。
From 391a0d9be338bbc0bc8d9aedaa7fc95e4c0024cc Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Wed, 1 Jul 2020 01:15:12 +0800
Subject: [PATCH 13/14] feat: add createApp (#415)
---
README.md | 21 ++++++++++++++
src/createApp.ts | 53 +++++++++++++++++++++++++++++++++
src/index.ts | 1 +
test/createApp.spec.js | 66 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+)
create mode 100644 src/createApp.ts
create mode 100644 test/createApp.spec.js
diff --git a/README.md b/README.md
index d88b7b81..56b8bc69 100644
--- a/README.md
+++ b/README.md
@@ -369,6 +369,27 @@ watch(() => {
+### createApp
+
+
+
+⚠️ createApp()
is global
+
+
+In Vue 3, `createApp()` is introduced to provide context(plugin, components, etc.) isolation between app instances. Due the 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.use('Bar', Bar)
+```
+
+
+
+
### Missing APIs
The following APIs introduced in Vue 3 are not available in this plugin.
diff --git a/src/createApp.ts b/src/createApp.ts
new file mode 100644
index 00000000..e0f12c77
--- /dev/null
+++ b/src/createApp.ts
@@ -0,0 +1,53 @@
+import type Vue from 'vue'
+import { VueConstructor } from 'vue/types/umd'
+import { getCurrentVue } from './runtimeContext'
+import { warn } from './utils'
+
+export interface App {
+ config: VueConstructor['config']
+ use: VueConstructor['use']
+ mixin: VueConstructor['mixin']
+ component: VueConstructor['component']
+ directive: VueConstructor['directive']
+ mount: Vue['$mount']
+ unmount: Vue['$destroy']
+}
+
+export function createApp(rootComponent: any, rootProps: any = undefined): App {
+ const V = getCurrentVue()!
+
+ let mountedVM: Vue | undefined = undefined
+
+ return {
+ config: V.config,
+ use: V.use.bind(V),
+ mixin: V.mixin.bind(V),
+ component: V.component.bind(V),
+ directive: V.directive.bind(V),
+ mount: (el, hydrating) => {
+ if (!mountedVM) {
+ mountedVM = new V({ propsData: rootProps, ...rootComponent })
+ mountedVM.$mount(el, hydrating)
+ return mountedVM
+ } else {
+ if (__DEV__) {
+ warn(
+ `App has already been mounted.\n` +
+ `If you want to remount the same app, move your app creation logic ` +
+ `into a factory function and create fresh app instances for each ` +
+ `mount - e.g. \`const createMyApp = () => createApp(App)\``
+ )
+ }
+ return mountedVM
+ }
+ },
+ unmount: () => {
+ if (mountedVM) {
+ mountedVM.$destroy()
+ mountedVM = undefined
+ } else if (__DEV__) {
+ warn(`Cannot unmount an app that is not mounted.`)
+ }
+ },
+ }
+}
diff --git a/src/index.ts b/src/index.ts
index 9ffbd2b5..4c3a9088 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -14,6 +14,7 @@ const VueCompositionAPI = {
}
export default VueCompositionAPI
+export { createApp } from './createApp'
export { nextTick } from './nextTick'
export { createElement as h } from './createElement'
export { getCurrentInstance } from './runtimeContext'
diff --git a/test/createApp.spec.js b/test/createApp.spec.js
new file mode 100644
index 00000000..d299be73
--- /dev/null
+++ b/test/createApp.spec.js
@@ -0,0 +1,66 @@
+const Vue = require('vue/dist/vue.common.js')
+const { createApp, defineComponent, ref, h } = require('../src')
+
+describe('createApp', () => {
+ it('should work', async () => {
+ const vm = new Vue({
+ setup() {
+ return {
+ a: ref(1),
+ }
+ },
+ template: '{{a}}
',
+ }).$mount()
+
+ await Vue.nextTick()
+ expect(vm.a).toBe(1)
+ expect(vm.$el.textContent).toBe('1')
+ })
+
+ it('should work with rootProps', async () => {
+ const app = createApp(
+ defineComponent({
+ props: {
+ msg: String,
+ },
+ template: '{{msg}}
',
+ }),
+ {
+ msg: 'foobar',
+ }
+ )
+ const vm = app.mount()
+
+ await Vue.nextTick()
+ expect(vm.$el.textContent).toBe('foobar')
+ })
+
+ it('should work with components', async () => {
+ const Foo = defineComponent({
+ props: {
+ msg: {
+ type: String,
+ required: true,
+ },
+ },
+ template: '{{msg}}
',
+ })
+
+ const app = createApp(
+ defineComponent({
+ props: {
+ msg: String,
+ },
+ template: '',
+ }),
+ {
+ msg: 'foobar',
+ }
+ )
+ app.component('Foo', Foo)
+ const vm = app.mount()
+
+ await Vue.nextTick()
+ expect(vm.$el.textContent).toBe('foobar')
+ })
+})
From 82ab91bab0c3d845dc7948b974cfc8f72caa9d31 Mon Sep 17 00:00:00 2001
From: Anthony Fu
Date: Wed, 1 Jul 2020 01:16:32 +0800
Subject: [PATCH 14/14] BREAKING CHANGE: match dist file naming with vue-next
(#413)
---
index.js | 7 +++++++
package.json | 12 +++++++-----
rollup.config.js | 12 ++++++------
3 files changed, 20 insertions(+), 11 deletions(-)
create mode 100644 index.js
diff --git a/index.js b/index.js
new file mode 100644
index 00000000..bf4ed976
--- /dev/null
+++ b/index.js
@@ -0,0 +1,7 @@
+'use strict'
+
+if (process.env.NODE_ENV === 'production') {
+ module.exports = require('./dist/vue-composition-api.common.prod.js')
+} else {
+ module.exports = require('./dist/vue-composition-api.common.js')
+}
diff --git a/package.json b/package.json
index dc4482fe..84499985 100644
--- a/package.json
+++ b/package.json
@@ -11,10 +11,11 @@
"type": "git",
"url": "git+https://github.com/vuejs/composition-api.git"
},
- "main": "dist/vue-composition-api.js",
- "umd:main": "dist/vue-composition-api.umd.js",
- "browser": "dist/vue-composition-api.umd.js",
- "module": "dist/vue-composition-api.module.js",
+ "main": "index.js",
+ "module": "dist/vue-composition-api.esm.js",
+ "browser": "dist/vue-composition-api.prod.js",
+ "unpkg": "dist/vue-composition-ap.prod.js",
+ "jsdelivr": "dist/vue-composition-api.prod.js",
"typings": "dist/index.d.ts",
"author": {
"name": "liximomo",
@@ -23,7 +24,8 @@
"license": "MIT",
"sideEffects": false,
"files": [
- "dist"
+ "dist",
+ "index.js"
],
"scripts": {
"start": "concurrently \"tsc --emitDeclarationOnly -w\" \"cross-env TARGET=es rollup -c -w\"",
diff --git a/rollup.config.js b/rollup.config.js
index 6dea1609..8fa7f89a 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -7,27 +7,27 @@ import dts from 'rollup-plugin-dts'
const builds = {
'cjs-dev': {
- outFile: 'vue-composition-api.js',
+ outFile: 'vue-composition-api.common.js',
format: 'cjs',
mode: 'development',
},
'cjs-prod': {
- outFile: 'vue-composition-api.min.js',
+ outFile: 'vue-composition-api.common.prod.js',
format: 'cjs',
mode: 'production',
},
'umd-dev': {
- outFile: 'vue-composition-api.umd.js',
+ outFile: 'vue-composition-api.js',
format: 'umd',
mode: 'development',
},
'umd-prod': {
- outFile: 'vue-composition-api.umd.min.js',
+ outFile: 'vue-composition-api.prod.js',
format: 'umd',
mode: 'production',
},
- es: {
- outFile: 'vue-composition-api.module.js',
+ esm: {
+ outFile: 'vue-composition-api.esm.js',
format: 'es',
mode: 'development',
},