Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defineOptions macro in <script setup> #432

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions active-rfcs/0000-define-options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
- Start Date: 2022-02-13
- Target Major Version: 3.x
- Reference Issues: https://github.com/vuejs/core/issues/5218
- Implementation PR: https://github.com/vuejs/core/pull/5738

# Summary

Introduce a macro in script setup, `defineOptions`, to use Options API in `script setup`, specifically to be able to set `name`, `inheritAttrs` and `render` in `script setup`.

# Basic example

```vue
<script setup lang="ts">
import { useSlots } from 'vue'

defineOptions({
name: 'Foo',
inheritAttrs: false
})

// Setup code...
const slots = useSlots()
</script>
```

<details>
<summary>Compiled Output</summary>

```js
const __default__ = {
name: 'Foo',
inheritAttrs: false
}
const setup = () => {
const slots = useSlots()
return { slots }
}
export default Object.assign(__default__, {
setup
})
```

</details>

### JSX in `script-setup`

```vue
<script setup lang="tsx">
defineOptions({
render() {
return <h1>Hello World</h1>
}
})
</script>
```

<details>
<summary>Compiled Output</summary>

With [Babel plugin](https://github.com/vuejs/babel-plugin-jsx).

```js
const __default__ = {
render() {
return h('h1', {}, () => 'Hello World')
}
}
const setup = () => {}
export default Object.assign(__default__, {
setup
})
```

</details>

# Motivation

This proposal is mainly to set the Options API using only `script setup`.

We already have `<script setup>`, but some options still need to be set in normal script tags (such as `name` and `inheritAttrs`). The goal of this proposal is to allow users to avoid script tag at all.

# Detailed design

## Overview

The behavior of `defineOptions` is basically the same as `defineProps`.

- `defineOptions` is **compiler macros** only usable inside `<script setup>`. They do not need to be imported, and are compiled away when `<script setup>` is processed.
- The options passed to `defineOptions` will be hoisted out of setup into module scope. Therefore, the options cannot reference local variables declared in setup scope. Doing so will result in a compile error. However, it _can_ reference imported bindings since they are in the module scope as well.
- The options passed to `defineOptions` cannot contain `props`, `emits` and `expose` options.

# Drawbacks

# Alternatives

# Adoption strategy

This feature is opt-in. Existing SFC usage is unaffected.

# Unresolved questions

## Appendix

### Enabling the Macros

I made a very prototype plugin [unplugin-vue-define-options](https://github.com/sxzz/unplugin-vue-define-options).

It supports Vite, Rollup, Webpack, Vue CLI and esbuild powered by [unplugin](https://github.com/unjs/unplugin).