Vue方法methods实现原理

特性

  • Vue 创建实例时,会自动为 methods 绑定当前实例 this
  • 保证在事件监听时,回调始终指向当前组件实例
  • 方法要避免使用箭头函数(箭头函数没法改变this指向,本身指向父级)
    • 箭头函数会阻止Vue正确绑定组件实例this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var app = Vue.createApp({
data() {
return {
title: 'This is my TITLE'
}
},
template: `
<h1>{{ title }}</h1>
<button @click="changeTitle">CHANGE TITLE</button>
`,
methods: {
changeTitle() {
this.title = 'This is your TITLE'
}
}
});

const vm = app.mount('#app');
  • @click="changeTitle('This is your TITLE')"
    • 函数名 + () 不是执行,而是传入实参的容器
    • 相当于React的写法:
    • onclick = "() => changeTitle('This is your TITLE')"
    • 也能这么写:
    • onClick={ () => changeTitle('This is your TITLE') }
    • onClick={ changeTitle.bind(this, 'his is your TITLE')}

方法挂载在实例上

而不是 methods 上,而且也没抛出 methods 属性到 vm 实例上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var app = Vue.createApp({
data() {
return {
title: 'This is my TITLE'
}
},
template: `
<h1>{{ title }}</h1>
<button @click="changeTitle('This is your TITLE')">CHANGE TITLE</button>
`,
methods: {
changeTitle(title) {
this.title = title;
}
}
});

const vm = app.mount('#app');
console.log(vm);
console.log(vm); // undefined

lodash的debounce防抖函数

第一种写法:

组件共用一个debounce,每个实例都共用它,不太好

第二种写法(推荐):

每次创建的时候都返回一个新的debounce函数

手写data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
var Vue = (function() {
function Vue(options) {
this.$data = options.data();
this._methods = options.methods;

this._init(this);
}

Vue.prototype._init = function(vm) {
initData(vm);
initMethods(vm);
}

function initData(vm) {
for (var key in vm.$data) {
(function(k) {
Object.defineProperty(vm, k, {
get: function() {
return vm.$data[k];
},
set: function(newVal) {
vm.$data[k] = newVal;
}
});
})(key);
}
}

function initMethods(vm) {
for (var key in vm._methods) {
vm[key] = vm._methods[key];
}
}

return Vue;
})();

var vm = new Vue({
data() {
return {
a: 1,
b: 2
}
},
methods: {
increaseA(num) {
this.a += num;
},
increaseB(num) {
this.b += num;
},
getTotal() {
console.log(this.a + this.b);
}
}
});

vm.increaseA(1);
vm.increaseA(1);
vm.increaseA(1);
vm.increaseA(1); // 5

vm.increaseB(2);
vm.increaseB(2);
vm.increaseB(2);
vm.increaseB(2); // 10

vm.getTotal(); // 15