鍍金池/ 問答/HTML/ vue中子組件的beforeCreate鉤子函數(shù)中讀取父組件傳入的數(shù)據(jù)出現(xiàn)報錯

vue中子組件的beforeCreate鉤子函數(shù)中讀取父組件傳入的數(shù)據(jù)出現(xiàn)報錯

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="renderer" content="webkit">
  <title>父子組件生命周期</title>
</head>
<body>
  <div id="app">
    <p>{{parentData}}</p>
    <child message="hello子組件"></child>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.15/vue.js"></script>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        parentData: '父組件數(shù)據(jù)',
      },
      beforeCreate() {
        console.log(`Parent--beforeCreate ${this.parentData} ${this.$el}`);
      },
      created() {
        console.log(`Parent--created ${this.parentData} ${this.$el}`);
      },
      components: {
        child: {
          template: `<div><p>{{message}}</p> <p>{{childrenData}}</p></div>`,
          props: {
            message: {
              type: String
            }
          },
          data: function () {
            return {
              childrenData: '子組件數(shù)據(jù)'
            }
          },
          beforeCreate() {
            console.log(this);
            console.log(`Child--beforeCreate ${this.message} ${this.childrenData} ${this.$el}`);
          },
          created() {
            console.log(`Child--created ${this.message} ${this.childrenData} ${this.$el}`);
          },
        }
      }
    })
  </script>
</body>

下面是輸出
圖片描述
子組件在beforeCreate中讀取外部的傳入的變量時報錯了,但是令我疑惑的是,上面可以輸出this的值,如果message沒有綁定到子組件上,最多就是輸出undefined值,而不應(yīng)該報錯。
難道是vue在內(nèi)部規(guī)定了子組件在beforeCreate的鉤子函數(shù)中不能讀取外部傳入的數(shù)據(jù),否則報錯?

回答
編輯回答
我以為

確實,按照正常情況來講的,當(dāng)this為object時,this.message是絕對不會報錯的。

然鵝js不會欺騙你,那么這個鍋只能讓vue來背了。

你可以點擊控制臺報錯的這一行,查看拋出錯誤的vue代碼,也就是vue.esm.js?a026:3297:
at VueComponent.proxyGetter [as trigger] (vue.esm.js?a026:3297)

然后你會發(fā)現(xiàn),代碼大概是這樣的:

var sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
};

function proxy (target, sourceKey, key) {
  sharedPropertyDefinition.get = function proxyGetter () {
    return this[sourceKey][key] // 是這里報錯了 sourceKey為_props, key為message
  };
  sharedPropertyDefinition.set = function proxySetter (val) {
    this[sourceKey][key] = val;
  };
  Object.defineProperty(target, key, sharedPropertyDefinition);
}

重點在于return this[sourceKey][key]

實際上this.message調(diào)用的并不是vue實例對象下的message屬性,而是this._props.message。
this._props在此時(beforeCreate)是undefined的。
這跟vue的生命周期有關(guān),可以看這個圖:https://cn.vuejs.org/images/l...

And,如果你在created鉤子中console.log(this),你會發(fā)現(xiàn)this下是會有message屬性的...(也有_props.message)。

是因為上面貼出的代碼中有這一段:Object.defineProperty(target, key, sharedPropertyDefinition);
target是當(dāng)前vue實例,key是message這一類的props。
( vue用了definePropertythis.message指向了this._props.message。)

所以,我們還可以做一個試驗:

  created() {
    console.log(this._props) // object
    console.log(this.message, 11)  // 'message content'
    delete this._props.message
    console.log(this.message, 22) // undefined
  }
2017年2月20日 07:15
編輯回答
卟乖
因為vue的數(shù)據(jù)劫持機制
在beforeCreate鉤子中訪問 this.message 實際上調(diào)用了
this.message的get函數(shù) 而在get函數(shù)中vue返回的是 this['_props']['message']
顯然這個時候 this['_props'] 為undefined 這就是報錯原因.

2018年9月21日 12:23