Vue: class attribute ignored on functional components

Created on 29 Jan 2018  ·  11Comments  ·  Source: vuejs/vue

Version

2.5.13

Reproduction link

https://jsfiddle.net/zc3u69af/2/

Steps to reproduce

Create a functional component.

Render it in a parent component with some classes applied to it.

The classes won't be there.

What is expected?

I would have expected that the class attribute would be present in the DOM, like for regular stateful components.

What is actually happening?

The class attribute is lost and does not appear in the DOM.


I think this issue might be related https://github.com/vuejs/vue-loader/issues/1136

Most helpful comment

I notice there's two data properties for classes staticClass and class and they're not inside data.attrs. So, you can use:

<template functional>
  <div
    :class="[
      data.class,
      data.staticClass
    ]"
  />
</template>

All 11 comments

This is expected, you need to pass down the data object yourself:

Vue.component("functional-comp", {
  functional: true,
    render(h, context) {
    return h("div", context.data, "This should be .red");
    }
})

I'm realising there's no note on the docs about this though. I'll create a PR

Understood, thanks very much!

@posva would you happen to know if this is possible with vue-loader?

<!-- in some FunctionalComponent.vue, where should I use data ? -->
<template functional>
  <div>This should be .red</div>
</template>

I haven't written the code that handles functional components in vue-loader, I think it was @blake-newman
So no, sorry, I don't know :(

is there any easy way to "intelligently merge" classes in the same way the docs mention normal components do?

You can do it this way

<template functional>
  <div :class="data.class">This should be .red</div>
</template>

I notice there's two data properties for classes staticClass and class and they're not inside data.attrs. So, you can use:

<template functional>
  <div
    :class="[
      data.class,
      data.staticClass
    ]"
  />
</template>

@VitorLuizC in terms of api - it's bad...

@patriciussanctus Yeap, and same happens to style property.

You can see all data properties on VNodeData type defintion (or just console data).

https://github.com/vuejs/vue/blob/4c98f9de39e18703ec3dbd05b596a1bbc3d0c8e3/types/vnode.d.ts#L44-L47

From the docs one would not expect the need to change the child component. I'm not too familiar with the internals here but from a users perspective being a functional component should not change the way Parent and child components interact.

Render function example:

render(createElement, { data } {
  return createElement(
    'div',
    {
      class: {
        ...(data.staticClass && {
          [data.staticClass]: true,
        })
      },
      attrs: {
        ...data.attrs,
      }
    }
  )
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

guan6 picture guan6  ·  3Comments

finico picture finico  ·  3Comments

paceband picture paceband  ·  3Comments

aviggngyv picture aviggngyv  ·  3Comments

lmnsg picture lmnsg  ·  3Comments