directory
- How to debug Vue3 source code breakpoint in browser
- Try Vue3 part two: The most important changes to the CompositionApi
- Try Vue3 3: CompositionAPI summary and wrapping objects
- How do I run Jest unit Tests
- Try Vue3 five: source code structure
- Try Vue3 six: innovation of responsive principle – Vue2, Vue3 implementation comparison
What is the response
First of all, let’s talk about what is reactive. There’s a way that you can change the data and you can define the response to it and that’s called a responsivity.
Specifically in our MVVM, the need for the ViewModel is that the data has changed and the view needs to respond. This is the case if you use the Jest use case
it('Test whether data is responded to when it changes', () = > {const data = reactive({
name: 'abc'.age: {
n: 5}})// Mock a response function
const fn = jest.fn()
const result = fn()
// Set the response function
effect(fn)
// Change the data
data.name = 'efg'
// Verify that fn takes effect
expect(fn).toBeCalled()
})
Copy the code
So let’s say that what we want is data and we can fire fn when data changes so that we can make a response, which of course is usually to trigger a view update or not. Here we make a Mock function with Jest to check if we make the corresponding.
Finally the code expect(fn).tobecalled () validly means that the test passes which is made accordingly
Solution for Vue2
The following shows how vue2 is implemented by redefining getter and setter methods via Object.defineProperty.
let effective
function effect(fun) {
effective = fun
}
function reactive(data) {
if (typeofdata ! = ='object' || data === null) {
return data
}
Object.keys(data).forEach(function (key) {
let value = data[key]
Object.defineProperty(data, key, {
emumerable: false.configurable: true.get: (a)= > {
return value
},
set: newVal= > {
if(newVal ! == value) { effective() value = newVal } } }) })return data
}
module.exports = {
effect, reactive
}
Copy the code
And of course there are two important issues that you have to deal with and the first one is that you can only do shallow responses if you have a second layer.
it('Test whether changes in multiple layers of data are responded to', () = > {const data = reactive({
age: {
n: 5}})// Mock a response function
const fn = jest.fn()
// Set the response function
effect(fn)
// Change layers of data
data.age.n = 1
// Verify that fn takes effect
expect(fn).toBeCalled()
})
Copy the code
For example, the following use cases can’t be overcome but there is a way to solve this problem by recursive calls
And, of course, there’s also a huge performance penalty for recursion, so keep that in mind.
And then there’s the array problem which we can solve by function hijacking
const oldArrayPrototype = Array.prototype
const proto = Object.create(oldArrayPrototype);
['push'.'pop'.'shift'.'unshift'.'splice'.'sort'.'reverse'].forEach(method= > {
// function hijacking
proto[method] = function(){
effective()
oldArrayPrototype[method].call(this. arguments) } })// Arrays provide responsiveness through data hijacking
if(Array.isArray(data)){
data.__proto__ = proto
}
Copy the code
Vue3
The new version of Vue3 uses ES6 Proxy to solve this problem. The previous two problems were much simpler. First of all, Proxy supports arrays so you don’t have to do any special code for arrays. There is no need to use recursive solutions for deep listening. When GET is an object, return the object as a response. And if you think about it this doesn’t happen at initialization but it happens when it’s set up and of course there’s a big performance improvement.
function reactive(data) {
if (typeofdata ! = ='object' || data === null) {
return data
}
const observed = new Proxy(data, {
get(target, key, receiver) {
// Reflect returns a value without an error
let result = Reflect.get(target, key, receiver)
// Multi-layer proxy
return typeofresult ! = ='object' ? result : reactive(result)
},
set(target, key, value, receiver) {
effective()
// proxy + reflect
const ret = Reflect.set(target, key, value, receiver)
return ret
},
deleteProperty(target,key){
const ret = Reflect.deleteProperty(target,key)
return ret
}
})
return observed
}
Copy the code
Of course, there are still advantages and disadvantages, such as compatibility issues, currently IE11 does not support Proxy. But it’s not a matter of believing that full ES6 support is irreversible.
In order to understand the difference between Vue2 and vu3’s reactive implementations, I have written both implementations, along with jEST tests. You can refer to github.com/su37josephx…
// cloneCode yarn NPX jest reactivity-demoCopy the code
directory
- How to debug Vue3 source code breakpoint in browser
- Try Vue3 part two: The most important changes to the CompositionApi
- Try Vue3 3: CompositionAPI summary and wrapping objects
- How do I run Jest unit Tests
- Try Vue3 five: source code structure
- Try Vue3 six: innovation of responsive principle – Vue2, Vue3 implementation comparison