Vue组件的本质与Vue.extend方法
ButtonCounter 确实只是一个 组件配置对象 ,而不是一个组件本身。当你将这个配置对象注册到Vue实例的 components 选项中时,Vue内部会自动调用 Vue.extend() 方法来处理这个配置对象。
Vue.extend()的作用 :
-
它接收一个组件配置对象作为参数
-
返回一个 VueComponent构造函数 (本质是一个函数)
-
这个构造函数继承自Vue构造函数
当你在Vue实例中注册组件时,Vue内部会执行类似这样的操作:
javascript
components: {
'button-counter': Vue.extend(ButtonCounter)
}
所以注册的实际上是 Vue.extend() 返回的构造函数,而不是你原始的配置对象。
组件实例化过程
当Vue模板中遇到 <button-counter></button-counter> 标签时:
-
Vue会使用之前通过 Vue.extend() 创建的构造函数
-
创建一个该构造函数的实例对象
-
这个实例对象与Vue实例类似,但有一些特定的组件行为
为什么组件本质是函数(构造函数)
-
组件的注册形式 :注册的是构造函数,这样Vue才能根据需要多次实例化组件
-
实例化过程 :使用 new VueComponent(options) 的方式创建组件实例
-
复用性考虑 :作为构造函数可以创建多个独立的组件实例
Vue实例和组件实例的关系
-
Vue实例 :通过 new Vue() 创建,是根实例
-
组件实例 :通过 new VueComponent() 创建,是子实例
-
继承关系 : VueComponent.prototype.proto === Vue.prototype ,所以组件实例可以访问Vue原型上的方法
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../vue.js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用组件 button-counter -->
<button-counter></button-counter>
</div>
<script>
// 定义一个名为 button-counter 的新组件,同时注册为全局组件
const ButtonCounter = {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
}
console.log('原始配置对象:', ButtonCounter) // 普通对象
// 手动调用Vue.extend
const ButtonCounterConstructor = Vue.extend(ButtonCounter)
console.log('Vue.extend返回:', ButtonCounterConstructor) // 构造函数
console.log('是否是函数:', typeof ButtonCounterConstructor === 'function') // true
// 创建组件实例
const componentInstance = new ButtonCounterConstructor()
console.log('组件实例:', componentInstance) // 对象
const vm = new Vue({
el: '#app',
data: {
message: 'hello vue'
},
components: {
'button-counter': ButtonCounter
}
})
console.log(vm)
</script>
</body>
</html>