2.5.16
https://github.com/padcom/vue-functional-no-class-passed
npm install
npm start
Functional component is painted in green/red by applying the items
CSS class and color: red
style
The items
CSS class nor style
is not applied
I am mostly using the added class in components for BEM-style annotations where a component is at the same time an element from the point of view of the container and a block from its personal point of view thus allowing me to delegate certain properties to the container, like positioning for example.
I'd like to use that same principle in functional components, for example with transition-group
that has the option to specify the tag
attribute. It works with statefull components but functional components fail to pass the class
and style
properties when rendering.
Please note that the functional components declared in the example repository do contain the v-bind="data.attrs"
and v-on="listeners"
attributes on the root node as described in the documentation.
I think the following example workaround would work:
MyUlFunc.js
import './MyUlFunc.css'
export default {
functional: true,
render(h, context) {
const data = {
...context.data,
props: {
...context.props,
tag: 'ul',
name: 'slide'
}
}
return h('transition-group', data, context.children)
}
}
MyUlFunc.css
.slide-move {
transition: transform 1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
This will render everything that I need regardless of #7557. With that I think a workaround exists but it still would be great to be able to do that in an SFC.
This would also work in an SFC but it is ugly:
<template functional>
<div v-bind="data.attrs" :class="data.staticClass" :style="data.staticStyle">
Functional component
</div>
</template>
Hi, thanks for filling this issue.
Functional components don't share the behavior of automatically applying attributes/classes/styles as stateful components, which has been documented here:
On normal components, attributes not defined as props are automatically added to the root element of the component, replacing or intelligently merging with any existing attributes of the same name.
Functional components, however, require you to explicitly define this behavior
Skipping the auto binding behavior would remove the performance overhead of always merging classes/styles/attirbutes on normal components. This is how functional components are made to be fast, by design. What you're using in the last comment is actually the correct way, and not a workaround.
... but it's ugly :(
Btw - there is nothing about passing on class and style to the functional component and what's even more annoying it does work with regular functional component, written in JavaScript as depicted in the previous example. Can't you at least make that the functional components behave the same without additional plumbing?
now that we have inheritAttrs
, it may be possible in the future to change this behaviour, it's all about flexibility. In the past, templates for functional components wasn't possible, so it made sense to have to pass them in js (and also easier):
render: (h, { data }) => h('div', data, [...])
// jsx
render: (h, { data }) => <div {...data}>...</div>
I was thinking: would it be possible to use a .vue file with a render function such as the one you mentioned? What I am looking for is a single file containing everything (like the SFC do) because I fail to see a point of having a separate .css file just to describe some animation keyframes.
I think I have it! SFC's seem to be very powerful and that I like very much:
<script>
export default {
functional: true,
render: (h, { data, children }) => (
<transition-group { ...data} tag="ul" name="slide">
{ children }
</transition-group>
)
}
</script>
<style>
.slide-move {
transition: transform 1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
</style>
That is very elegant :)
Most helpful comment
This would also work in an SFC but it is ugly: