Preface
In daily development,$set
It is also a very practical API, because the core of Vue2's responsive implementation is to utilize ES5, When we change the array or add new attributes to the object by directly modifying the array subscript, we cannot listen to the data changes, and then we will use it
$set
, let the modified operations also respond. We need to know why, let’s see how $set is implemented in Vue.
Application scenarios
let dataArr = ["item1"]; let dataObject = { name: "ccs" }; dataArr[2] = "item2"; = 22; // The response failed and the page did not display the updated new data this.$set(,2,'item2') this.$set(,'age',22) //The response is successful, the page displays the updated new data
set implementation
Next, let's take a look at the definition of $set in Vue
function set(target: Array<any> | Object, key: any, val: any): any { if ( .NODE_ENV !== "production" && (isUndef(target) || isPrimitive(target)) ) { warn( `Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}` ); } if ((target) && isValidArrayIndex(key)) { = (, key); (key, 1, val); return val; } if (key in target && !(key in )) { target[key] = val; return val; } const ob = (target: any).__ob__; if (target._isVue || (ob && )) { .NODE_ENV !== "production" && warn( "Avoid adding reactive properties to a Vue instance or its root $data " + "at runtime - declare it upfront in the data option." ); return val; } if (!ob) { target[key] = val; return val; } defineReactive(, key, val); (); return val; }
First, determine whether the target of set isundefined
and basic type ifundefined
Or the basic type will report an error,Because users should not set things in undefined and basic types, and then determine whether the target is an array and key is a legal index. The legal index refers to an integer with a value greater than or equal to 0. If both conditions are true, call the splice method to insert or modify the array on the target array. Heresplice
Not ordinarysplice
,It is the splice in Wang Wei's poem, the splice rewritten by the vue agent
Array implementation response
$set implements the method of modifying the response of an array by the proxy to modify the response. Next, let's take a look at the specific implementation.
const arrayProto = export const arrayMethods = (arrayProto) const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] function def(obj, key, val, enumerable) { (obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } (function (method) { const original = arrayProto[method] def(arrayMethods, method, function mutator (...args) { const result = (this, args) const ob = this.__ob__ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = (2) break } if (inserted) (inserted) () return result }) })
Proxy rewrites in vue not justsplice
,havepush、pop、shift、unshift、splice、sort、reverse
These seven methods are first executedconst result = (this, args)
Execute the original array method and get its value, next judge if it is in the arrayAdd valueThen the newly added value is also responsive.The last stepGet this array_ob_object
right_ob_
The dep in the distribution update.
If you want to know the responsiveness of vue, you can check the previous articlesThe interviewer asked you about the responsive principle of Vue2, how do you answer?
Object implementation response
$set
The logic in the middle and lower half is used to process object responses, let's continue to look at it
if (key in target && !(key in )) { target[key] = val; return val; } const ob = (target: any).__ob__; if (!ob) { target[key] = val; return val; } defineReactive(, key, val); (); return val;
First, if the attribute is directly returned to the end logic in the target object,Because vue will lose its response only when adding attributes that were not originally in the target object.
For examplelet obj={} ='ccs',
When vue is initialized, all attributes in data will be responsive. If the value is an object or an array, a new one will beObserver
The instance is stored in __ob__,If you want to know the responsiveness of vue, you can check the previous articlesThe interviewer asked you about the responsive principle of Vue2, how do you answer
Get the _ob_ of this object for judgment. If it does not exist, it means it isNot initialized by vuea normal object instead ofResponsive ObjectsOtherwise, it will be manually passeddefineReactive
Add a get method and a set method to the attributeImplement response, and then call it manuallydep
Insidenotify()
Release updates.
Summarize
The $set method in vue processes arrays and objects essentially the same, adding a response to the added value and then manually triggering the dispatch update.
The above is the details of how the magic $set is implemented in Vue? For more information about Vue's implementation of $set, please follow my other related articles!