Vue组件的一些底层细节
Vue组件的本质与Vue.extend方法
ButtonCounter 确实只是一个 组件配置对象 ,而不是一个组件本身。当你将这个配置对象注册到Vue实例的 components 选项中时,Vue内部会自动调用 Vue.extend() 方法来处理这个配置对象。
Vue.extend()的作用 :
- 它接收一个组件配置对象作为参数
- 返回一个 VueComponent构造函数 (本质是一个函数)
- 这个构造函数继承自Vue构造函数
当你在Vue实例中注册组件时,Vue内部会执行类似这样的操作:
components: {'button-counter': Vue.extend(ButtonCounter)
}所以注册的实际上是 Vue.extend() 返回的构造函数,而不是你原始的配置对象。
组件实例化过程
当Vue模板中遇到 <button-counter></button-counter> 标签时:
1. Vue会使用之前通过 Vue.extend() 创建的构造函数
2. 创建一个该构造函数的实例对象
3. 这个实例对象与Vue实例类似,但有一些特定的组件行为
为什么组件本质是函数(构造函数)
1. 组件的注册形式 :注册的是构造函数,这样Vue才能根据需要多次实例化组件
2. 实例化过程 :使用 new VueComponent(options) 的方式创建组件实例
3. 复用性考虑 :作为构造函数可以创建多个独立的组件实例
Vue实例和组件实例的关系
- Vue实例 :通过 new Vue() 创建,是根实例
- 组件实例 :通过 new VueComponent() 创建,是子实例
- 继承关系 : VueComponent.prototype.__proto__ === Vue.prototype ,所以组件实例可以访问Vue原型上的方法
<!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.extendconst 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>