摘要:通过查看官网说明,中不要使用和开头,因为在内部也使用和作为方法或属性,这是为了防止冲突。使用如下就不会报错了。
我们先来看一个简单的例子:
{{test}} {{_tttttttttt}} {{$tttttt}}
这么一个简单例子,但是vue却会提示你报错了,错误如下:
从错误中我们可以发现报错的原因竟然是$tttttt和_tttttttttt的变量是没有定义。这是为什么呢?
我们明明在data中定义了。
通过查看官网API说明,data中不要使用$和_开头,因为在Vue内部也使用$和_作为方法或属性,这是为了防止冲突。
那么我们就从源码的角度来分析,我们定义的变量为什么没了呢??、
我们都知道vue采用了ES的defineProperty来实现数据驱动视图,如下:
Object.defineProperty(target, key) { enumerable: true, configurable: true, get: function() { // 这里获取数据 }, set: function() { // 这里设置参数,通知更新视图 } }
可如果仅仅是这样的话,我们在vue中是没法通过this.xxx来获取变量的,而必须是通过this.$data.xxx。因此vue的变量都挂在在$data或_data上。
所以vue内部还做了一层代理,如下
// target是vue实例,key为_data,这样就能通过访问this.xxx = this._data.xxx了 function proxy (target, sourceKey, key) { sharedPropertyDefinition.get = function proxyGetter () { return this[sourceKey][key] }; sharedPropertyDefinition.set = function proxySetter (val) { this[sourceKey][key] = val; }; Object.defineProperty(target, key, sharedPropertyDefinition); }
所以那么我们的变量为什么还是不存在呢,那是因为vue做了一个检测,检测你的变量的开头是否为_或$,如果使用了那么就不会使用代理了,
变量只会存在$data上或_data上。我们来看下源码:
function initData (vm) { var data = vm.$options.data; data = vm._data = typeof data === "function" ? getData(data, vm) : data || {}; if (!isPlainObject(data)) { data = {}; process.env.NODE_ENV !== "production" && warn( "data functions should return an object: " + "https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function", vm ); } // proxy data on instance var keys = Object.keys(data); var props = vm.$options.props; var methods = vm.$options.methods; var i = keys.length; while (i--) { var key = keys[i]; if (process.env.NODE_ENV !== "production") { if (methods && hasOwn(methods, key)) { warn( ("Method "" + key + "" has already been defined as a data property."), vm ); } } if (props && hasOwn(props, key)) { process.env.NODE_ENV !== "production" && warn( "The data property "" + key + "" is already declared as a prop. " + "Use prop default value instead.", vm ); } else if (!isReserved(key)) { // 这边处理代理,所以isReserved处理了是否要进行代理 proxy(vm, "_data", key); } } // observe data observe(data, true /* asRootData */); function isReserved (str) { var c = (str + "").charCodeAt(0); return c === 0x24 || c === 0x5F // 这边判断chartCode是否为_和$ } }
到这里我们就完成的解释为什么无法访问了,所以一般不要使用_和$命名,如果真的要使用的话,那也行。
使用如下就不会报错了。
{{test}} {{_data._tttttttttt}} {{_data.$tttttt}} {{$data._tttttttttt}} {{$data.$tttttt}}