vue中的一个组件就是一个vue实例吗?
所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象
先说结论
这句话,这是官方文档说的
不过严谨来说,应该是
一个单页应用就是一个 vue 的实例
每个自定义组件就是一个 vueComponent 实例,
只不过 vueComponent 的构造器和 vue 的构造器的内容是基本一样的。效果表现也一致,两者对比如下
<div id="app">{{uname}}</div>
<script>
// 仅有Vue实例
var app = new Vue({
el: "#app",
data() {
return {
uname: "小红",
};
},
methods: {
say() {
console.log("调用了say方法");
},
},
mounted() {
this.say();
},
});
</script>
<div id="app"></div>
<script>
// 组件
const RootCmp = {
data() {
return {
uname: "小红",
};
},
methods: {
say() {
console.log("调用了say方法");
},
},
mounted() {
this.say();
},
template: "<div>{{uname}}</div>",
};
var app = new Vue({
el: "#app",
render: (h) => h(RootCmp),
});
</script>
证明
我们创建个 vue 项目
<div id="app">
{{ message }}
<cmp-one></cmp-one>
------
<cmp-two></cmp-two>
</div>
<script>
// 全局组件
Vue.component("CmpOne", {
template: "<div>组件1</div>",
});
var app = new Vue({
el: "#app",
data: {
message: "Hello Vue!",
},
components: {
CmpTwo: {
// 局部组件
template: "<div>组件2</div>",
},
},
});
</script>
然后开始分析源码
以下是 vue.js 部分代码,
我们很快找到 Vue 的类,并添加个 log
function Vue(options) {
console.log("Vue构造类");
if (!(this instanceof Vue)) {
warn("Vue is a constructor and should be called with the `new` keyword");
}
this._init(options);
}
结果发现,Vue 构造函数只会被执行一次,也就是你手动 new 的时候。
这足以证明每个组件(或.vue)文件不是 Vue 的实例。
那组件是谁的实例呢?
我们继续看源码,通过代码分析我们得知
全局组件 or 局部组件的注册初始化,是走这里
...
var Sub = function VueComponent (options) {
console.log('VueComponent组件的构造类');
this._init(options);
};
...
// 其中vnode.componentOptions.Ctor就是VueComponent类
new vnode.componentOptions.Ctor(options);
如上代码中,VueComponent组件的构造类会被打印两次。
这也就是说,它才是组件实例的构造函数(类)。
源码稍微深度分析
Vue.extend = function (extendOptions, is) {
var Super = this;
// ...
var Sub = function VueComponent(options) {
console.log("VueComponent组件的构造用来 实例化");
this._init(options);
};
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
// ...
return Sub;
};
function initAssetRegisters(Vue) {
// ...
ASSET_TYPES.forEach(function (type) {
Vue[type] = function (id, definition) {
if (!definition) {
return this.options[type + "s"][id];
} else {
if (type === "component" && isPlainObject(definition)) {
definition.name = definition.name || id;
definition = this.options._base.extend(definition);
}
return definition;
}
};
});
}
function initGlobalAPI(Vue) {
// ...
initAssetRegisters(Vue);
}
initGlobalAPI(Vue);
解读:
项目初始化进来的时候会执行一个全局方法 initGlobalAPI
initGlobalAPI里会调用initAssetRegisters
initAssetRegisters的作用是给你定义的一些全局Asset扩展一些属性
枚举ASSET_TYPES 就是全局Asset:包含 component,directive,filter
比如我的组件 CmpOne,原本只有 template 属性,经过扩展后,就会多出如下属性
{
cid: 1
component: ƒ ( id, definition )
directive: ƒ ( id, definition )
extend: ƒ (extendOptions, is)
extendOptions: {template: '<div>组件1</div>', name: 'CmpOne', _Ctor: {…}}
filter: ƒ ( id, definition )
mixin: ƒ (mixin)
options: {components: {…}, directives: {…}, filters: {…}, template: '<div>组件1</div>', _base: ƒ, …}
sealedOptions: {components: {…}, directives: {…}, filters: {…}, template: '<div>组件1</div>', _base: ƒ, …}
super: ƒ Vue(options)
superOptions: {components: {…}, directives: {…}, filters: {…}, _base: ƒ}
use: ƒ (plugin)
}
其中重要的一点就是给CmpOne组件指定了构造器
那是怎么指定的呢?
this.options._base.extend(definition);
这句代码本质上就是调用了Vue.extend来创建了一个Vue的子类。
那么情况就明了了,组件构造函数是继承自Vue构造。
最后vue在创建vdom的时候,就会去实例化组件类,即new VueComponent()
总结
Vue组件构造类是继承自Vue类- 它们的属性options也基本是一样的,Vue 实例会比 Vue 组件多出 el 和 router 属性(对应官方说辞:组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。)
所有的Vue组件都是Vue实例这句话只是官方为了方便咱们理解,但严格来说并不对,严格来说应该是所有的Vue组件都是Vue的子类实例- 在多页应用下或vue2的
Vue.extend和vue3的createApp,才会形成多个Vue实例


扩展
Vue.component和Vue.extend的联系:
Vue.component注册或获取全局组件。注册还会自动使用给定的 id 设置组件的名称,如上id就是组件名CmpOne,内部实质上调用了Vue.extend,最后返回"子类"(构造器),这个子类构造器。
vue中的一个组件就是一个vue实例吗?的更多相关文章
- 【Vue】Vue中的父子组件通讯以及使用sync同步父子组件数据
前言: 之前写过一篇文章<在不同场景下Vue组件间的数据交流>,但现在来看,其中关于“父子组件通信”的介绍仍有诸多缺漏或者不当之处, 正好这几天学习了关于用sync修饰符做父子组件数据双向 ...
- vue中的父子组件相互调用
vue中的父子组件相互调用: 1.vue子组件调用父组件方法:子组件:this.$emit('xx'); 父组件:定义yy方法,并在引用子组件时传参,如@xx="yy" 2.vue ...
- Vue之vue中的data为什么是一个函数+vue中路径别名alias设置
问题描述 为什么在vue组件中,我们的data属性必须是一个函数,new Vue()中的data除外,因为new Vue中只有一个data属性. 原因 因为我们能抽离出来的组件,肯定是具有复用性的,它 ...
- vue中引入swiper(vue中的滑块组件vue-awesome-swiper)
第一步安装 npm install vue-awesome-swiper --save 第二部在main.js中引入 import VueAwesomeSwiper from 'vue-awesome ...
- vue中使用keepAlive组件缓存遇到的坑
项目开发中在用户由分类页category进入detail需保存用户状态,查阅了Vue官网后,发现vue2.0提供了一个keep-alive组件. 上一篇讲了keep-alive的基本用法,现在说说遇到 ...
- Vue中,父组件向子组件传值
1:在src/components/child/文件夹下,创建一个名为:child.vue的子组件 2:在父组件中,设置好需要传递的数据 3:在App.vue中引入并注册子组件 4:通过v-bind属 ...
- vue中兄弟之间组件通信
我们知道Vue中组件之间的通信有很多方式,父子之间通信比较简单,当我们使用vuex时候,兄弟组件之间的通信也很好得到解决 当我们项目较小时候,不使用vuex时候Vue中兄弟组件之间的通信是怎样进行的呢 ...
- vuex 实现vue中多个组件之间数据同步以及数据共享。
http://pan.baidu.com/s/1hrJfpli demo下载地址 前言 在一些项目中有很多数据状态之间要实现数据共享状态共享,例如购物车的数据.用户的登录状态等等.vue父元素是可以 ...
- vue中修改子组件样式
一.问题叙述 项目里需要新添加一个表单页面,里面就只是几个select,这个几个select是原本封装好的组件,有自己原本的样式,而这次的原型图却没有和之前的样式统一起来,需要微调一下,这里就涉及到父 ...
- Vue中iframe和组件的通信
最近的项目开发中用到了Vue组件中嵌套iframe,相应的碰到了组件和HTML的通信问题,场景如下:demo.vue中嵌入 test.html 由于一般的iframe嵌套是用于HTML文件的,在vue ...
随机推荐
- 继承 QPaintEngine 利用 QSvgRenderer 从SVG 图片中提取路径(QPainterPath)的方法
SVG 作为为可缩放矢量图形(Scalable Vector Graphics),易于编辑和维护,基于XML的文本文件存储,在网页设计.图标制作.数据可视化和其他图形相关的领域应用广泛.在应用工程中总 ...
- 🎀杜伽Durgod K610W蓝牙连接问题解决
简介 杜伽Durgod K610W键盘支持三模连接,在配对成功蓝牙后切换连接通道后,再次连接蓝牙通道时无法正常自动连接已配对的蓝牙,需取消配对再重新配对后才能正常连接.这种问题可以通过升级键盘固件解决 ...
- OpenEuler22.03源码编译安装nginx1.24.0
一.环境说明 操作系统版本:OpenEuler22.03 SP2 LTS Nginx版本:1.24.0 安装位置:/app/nginx Selinux配置:关闭或设置为permissive 二.Ngi ...
- <HarmonyOS第一课04>应用程序框架基础
视频链接: https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717497122909477?ha_sou ...
- 工具 | Hashcat
0x00 简介 Hashcat是一款强大的密码破解工具. 下载地址 Hashcat下载: Hashcat下载 0x01 功能说明 直接破解 组合攻击 掩码暴力破解 混合攻击 联合攻击 注:仅供安全研究 ...
- AT_arc168_e [ARC168E] Subsegments with Large Sums 题解
题意: \[\begin{aligned} &\text{给定长度为 } n \text{ 的数列 } \{a_i\} \text{ 和两个参数 } k, s \text{,将 } \{a_i ...
- vue3 基础-动态组件 & 异步组件
之前学习的都是父子组件传值的话题, 一句话总结就是, 常规数据通过属性传, dom 结构通过插槽 slot 来传. 而本篇则关注如何通过数据去控制组件的显示问题, 如咱经常用到的页面切换呀, Tab ...
- 交易信号---MACD、RSI、Boll、分型等技术信号
技术指标 在交易决策过程中的简图: 什么是技术指标? 基于行情数据,通过特定数学公式或模型计算得出的.用于辅助交易决策的数值序列 技术指标的分类 三种关系: 趋势线: 股市走势震荡起伏,供需关系被打破 ...
- 阿里云部署Django主要注意事项
(1)virtualenv 报错 os 没有 PathLike属性 阿里云ubuntu16.0服务器默认python版本分别是2.7.12,3.5.2,而PathLike是在python 3.6时才被 ...
- .NET外挂系列:2. 了解强大的 harmony 注解特性
一:背景 1. 讲故事 上一篇我们简单的聊了下harmony外挂的基本玩法,让大家宏观上感受到了外挂在 .NET高级调试 领域的威力,这一篇我们从 注解特性 这个角度继续展开. 二:harmony 注 ...