script-setup unnecessarily exposes vue api
Version
3.0.5
Steps to reproduce
<script setup>
import { defineProps, reactive, watch } from 'vue'
defineProps({
value: String
})
const state = reactive({ count: 0 })
watch(() => state.count, () => {
})
function onFocus(e) {
console.log(e)
}
</script>
is compiled into
const _sfc_main = {
expose: [],
props: {
value: String
},
setup(__props) {
const state = reactive({ count: 0 })
watch(() => state.count, () => {
})
function onFocus(e) {
console.log(e)
}
return { state, onFocus, reactive, watch }
}
What is expected?
Component's setup should not return vue's api functions such as reactive, watch, etc.
What is actually happening?
Compiler unnecessarily exposes vue's api functions.
We can optimize this for vue's own APIs, but that happens for any import, and it does so by design.
in <script setup>
, the template is treated more like an inline render function - everything that's available in setup
is available in the render function / template - which includes all imports, and that can even be useful:
import { capitalize } from 'lodash-es'
props: ['title'],
setup (props) {
return () => <div> { capitalize(props.title) }</div>
}
<template>
<div> {{ capitalize(props.title) }}</div>
</template>
<script setup>
import { defineProps } from 'vue'
import { capitalize } from 'lodash-es'
const props = defineProps()
</script>
From a technical perspective we can optimize the compiler to exclude vue's own imports, but that may lead to situations were people get confused that they can do the above, but not this:
<template>
<child @someEvent="($event) => emit('re-emitted-some-event', toRaw($event))"></child>
</template>
<script setup>
import { toRaw } from 'vue'
</script>
While the above likely doesn't make much sense, and usage of most of the other Vue APIs in the template doesn't either, I'm willing to bet someone can find a scenario that makes sense, and then be confused by this special treatment of Vue's exports compared to others.