咱們先來看一個簡單的例子:html
<template> <div class="hello"> {{test}} {{_tttttttttt}} {{$tttttt}} </div> </template> <script> import h222 from './h2' export default { name: 'HelloWorld', data () { return { _tttttttttt: '__', $tttttt: '$$', test: 'test' } }, mounted () { console.log(this) } } </script>
這麼一個簡單例子,可是vue卻會提示你報錯了,錯誤以下:vue
從錯誤中咱們能夠發現報錯的緣由居然是$tttttt和_tttttttttt的變量是沒有定義。這是爲何呢?
咱們明明在data中定義了。
經過查看官網API說明,data中不要使用$和_開頭,由於在Vue內部也使用$和_做爲方法或屬性,這是爲了防止衝突。
那麼咱們就從源碼的角度來分析,咱們定義的變量爲何沒了呢??、ide
咱們都知道vue採用了ES的defineProperty來實現數據驅動視圖,以下:ui
Object.defineProperty(target, key) { enumerable: true, configurable: true, get: function() { // 這裏獲取數據 }, set: function() { // 這裏設置參數,通知更新視圖 } }
可若是僅僅是這樣的話,咱們在vue中是無法經過this.xxx來獲取變量的,而必須是經過this.$data.xxx。所以vue的變量都掛在在$data或_data上。this
因此vue內部還作了一層代理,以下spa
// 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:\n' + '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是否爲_和$ } }
到這裏咱們就完成的解釋爲何沒法訪問了,因此通常不要使用_和$命名,若是真的要使用的話,那也行。
使用以下就不會報錯了。code
<template> <div class="hello"> {{test}} {{_data._tttttttttt}} {{_data.$tttttt}} {{$data._tttttttttt}} {{$data.$tttttt}} </div> </template> <script> import h222 from './h2' export default { name: 'HelloWorld', data () { return { _tttttttttt: '__', $tttttt: '$$', test: 'test' } }, mounted () { console.log(this.$data._tttttttttt) console.log(this.$data.$tttttt) console.log(this._data._tttttttttt) console.log(this._data.$tttttt) } }
您的點贊是我繼續努力的動力,謝謝。component