Subscribe on changes!

Incorrectly treating the component tag name as a function with the same name and unexpected calling the function twice

avatar
Sep 27th 2023

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNqNU8Fu2zAM/RXBl7RAbWHoTplrdCt62A7bsG43XzyZidXalCDRaYAi/15KblzXToECAWKR1HuPT+RT8tXabNdDsk5ygs62FUFRohB586mgRnvBP64RynTWICDlkjOxwlPlKFUGd+B8RdpgkcsTwVgc7nM6/pWYywkZH71y2pLwQH1Ia+ZyJO4C1s0ESmyc6cQqk4tM6GH1Zbx5wzRjcTgc8yWyNM9MC+grcXYurgrxFOSGItNC1prt2eofwt6CIqiFqtpW41ZselTh1uq8xAPDct+xgyK5SAYJaVfZ7N4bZGcjZPmS8GWyHkhCjGWFc5k0RNavpVQ18rUaWr1zGQJJtJ285jLpeiTdQVqb7voyu8w+y1p7moYz8F3635lHD45ByuRiQiM5yN2mDrAGB+6jtLNrU+pZakEf2A9sEJtCni3d6O3MkjAOugX3ywY331rDVpvHHzFGroexF9WAejgRv/f7oaffDqKySf/82lugIX179xP2/D0mO1P37cszvJP8AzwOfdA4lH3rsWbZk7qo9nt8YR6Qv/52T4D+2FQQGt2I9fE9wlS+1/qrXHZ74uLJsV+sLm+bHXd3uY9CNbrlUX5d6NlGMtFxZU5gH4ErNNSAm6O9RTo8A7y8gtQ=

Steps to reproduce

In the same Vue file (For example: App.vue): First you import another Vue component as its child component, assuming the name of the child component is StartConversation, like this: import StartConversation from './StartConversation.vue'; And in template, we can use this component name with kebeb-case "start-conversation" as html tag.

Then, you have a function that has the same name as the child components mentioned aboved, like this: const startConversation = () => {console.log('Unexpected call the func')};

When you start the Vue project, you can see "Unexpected call the func" printed twice in the console. In the case of Vue SFC playground (link to minimal reproduction provided before), the start-conversation child component will not be rendered.

What is expected?

Vue child component file name should be distinguished from the function name. Notice that the component tag name is kebeb-case, the file name and the registered component name is PascalCase, and the function name is camelCase.

What is actually happening?

The function is incorrectly executed twice due to the component tag name "start-conversation" and "/start-conversation". Although we can use self-closing tag "start-conversation /" in Vue3, the function will also be executed twice.

System Info

No response

Any additional comments?

No response

avatar
Sep 27th 2023

I think this is the design of script setup 1.

<template>
  <start-conversation></start-conversation>
  <start-conversation/>
  <startConversation/>
  <StartConversation/>
</template>

<script setup>
import StartConversation from './StartConversation.vue';
const startConversation = () => {
};
</script>
return (_ctx, _cache) => {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createVNode(startConversation),
    _createVNode(startConversation),
    _createVNode(startConversation),
    _createVNode(StartConversation)
  ], 64 /* STABLE_FRAGMENT */))
}
}
<template>
  <start-conversation></start-conversation>
  <start-conversation/>
  <startConversation/>
  <StartConversation/>
</template>

<script setup>
// import StartConversation from './StartConversation.vue';
const startConversation = () => {
};
</script>
return (_ctx, _cache) => {
  const _component_StartConversation = _resolveComponent("StartConversation")

  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createVNode(startConversation),
    _createVNode(startConversation),
    _createVNode(startConversation),
    _createVNode(_component_StartConversation)
  ], 64 /* STABLE_FRAGMENT */))
}
}
<template>
  <start-conversation></start-conversation>
  <start-conversation/>
  <startConversation/>
  <StartConversation/>
</template>

<script setup>
import StartConversation from './StartConversation.vue';
//const startConversation = () => {
//};
</script>
return (_ctx, _cache) => {
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createVNode(StartConversation),
    _createVNode(StartConversation),
    _createVNode(StartConversation),
    _createVNode(StartConversation)
  ], 64 /* STABLE_FRAGMENT */))
}
}

By comparison, it can be seen that for 1 and 2, vue will convert

  <start-conversation></start-conversation>
  <start-conversation/>
  <startConversation/>

into lowerCamelCase. So for case 1, I think it is necessary to strictly follow the imported component variable names when writing templates。

avatar
Sep 27th 2023

The reason why the console prints 'Unexpected call the func' is because when the function parameter passed to createVNode is a function, the parameter will be processed as a functional component.

avatar
Sep 28th 2023

Using PascalCase in your component is a workaround