<!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: '父组件数据',
},
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: '子组件数据'
}
},
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值,而不应该报错。
难道是vue在内部规定了子组件在beforeCreate的钩子函数中不能读取外部传入的数据,否则报错?
确实,按照正常情况来讲的,当this为object时,this.message是绝对不会报错的。
然鹅js不会欺骗你,那么这个锅只能让vue来背了。
你可以点击控制台报错的这一行,查看抛出错误的vue代码,也就是vue.esm.js?a026:3297:
at VueComponent.proxyGetter [as trigger] (vue.esm.js?a026:3297)
然后你会发现,代码大概是这样的:
重点在于
return this[sourceKey][key]
。实际上
this.message
调用的并不是vue实例对象下的message属性,而是this._props.message
。而
this._props
在此时(beforeCreate)是undefined
的。这跟vue的生命周期有关,可以看这个图:https://cn.vuejs.org/images/l...。
And,如果你在
created
钩子中console.log(this)
,你会发现this
下是会有message
属性的...(也有_props.message)。是因为上面贴出的代码中有这一段:
Object.defineProperty(target, key, sharedPropertyDefinition);
target是当前vue实例,key是message这一类的props。
( vue用了
defineProperty
把this.message
指向了this._props.message
。)所以,我们还可以做一个试验: