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

Possibility to somehow read the "passed" class property #11244

Closed
KingSora opened this issue Mar 25, 2020 · 4 comments
Closed

Possibility to somehow read the "passed" class property #11244

KingSora opened this issue Mar 25, 2020 · 4 comments

Comments

@KingSora
Copy link

What problem does this feature solve?

Good day! I'm the author of the OverlayScrollbars Library.
The library is written in vanilla Javascript and I'm currently providing a Vue wrapper Component for it.
I ran into a issue with the class attribute recently and I need some guidance of someone who has better understanding of the overall structure of Vue.

The setup (minimal example):
In Vue I'm rendering a div:

Then I'm initializing the library in the mounted hook

mounted() {
    myLibrary(this.$el);
}

The library is adding internally classes to the already rendered div, so the virtual node still looks like this:

<div class="my-host"></div>

But the real DOM element might look like this:

<div class="my-host my-host-option-a my-host-option-b xyz"></div>

This leads to no problems, as long as the class attribute is set only once / is static, but as soon as you change it from the outside, vue overwrites the class names set by the library internally, because vue has no clue about it.

My question is now, how can I access the class string inside the virtual DOM node? I've written a method which is able to merge all class names correctly, but in order to do that, I need access to the class names which were set by vue. (e.g. which are inside the virtual DOM)

Are there some best practices to do that? - Or is there a different way to handle my problem? I'm sure I'm not the first with this kind of issue, since this could be pretty common among authors of 3rd party libraries.

I've also found out that I could access these values with:$vnode.data.class and $vnode.data.staticClass, but it feels like a hack.

What does the proposed API look like?

There are many possibilites to solve this issue, you could just expose the desired values inside the $attrs object, or make it observable inside the watch object. I know that in Vue3 it will be accessable in the $attrs object, but is there a workaround in the meantime for Vue2.x?

@posva
Copy link
Member

posva commented Mar 26, 2020

This leads to no problems, as long as the class attribute is set only once / is static, but as soon as you change it from the outside, vue overwrites the class names set by the library internally, because vue has no clue about it.

You need to wrap the behavior in a component with a static template so that Vue never overwrites anything you manually add:

<template>
  <div/>
</template>

<script>
export default {
  mounted () {
    myLib(this.$el)
  }
}

then add props, watcher and other things to call your library.

The general direction (for Vue 3 as well) is to not manipulate the DOM that is manipulated by Vue, you either let Vue handle the whole thing or wrap it in a component and handle all the DOM manipulation yourself


PS: Please, use the forum, the Discord server or StackOverflow for questions. Github issues are for bug reports and feature requests only 🙂

@posva posva closed this as completed Mar 26, 2020
@KingSora
Copy link
Author

KingSora commented Mar 26, 2020

@posva
Thanks for your time! Unfortunately your answer didn't solve my issue, nor did it introduce a workaround for the problem, why did you close then the feature request?

You need to wrap the behavior in a component with a static template so that Vue never overwrites anything you manually add

I'm doing this already, but If someone is using this wrapper component like this:

<wrapper class="custom-class-set-by-user"></wrapper>

Then the class property will be set to my host component and I can't do anything against it.
I can't read the value of the class property, I can't prevent the class value from beeing set, I can't watch the class property like all other properties... I basically have no control at all over the class (and style) property at all.

I've written wrapper components for all popular frontent frameworks like React and Angular. Every framework has a solution for this kind of problem and I think Vue must have a solution as well. - Maybe the solution I've found out myself:

I've also found out that I could access these values with:$vnode.data.class and $vnode.data.staticClass, but it feels like a hack.

But I still don't know whether I can access this property, because it isn't in the Vue documentation.


PS: I've used the Discord server, but the same as here I did not found a suitable answer yet, so I've decided to open a issue on Github to be able to provide the users of my libarary a better experience.

@posva
Copy link
Member

posva commented Mar 26, 2020

Unfortunately your answer didn't solve my issue, nor did it introduce a workaround for the problem, why did you close then the feature request

Because it's a question and it should be posted in the proper channels I said in my comment. Please respect that, we will appreciate it. Thank you.

Regarding the class producing a rerender: Instead of class use a custom prop with a different name so you can retrieve these properties without inducing re render. Forbid the use of class in the documentation

@KingSora
Copy link
Author

Alright, I'll rephrase my feature request, and open a different issue.

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

No branches or pull requests

2 participants