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

use <script setup name="cpnName"> instead of two <script> #5218

Closed
gumingWu opened this issue Jan 7, 2022 · 19 comments · Fixed by #5738
Closed

use <script setup name="cpnName"> instead of two <script> #5218

gumingWu opened this issue Jan 7, 2022 · 19 comments · Fixed by #5738
Labels

Comments

@gumingWu
Copy link

gumingWu commented Jan 7, 2022

What problem does this feature solve?

When I create a component vue file,I will write two script in it,first script maintain the component name,sceond script use script setup syntax,I think it need to be optimized
E.g
before

<script> export default { name: 'ChildCpn' } </script>

after

<script setup name="ChildCpn"></script>

so cool~

What does the proposed API look like?

<script setup name="ChildCpn">
@edison1105
Copy link
Member

edison1105 commented Jan 7, 2022

This might be a good feature.
same as #4997 (comment)

@sxzz
Copy link
Member

sxzz commented Feb 8, 2022

I'm trying to switch Element Plus to script-setup syntax, but this problem is blocking us. As a 3rd party component, we should add a prefix to component name, so we should add name property for every Vue SFC. If I use script-setup, there's two script tags at the same time. I think it's too ugly and seems to be incompatible with some cases. (such as 已声明“defineComponent”,但从未读取其值。ts(6133))

IMHO, Maybe Vue can provide a marco API called defineOptions. It can set some Options API (name, inheritAttrs...).

Example:

<script setup lang="ts">
defineOptions({
  name: 'Foo',
  inheritAttrs: false,
})

defineProps<Props>()
// ...
</script>

and it transforms to

<script lang="ts">
export default {
  name: 'Foo',
  inheritAttrs: false,
}
</script>

<script lang="ts" setup>
defineProps<Props>()
// ...
</script>

Related issue: element-plus/element-plus#5709 (comment)

UPDATE:
I made a plugin unplugin-vue-define-options to implement this feature

RFC

@Tofandel
Copy link
Contributor

I think I like this proposal better than defineOptions, if <script> behaves like a vue component that accepts props like options that would be amazing, then we could pass options like

<script setup :inerit-attrs="false" name="MyComponent" layout="a custom option">

@joezimjs
Copy link

joezimjs commented Mar 28, 2022

They wrongly closed #5633 as a duplicate of this, so I'm putting this here so it doesn't just disappear and because it's related enough to be in here anyway.

I saw some people on Twitter that noted Vue's general usage of default exports for all components. Some people, and myself to an extent, think that named exports are a better practice, but I love <script setup> too much to give it up for named exports.

So I was thinking about enhancing <script setup> with an additional attribute: name (or namedExport or something like that). We can use it to specify the name it'll be exported as. I originally thought about using it for both the export name and the component name (like you're asking for in this issue, hence using the name attribute), but I think people should be able to set a component name without being required to opt into named exports. So let's assume I'm going to use the namedExport attribute instead of just name so we're not clashing:

E.g.

<script setup namedExport="MyComponent">
// ...
</script>

Would compile to

export const MyComponent = {
    // ...
}

If we want to simplify and combine these attributes into a cohesive bunch we can use name to set the component name and usenamedExport without assigning a value (as if it's a boolean) to indicate that we want to use a named export without having to retype the name of the component:

E.g.

<script setup name="MyComponent" namedExport>
// ...
</script>

Would compile to

export const MyComponent = {
    name: "MyComponent",
    // ...
}

So if you don't want to set a component name, or if you want the exported name and the component name to be different, set namedExport to something, otherwise just use namedExport without a value to get it to derive the name from a name attribute if it exists, or the file name.

<script setup name="ParentGroup.ChildComponent" namedExport="ChildComponent">
// ...
</script>

Would compile to

export const ChildComponent = {
    name: "ParentGroup.ChildComponent",
    // ...
}

@jzfai
Copy link

jzfai commented Apr 20, 2022

When does the official plan to add this function?

#5758

@chencheng365
Copy link

When does the official plan to add this function?
This feature is very much needed in the project

@sxzz
Copy link
Member

sxzz commented Apr 20, 2022

I made a plugin unplugin-vue-define-options to implement this feature, if you really need it.

@gumingWu
Copy link
Author

NOW! I have the new ideas, if I want to write the JSX in <script setup>, maybe vue can supply a new API, like defineTemplate

E.g.

<script lang="ts">
setup() {
    return () => (
        <div></div>
    )
}
</script>

——————

<script setup>
const msg = ref('hi')
defineTemplate(() => (
    <div>{{ msg }}</div>
))
</script>

use this API, the file just need one label

@sxzz
Copy link
Member

sxzz commented Apr 24, 2022

@gumingWu I think we can discuss this API in a new issue.

@gumingWu
Copy link
Author

#5798
@sxzz let's talk in new issue~

@lihanspace
Copy link

I think try not to change <script>, maybe defineName('Foo') is better.

@joezimjs
Copy link

I think try not to change <script>, maybe defineName('Foo') is better.

At the very least, it fits with defineProps and defineEmits, so you're probably right that it's better. To go along with my suggestion about named exports, could we use defineExportName as well?

@lvminjie5201314
Copy link

I think a script tag with name= "XXX" is the best implementation

@rennzhang
Copy link

I support <script name=" xxx" >
Is there any relevant plan?

@yyx990803
Copy link
Member

1693924 automatically infers component name based on filename.

@Mrlilili
Copy link

1693924 automatically infers component name based on filename.

When a component contains multiple subcomponents, the directory structure looks like this:
image
So the name of this component will be index, not OtherHome,this is not good for readability。
If you change index.vue to OtherHome.vue, it will look very strange,And the reference needs to look like this
import OtherHome from '. /OtherHome/OtherHome.vue'.

If it's index.vue, you can just do this
import OtherHome from '. /OtherHome'.

@joezimjs
Copy link

joezimjs commented May 12, 2022

I don't think this should have been closed, because we're all aware that it automatically infers component names. We want to be able to explicitly write them because file name isn't always the most useful.

Anyway, @Mrlilili a way you can handle your situation is to have OtherHome.vue plus an index.js (or .ts obviously) with this:

import OtherHome from './OtherHome'
export default OtherHome

And while that might be annoying to do, it'll help with your problem and it's simple enough to create a tiny code generator to handle most of this.

You also have the separate <script> tag where you can specify the name.

@Tofandel
Copy link
Contributor

Or we need a way to customize (webpack option) how this name is generated with a function that takes the path in param and outputs the name

@jxb4137
Copy link

jxb4137 commented Jul 13, 2022

@github-actions github-actions bot locked and limited conversation to collaborators Sep 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.