Vue using wrong component when there're global and local components with same name but registered with different naming conventions #4434

Closed
fenivana opened this Issue Dec 10, 2016 · 14 comments

Projects

None yet

6 participants

@fenivana

JSFiddle: http://jsfiddle.net/fenivana/3y7hzwg8/

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
  </head>

  <body>
    <div id="app">
      <x-foo/>
    </div>

    <script>
    Vue.component('x-foo', {
      template: '<div>global foo component will be used</div>'
    })

    new Vue({
      el: '#app',

      components: {
        XFoo: {
          template: '<div>local foo component won\'t show</div>'
        }
      }
    })
    </script>
  </body>
</html>
@JounQin
JounQin commented Dec 10, 2016 edited

change it to:

new Vue({
    el: '#app',
    components: {
      'x-foo': {
        template: '<div>local foo component won\'t show</div>'
    }
  }
})

x-foo and XFoo are different, it seems to be just a fallback when x-foo component not found.

@fnlctrl
Member
fnlctrl commented Dec 10, 2016

^ As above

@fnlctrl fnlctrl closed this Dec 10, 2016
@fenivana

I exactly know changing to x-foo can solve the problem, but I think the fallback preference is wrong. It should find all naming conventions in local registered components first, If not found, then look into global components.

@fenivana

@yyx990803 @fnlctrl What do you think?

@fenivana
fenivana commented Dec 10, 2016 edited

And how can I know what naming conventions the third party UI libraries are using? Will my local components with the same name conflict with theirs? Who knows.

@fnlctrl
Member
fnlctrl commented Dec 10, 2016 edited

And how can I know what naming conventions the third party UI libraries are using?

Why would it be relevant? You can always alias them inside the components options.

Consider the reverse scenario, where you want to override a third party component's local component x-foo, with your own globally registered component x-foo.

Anyway, you should always explicitly alias components if there is a potential naming conflict, and never rely on the fallback precedence.

@fenivana
fenivana commented Dec 10, 2016 edited

Why would it be relevant? You can always alias them inside the components options.

The real scenario is, when we use a UI collection set. we simply import it and use it:

import SomeUI from 'some-ui'
Vue.use(SomeUI)

We don't need to care about whether it's registered with kebab-case, camelCase, or TitleCase.

If we register a local component , we simply do:

<template>
  <div>
    <tab-pane>something</tab-pane>
  </div>
</template>

<script>
import TabPane from './TabPane.vue'
export default {
  components: {
    TabPane
  }
}
</script>

But what if SomeUI also has a component named 'tab-pane', and it is registered with:

Vue.component('tab-pane', {...})

Then the local registered component will never be used.

We have to use a longer syntax:

export default {
  component: {
    'tab-pane': TabPane
  }
}

And what you said overriding a thirty UI's local component with a global component is a rare case, it's like a hack. And if it's local component is registered with kebab-case, you'd never had a chance.

And, the vue guide says:

When registering components (or props), you can use kebab-case, camelCase, or TitleCase.
Vue doesn’t care.

And you just told me vue cares about it, and we should care about it too!

@fnlctrl
Member
fnlctrl commented Dec 10, 2016

And you just told me vue cares about it, and we should care about it too!

That's not what I said. Let me quote my words again:

You should always explicitly alias components if there is a potential naming conflict, and never rely on the fallback precedence.

In your case you're creating a component that has the same name of a 3rd party component, which should have been avoided in the first place, since it's you defining the local component and you have full control over its name.

@fenivana

Please don't play with words. What the fact is I registered a component with the wrong naming convention and Vue cares about it.

Please let @yyx990803 to end the dispute.

@fenivana

Yeah, you can say, it's not a bug, it's a feature, doc is wrong, not the code.

@ktsn
Member
ktsn commented Dec 10, 2016 edited

I think this is a bug, camel case and title case component name seems aliases rather than fallback. Practically, we use camel/title case to register local component (with ES6 object shorthand) since JavaScript does not allow kebab case as variable names.

And also, local component should not be overridden by global components. It can easily cause unexpected behavior and break capsulations of third party components.

@LinusBorg LinusBorg reopened this Dec 10, 2016
@defcc
Member
defcc commented Dec 10, 2016

Sounds reasonable, but maybe it will bring a breaking change.

@JounQin
JounQin commented Dec 10, 2016

What about using both of them (<x-foo/> and <XFoo/>) in one template, how could it render? Are they same?

@defcc
Member
defcc commented Dec 10, 2016 edited

@JounQin Here is what happend internally. https://github.com/vuejs/vue/blob/8c0fac699a48ec62b25a94b4083ea1d75c52c236/src/core/util/options.js#L322

const res = assets[id] ||
    // camelCase ID
    assets[camelize(id)] ||
    // Pascal Case ID
    assets[capitalize(camelize(id))]

with [, it will check prototype chain, so first x-foo, then XFoo

So I think it might bring breaking change in some cases if we apply the new resolving strategy.

@yyx990803 yyx990803 closed this in 2afa260 Dec 13, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment