Vue 在创建实例的过程中调用 data 函数
返回数据对象
通过响应式包装后存储在实例的 $data
并且实例可以直接越过 $data 访问属性

这是为了如在 methods 通过 this.xxx 属性就可以访问到 $data 下的 xxx,这是实例上 get 与 set 所实现

  1. const app = Vue.create({
  2. data() {
  3. return {
  4. title: 'This is my TILTE'
  5. }
  6. },
  7. template: `
  8. <h1>{{ title }}</h1>
  9. `
  10. });
  11. const vm = app.mount('#app');
  12. // 这两个其实是同一份数据
  13. vm.$data.title = 'This is your TITLE';
  14. vm.title = 'This is my TITLE';
  15. // 在实例增加一个属性, 在 $data 是没有的
  16. vm.author = 'Xiaoye';
  17. vm.$data.author = 'Xiaoye'; // 虽然这样可以增加,但是没法在 template 渲染出来,因为渲染时是没有

$data 是响应式数据对象
$,,_,这些都是 Vue 提供的内置 API,开发者尽量要避免用这些前缀命名自己的变量和方法名

data 为何必须是一个函数

  1. const App = {
  2. /*
  3. data: { // 这里是会报错,Vue 会检查 data 是否为 function
  4. a: 1
  5. },
  6. */
  7. data: function(){
  8. return {
  9. a: 1
  10. }
  11. },
  12. template: `
  13. <h1>{{ a }}</h1>
  14. `
  15. }
  16. Vue.createApp(App).mount('#app');

如果 data 可以不是函数,实现一下:

  1. var data = {
  2. a: 1,
  3. b: 2
  4. }
  5. var vm1 = new Vue({
  6. data: data
  7. })
  8. var vm2 = new Vue({
  9. data: data
  10. })
  11. vm1.b = 3;
  12. console.log(vm1, vm2); // {a: 1, b: 3} | {a: 1, b: 3}
  13. function Vue (options) {
  14. this.$data = options.data;
  15. var _this = this;
  16. for(var key in this.$data) {
  17. (function(k){
  18. Object.defineProperty(_this, k, {
  19. get: function() {
  20. return _this.$data[k];
  21. },
  22. set: function(newValue) {
  23. _this.$data[k] = newValue;
  24. }
  25. });
  26. })(key);
  27. }
  28. }

如果两个实例都使用同一个 data 引用。其中一个实例修改了,会影响到另外一个实例,即会被污染。
使用函数每次实例都会执行函数得到一个独一无二的引用,避免数据的污染。

如果使用对象不使用函数,要深拷贝

  1. this.$data = deepClone(options.data);

因为 Object.defineProperty 在 IE8 只支持 DOM,可以使用 __defineGetter____defineSetter__

  1. function Vue (options) {
  2. this.$data = deepClone(options.data);
  3. var _this = this;
  4. for(var key in this.$data) {
  5. (function(k){
  6. _this.__defineGetter__(k, function() {
  7. return _this.$data[k];
  8. });
  9. _this.__defineSetter__(k, function(newValue) {
  10. _this.$data[k] = newValue;
  11. });
  12. })(key);
  13. }
  14. }