#7981 is a breaking change
See original GitHub issueVersion
2.5.18-beta.0
Reproduction link
https://jsfiddle.net/50wL7mdz/806315/
Steps to reproduce
Change src
attributes in HTML to try w/ different versions
What is expected?
isChanged
computed property to be true
after delay
What is actually happening?
it doesn’t get an updated value of isChanged
Let’s consider a bit simplified situation of my real one. Suppose I have a DataWrapper
which purpose is to tell whether the held data object was changed or not.
This wrapper has 2 properties: isChanged
(read-only, boolean, false by default) and data
(read-write, any type); and it is initialized w/ some data.
I think it’s clear and not a problem that isChanged
property should only have a getter, but for the sake of reactivity, it’s allowed to have setter be added. Also, in data
setter there’s a line
try { this.isChanged = true } catch (e) {/*ignore*/}
for this purpose, i.e. if a setter was defined by some reactivity library (built into Vue in our case), we should invoke it before changing the internal state to let it pass the Vue’s check and propagate the change across dependent values:
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
But then, since we hadn’t any setter initially defined for isChanged
property, the following check
// #7981: for accessor properties without setter
if (getter && !setter) { return }
, which was added in PR #7981, is failed and the change is not propagated, which is definitely not a desired behavior.
Commenting of this line completely solves the problem.
So I consider this change as a breaking and think it should be reverted to original behavior.
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
Well, I see it like this: #7981 was introduced to skip unnecessary obervations:
In a usual scenario, an object property that only has a getter and no setter can only be changed by other means unknown to Vue. Vue can only track changes through a setter, which the object in question apparently doesn’t use. So there’s no use in making this object reactive. 99 times out of a 100, we would otherwise observe an object property that, as far as Vue can tell, won’t ever change.
Now, before this PR, we did add this setter, and you are the 1 in a 100 case where the author actively checks for this setter to call it just to accomodate Vue.
But I’m not really willing to call this a breaking change as we never made that implementation detail part of our public API contract. To the contrary, we have warnings like this one in our docs:
You are of coure free to work around these limitations like you did, but it’s not our responsibility to think of each possible interaction with stateful objects in reactive
data
(that we explicitly warn against) when doing internal changes.Thanks for understanding. I hope you find a good way to solve your issue