-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
Ref (DOM element) should work with non-ref (reactivity) #660
Comments
Why would you want a more implicit behavior without saying it's a |
@posva Do you find the behavior of the first repro above intuitive for a newcomer? I ended up in that situation (more involved, but basically this root cause) and I lost a lot of time figuring out why I didn't get the element. It was not a nice experience. Moreover I didn't try but I expect this to not work either: setup() {
let scope = reactive({ b1: null })
return scope
} Because there is no It's also inconsistent with other stuff that updates the scope, like This is bad developer experience. If you don't fix it, you should document this more clearly, with a red box in the docs and create a warning in DEV mode if you detect this situation (property exists but is not a ref). |
I'm asking you the questions to get a better understanding, never said this was or wasn't going to be fixed 🙂 . To answer your questions:
I honestly don't see how a newcomer will figure out how
So using
I'm sorry, I don't understand what you are exactly referring to |
Well, I did? (obviously I read some docs) Disclosure: I'm trying out Vue but I have years of experience with several other frameworks and UI development in general. I may not be representative of a beginner.
Here's a piece of code: <input v-model="name" ref="box" /> setup() {
return reactive({ name: 'John', box: null })
} To me it's surprising (in a bad way) that |
That's a bit contradictory: you didn't figure it out if you read the docs 😄 . Did you read this https://vue-composition-api-rfc.netlify.com/api.html#template-refs or something else? I don't think we have proper docs on this yet, so it's something we can gather feedback from Thanks for the example, now I see how
Regarding the technical difference, when using the reference to the element/component, it is reactive, meaning that we need to use a reactive variable to retrieve that ref in the js: setup() {
const el = ref(null)
// notice the `value` like other reactive properties
const textFromEl = computed(() => el.value.textContent)
return { el }
} This wouldn't be possible if we had Where in the code were you using the |
I did but unfortunately I found it only after figuring out what was the problem on my own.
So it's there but it's easy to overlook. I've read the source code and understand that the two directives work very differently under the hood. The current behavior makes a lot of sense in the old context of
I am fully aware of that. As I said in the original issue, many times an element won't change over the lifetime of your component, so that's fine. More annoyingly, I might use
Sure, this is what I was experimenting with: (The code editor doesn't load for me in FF, but it does in Chrome) You'll notice this code does a |
That's not true, it appears in all three code samples as well. The paragraph that mentions it is also the only explanation. That's rather hard to overlook.
Yes, I'm referring to the difference from Vue 2 and Vue 3 trying to give some background to explain why this could make sense to us and make it clearer why it doesn't necessarily makes sense in its current state.
Sure, but we cannot be aware of that condition, so it has to be treated as the larger case: it could change -> it should be a reactive variable. Thanks for the example, it gives more context! Instead of using I agree that a warning makes total sense here. I still feel it's only a patch because of the comparison with |
Yeah but I'm using |
Personally I didn't expect someone to return the object returned by |
BREAKING CHANGE: revert setup() result reactive conversion Revert 6b10f0c & a840e7d. The motivation of the original change was avoiding unnecessary deep conversions, but that can be achieved by explicitly marking values non-reactive via `markNonReactive`. Removing the reactive conversion behavior leads to an usability issue in that plain objects containing refs (which is what most composition functions will return), when exposed as a nested property from `setup()`, will not unwrap the refs in templates. This goes against the "no .value in template" intuition and the only workaround requires users to manually wrap it again with `reactive()`. So in this commit we are reverting to the previous behavior where objects returned from `setup()` are implicitly wrapped with `reactive()` for deep ref unwrapping.
I wish this behavior would be changed, esp. since alpha 8. In Vue 3 you don't think in refs names anymore. With the API you think in an object that represent a reactive state. Forcing a ref here is not cool, e.g. you can also have reactive state by returning a reactive object: setup() {
return reactive({ element: null })
} This code really doesn't make much difference compared to: The fix doesn't look complicted:
That's about it? |
The docs are really outdated or I have found a bug. At Usage inside v-for they are showing how to put the elements to the array.
so here the divs variable is not defined. Quick example:
Results in Using "vue": "^3.0.0-alpha.8", "@vue/compiler-sfc": "^3.0.0-alpha.8". Do you plan to put back something like $children? In my case I have manually defined 100 icons and need to foreach them all to run a function inside each specific component. Appending to 100 lines something like :ref="r => array.push(r)" looks quite weird to me. // Edit, I just realized maybe the v-for is setting "this" context for template variables? If it does then it means I can't define multiple components to the same array. Hack will be to define foreach loop with 1 dummy iteration. (just checked it and it is not this case) |
@sionzeecz your case is working as intended. If you want to report a bug, open a new issue with actual reproduction instead of commenting on other issues. |
This comment has been minimized.
This comment has been minimized.
By "working as intended" I mean the code you showed is working. There is no bug. If there is one, you should provide a reproduction (e.g. a codepen, and in a separate issue). |
Closing the original issue since a |
@yyx990803 Can I ask what's the motivation? |
Because the user may do this: const state = {
foo: null
}
onMounted(() => {
state.foo // expect to get a ref but won't, because local `state` is not reactive
})
return state A |
With the change I proposed it would totally work, wouldn't it? And that's kind of the point. At the same time, Vue 2 is the past, Vue 3 is gonna have new users that never had exposure to Vue 2; or that might have experience with other frameworks. They might be surprised that your example (with or without reactive) doesn't work. As a new user I genuinely don't understand the logic here and I feel this is a limitation more than an enhancement. After looking at the code, it seems rather trivial to change. |
What problem does this feature solve?
The way it currently (doesn't) works is really surprising for users.
It took me a long amount of time to understand why I couldn't get a DOM element from my code.
Here's a simplified repro:
Looking at this code, my intuition is that
b1
will be a ref containing the first HTMLButton andb2
will be a non-reactive field containing the second HTMLButton.With vue-next@3.0.0-alpha.3,
b1
works as expected butb2
staysnull
.This is confusing, especially since in templating the
ref
nature ofb1
is hidden -- code usingb1
andb2
is the same in template expressions.Moreover for better usability you may be tempted to hide all your refs behind a getter/setter, I'm doing this:
And now even though
b1
is reactive, it'snull
just likeb2
because Vue doesn't see theref
hidden inside the getter/setter.Similar issues arise when using the built-in
reactive({ b1: null, b2: null})
.What does the proposed API look like?
There is no new API surface.
I propose to change the behavior of
<div ref=x>
so that the HTML element is available insetup
state whether the field is aref
or not.If there is a technical reason to not do that, I suggest that you detect this and provide a warning in DEV mode.
The text was updated successfully, but these errors were encountered: