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

DOM class attribute not rendered properly with functional components #1014

Open
Bartheleway opened this issue Oct 18, 2017 · 9 comments
Open

Comments

@Bartheleway
Copy link

Version

13.3.0

Reproduction link

https://codesandbox.io/s/0vmk6026jl

Steps to reproduce

Create a functional component using the single file way (<template functional><div class="test"></div></template>).
Use that functional component in another component and add the class attribute (<my-cmp class="test2"></my-cmp>)

What is expected?

It should merge the two classes on the root element and provide scope css support

I should get <div class="test test2"></div>

What is actually happening?

The css classes are not merged. It only applies those from the functional component.

I get <div class="test"></div>


This is working if I write my component with only JS.

@yyx990803
Copy link
Member

This is probably not properly documented, but functional components do not have the class/style merging behavior by default, because originally it only supported pure JavaScript render functions, in which you are responsible for fully controlling the classes by binding context.data.class and context.data.staticClass yourself.

We may introduce proper class/style merging for template-based functional component in a patch release.

@Bartheleway
Copy link
Author

Hi, thanks for this precision. The weird thing is that if you inspect the "test2" which is a pure JS functional component, it actually works. So it's like it's a half-working feature ;)

If you look at my implementation of the two functional components, they look pretty similar. I don't know how vue-loader transform the template-based functional component into a pure JS functional component but it seems that it forgot to add context.data as the second parameter of the render function.

@yyx990803
Copy link
Member

test2 is rendering an internal stateful component. (That component is also recreated on the fly for every render, not something you should do.)

@Bartheleway
Copy link
Author

Okay so if I understand correctly, functional component should be leaf components or only have functional components as children (as a best usage practice) ?

@yyx990803
Copy link
Member

It can have stateful child components, but you should not be declaring stateful child components directly in the render function. That creates a different component definition on every render.

@Bartheleway
Copy link
Author

Ok. I did update my example to add extra ways to work with functional component. There still seems to have a non equivalent between the template functional and the pure JS functional component.

I hope this will help dig into the subject :)

@dasDaniel
Copy link

dasDaniel commented Apr 6, 2018

I was stuck on this issue too, rolling out custom solution to work with html template was actually pretty easy for my limited requirements
<div :class="['alert', data.class, data.staticClass].join(' ')" :style="data.style">

the problem is that you can't use v-bind:"data" for static parameters, and there are different types at work (style uses objects, class can use strings, arrays, or objects) so the logic to do it properly is a bit more complex, and AFAIK, you cannot define it in the script, which limits the ability to do complex computations inline.

Of course you can do this with the render functions, and have more logic in there, but then you're not using the templates.

but easier yet is to not use functional components, which in my case (with few components) has little effect.

@pkaminski
Copy link

Thank @dasDaniel, your answer saved the day. Minor correction: AFAICT it should be :style="[data.style, data.staticStyle]".

@mesqueeb
Copy link

mesqueeb commented Jun 7, 2019

Thanks @dasDaniel
this solved my issue of merging classes on functional components:

<template functional>
  <div :class="['alert', data.class, data.staticClass].join(' ')">
  </div>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants