This article mainly analyzes the issue of Vue data not allowing arrow functions. The article provides a detailed explanation through source code analysis and has certain reference value. Friends in need can refer to it.
First, it should be clarified that a() {} and b: () => {} are different.
let obj = {
a() {},
// 相当于
a:function() {},
b: () => {}
}
1 Vue.js Source Code Analysis
Note: Only the core code is covered here.
This code snippet also demonstrates the implementation principle of UMD. This article does not focus on that; interested readers can explore it on their own.
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Vue = factory());
}(this, (function (){
'use strict';
console.log(this) //*undefined*
})))
Analysis 1:
For JavaScript, functions in non-strict mode have a this context. If you are not clear about this, here is a portal this pointing related.
Regarding the this pointing issue discussed in this article: if not in strict mode, this should point to window, but because the Vue author uses strict mode, it points to undefined.
The following is the implementation principle of data in Vue:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Vue = factory());
}(this, (function (){
'use strict';
function getData(data,vm) {
return data.call(vm, vm)
}
function initData(params) {
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
}
initData()
})))
That is to say, every time a new instance is created, it will check whether there is a data function. If so, it will assign it to vm._data. Attentive students will notice that for the vm instance, there is no data, but vm._data.
ES5 Functions and ES6 Arrow Functions
var obj = {
a: () => {
'use strict';
console.log(this,'a')
},
b() {
console.log(this,'b')
},
c() {
// window
let e = () => {
console.log(this,'e')
}
return e
}
}
obj.a() // window
obj.b() // obj
obj.c()() // obj
For ordinary functions (non-strict mode), this points to the caller. In ES6 arrow functions, this points to the context at the time of declaration.
Combining the above two points, let's analyze today's issue:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Vue = factory());
}(this, (function (){
'use strict';
let vm = {}
var data = () => {
console.log(this);//undefined
return {
a: 1
}
}
function getData(data,vm) {
return data.call(vm, vm)
}
function initData(params) {
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
}
initData()
console.log(vm);
})))
The above code indicates that if you use an arrow function for data: () => {}, this points to undefined. It will still be assigned to vm._data, but it will behave globally, caching your data as long as the page is not refreshed.
If we use data() {}, this points to the vm instance, so it will update with the instance.
暂无评论。