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

script-setup unnecessarily exposes vue api #3249

Closed
sqal opened this issue Feb 17, 2021 · 4 comments
Closed

script-setup unnecessarily exposes vue api #3249

sqal opened this issue Feb 17, 2021 · 4 comments
Labels
✨ feature request New feature or request

Comments

@sqal
Copy link
Contributor

sqal commented Feb 17, 2021

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.

@HcySunYang HcySunYang added the ✨ feature request New feature or request label Feb 18, 2021
@little-buddy
Copy link

I think so.

@LinusBorg
Copy link
Member

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.

@dengrc
Copy link

dengrc commented Aug 18, 2021

Double <script>
Don’t need to export, put the first one

<script lang="ts">
import { ref } from 'vue'
</script>
<script setup lang="ts">
const expanded = ref(false)
</script>

@LinusBorg
Copy link
Member

This no longer applies, see this playground's compiled JS output.

@github-actions github-actions bot locked and limited conversation to collaborators Oct 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
✨ feature request New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants
@LinusBorg @sqal @dengrc @HcySunYang @little-buddy and others