-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
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
refactor: make the set method more reasonable #7981
Conversation
src/core/observer/index.js
Outdated
@@ -172,7 +172,11 @@ export function defineReactive ( | |||
set: function reactiveSetter (newVal) { | |||
const value = getter ? getter.call(obj) : val | |||
/* eslint-disable no-self-compare */ | |||
if (newVal === value || (newVal !== newVal && value !== value)) { | |||
if ( | |||
(getter && !setter) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then when have the chance to invoke customSetter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following content is my understanding, there may be incorrect place.
The first thing we can guarantee is that if the value of the property
property is undefined
, both the value of getter
and setter
will be undefined
:
/* defineReactive */
const property = Object.getOwnPropertyDescriptor(obj, key)
// If `property === undefined`, both `setter` and `getter` are undefined
const getter = property && property.get
const setter = property && property.set
The customSetter
method is mainly used to print prompt information when the property value is set, and mainly used in the following aspects:
- Define the injected value on the instance object:
/* inject.js initInjections */
defineReactive(vm, key, result[key], customSetter)
At this point, the return value of Object.getOwnPropertyDescriptor(vm, key)
is undefined
, so both getter
and setter
are undefined
- Define the
$attrs
and$listeners
properties on the instance object:
/* render.js initRender */
defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => {
!isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
}, true)
defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => {
!isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
}, true)
We can still guarantee that the following statement's value is undefined
:
Object.getOwnPropertyDescriptor(vm, '$attrs') // undefined
Object.getOwnPropertyDescriptor(vm, '$listeners') // undefined
- Define the props data on the
vm._props
object:
/* state initProps */
const props = vm._props = {}
defineReactive(props, key, value, customSetter)
The value of Object.getOwnPropertyDescriptor(props, key)
is undefined
。
In summary, when the value of the Object.getOwnPropertyDescriptor method
is undefined
, both the getter
and the setter
are undefined
, so (getter && !setter)
will always be false
and will not affect the execution of the customSetter
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But won't it make the code harder to maintain? Since every time you add a call to defineReactive
with customSetter
you'll have to check all these conditions.
IMHO, as this refactor aims to get rid of unnecessary observation, putting the getter
and setter
check right before assigning to val
might be easier to understand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sodatea I have made some changes.
niubi |
This comment has been minimized.
This comment has been minimized.
厉害厉害 |
What kind of change does this PR introduce? (check at least one)
Does this PR introduce a breaking change? (check one)
If yes, please describe the impact and migration path for existing applications:
The PR fulfills these requirements:
dev
branch for v2.x (or to a previous version branch), not themaster
branchfix #xxx[,#xxx]
, where "xxx" is the issue number)If adding a new feature, the PR's description includes:
Other information:
Please check: #7280 (comment)