Vue 在创建实例的过程中调用 data 函数
返回数据对象
通过响应式包装后存储在实例的 $data
并且实例可以直接越过 $data 访问属性
这是为了如在 methods 通过 this.xxx 属性就可以访问到 $data 下的 xxx,这是实例上 get 与 set 所实现
const app = Vue.create({data() {return {title: 'This is my TILTE'}},template: `<h1>{{ title }}</h1>`});const vm = app.mount('#app');// 这两个其实是同一份数据vm.$data.title = 'This is your TITLE';vm.title = 'This is my TITLE';// 在实例增加一个属性, 在 $data 是没有的vm.author = 'Xiaoye';vm.$data.author = 'Xiaoye'; // 虽然这样可以增加,但是没法在 template 渲染出来,因为渲染时是没有
$data 是响应式数据对象
$,,_,这些都是 Vue 提供的内置 API,开发者尽量要避免用这些前缀命名自己的变量和方法名
data 为何必须是一个函数
const App = {/*data: { // 这里是会报错,Vue 会检查 data 是否为 functiona: 1},*/data: function(){return {a: 1}},template: `<h1>{{ a }}</h1>`}Vue.createApp(App).mount('#app');
如果 data 可以不是函数,实现一下:
var data = {a: 1,b: 2}var vm1 = new Vue({data: data})var vm2 = new Vue({data: data})vm1.b = 3;console.log(vm1, vm2); // {a: 1, b: 3} | {a: 1, b: 3}function Vue (options) {this.$data = options.data;var _this = this;for(var key in this.$data) {(function(k){Object.defineProperty(_this, k, {get: function() {return _this.$data[k];},set: function(newValue) {_this.$data[k] = newValue;}});})(key);}}
如果两个实例都使用同一个 data 引用。其中一个实例修改了,会影响到另外一个实例,即会被污染。
使用函数每次实例都会执行函数得到一个独一无二的引用,避免数据的污染。
如果使用对象不使用函数,要深拷贝
this.$data = deepClone(options.data);
因为 Object.defineProperty 在 IE8 只支持 DOM,可以使用 __defineGetter__、__defineSetter__
function Vue (options) {this.$data = deepClone(options.data);var _this = this;for(var key in this.$data) {(function(k){_this.__defineGetter__(k, function() {return _this.$data[k];});_this.__defineSetter__(k, function(newValue) {_this.$data[k] = newValue;});})(key);}}
