Vue.extend和VueComponent的关系源码解析
目录
0.概念解释
前言
需求分析
Vue.extend
编程式的使用组件
源码分析
0.概念解释
Vue.extend和VueComponent是Vuejs框架中创建组件的两种不同方式。Vue.extend方法能够让你根据Vue对象(继承)来定义一个新的可重用的组件构造器。而VueComponent方法则是将该元件定义下侧的函数以及组件实例化时需要用到的选项(如data、computed、watch、methods、created等)作为对象传入,系统会将这个对象转换成一个Vue的构造器。 两者的关系是, Vue.extend本质上是一个用来创建Vue组件的函数,而VueComponent是定义组件的一种方式。使用Vue.extend可以灵活地定义组件,而使用VueComponent可以使代码更加简洁,可以快速创建出组件。Vue.extend的好处是它可以通过链式调用更方便地定义组件,而在VueComponent中只允许传入对象参数,因此Vue.extend灵活度更高。尽管VueComponent定义组件更简洁,但其性能却不及Vue.extend,而且它也不便于做复杂的组件定义。因此,Vue.extend和VueComponent有其各自的应用场景,可以根据实际需求来选择使用哪一种,而不是简单地把它们二者看成同一种方式。
前言
写Vue.js已经3年了吧,对Vue.extend全局方法的了解也就停留在了解啦,一直抱着不用就不学的思想,造成了一次又一次的错过~~~
直到最近,才通过公司10年秃头少年的代码,才知道错过Vue.extend方法,也就等于错过了对Vue组件的第二春了解的机会!!!
需求分析
在页面中弹出消息提示框,比如在用户点击按钮给予回应
这种业务场景很常见吧,肯定是先创建一个弹框组件,在需要使用弹框的地方注册组件并挂载到页面上去
但是需求还没结束,又提出在所以页面都可以弹出这个消息提示框
首选局部注册肯定是不行了,局部注册只能当前页面使用,所以要选择在App.vue中注册并挂载,因为App.vue是所有组件的根组件,所以组件也都能访问到App.vue中的方法,我们只需要在App.vue暴露一个弹框显示的方法就可以了
产品还不打算放过我,又提出需求是可以同时出现多个消息提示框
这个就不好实现了呀,一个组件挂载只能弹出一个提示框,总不能在App.vue挂载很多个吧,其实这也是解决方案,但是不利于扩展、占用内存!!!
那就没有办法了吗?也不是,那就要请出主角Vue.extend全局方法!!!
Vue.extend
看看官方的八股文:
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象
我认为这段文字表达十分明了,首先Vue.extend参数是包含组件选项的对象,返回值是Vue的子类
import Vue from 'vue'
let VueComponent = Vue.extend({})
VueComponent.prototype.__proto__ == Vue.prototype // true
我们这里将子类称为VueComponent
你对这个名称很熟悉吧~~~
import Vue from 'vue/dist/vue.esm.js' // 必须引入这个版本的Vue才可以使用template选项
new Vue({el: "#app",template: `<App></App>`,components: { App },mounted() {let app = this.$children[0]; // App组件实例let VueComponent = app.constructor // App构造函数console.log(app);console.log(VueComponent);console.log(VueComponent.prototype.__proto__ == Vue.prototype);}
})
不难发现VueComponent就是组件的构造函数~~~
是不是一下就明白了,Vue.extend的返回值就是组件的构造函数,传入的选项就是组件的初始配置
Vue.extend作用可以理解为:
首选创建一个Vue类的子类(组件的构造函数),将传入的组件选项配置当做实例子类的默认值(组件的初始配置),并返回这个类(组件的构造函数)
Vue.component("Toast", {}) // 全局注册组件
console.log(Vue.component("Toast")); // Toast组件构造函数
在使用Vue.component方法注册全局组件时,其实内部也是先调用Vue.extend生成VueComponent,再声明到全局组件中,局部组件也是一样的~~~
其实这里还能了解一个知识点:所以的组件构造函数的父类都是Vue,所以组件可以使用Vue上所以方法和属性,比如emit、set等
编程式的使用组件
VueComponent可以被称为小Vue,VueComponent的使用也就可以对照Vue
let VueComponent = Vue.extend({})
new VueComponent({el: "#app",template: `<h1>Vue.extend的使用</h1>`
})
是不是和Vue的使用一模一样喃?
区别在于Vue.extend可以通过参数确定组件的初始配置~~~
现在完成一下最开始的需求吧~
编写my-toast.vue
<template><h1 class="title" v-if="show">{{ title }}</h1>
</template>
<script>export default {name: "my-toast",props: {title: {typeof: String,default: ""}},data() {return {show: true};},created() {setTimeout(() => {this.show = false;this.$nextTick(() => {this.$destroy();});}, 2000);}};
</script>
<style>.title {width: 180px;height: 50px;position: fixed;right: 20px;top: 20px;background-color: rgba(0, 0, 0, 0.15);text-align: center;line-height: 50px;border-radius: 8px;font-size: 16px;}
</style>
在vue的原型上绑定显示弹框方法
import Vue from 'vue';
import myToast from './components/my-toast.vue';
Vue.prototype.$toast = function (title) {const ToastComponent = Vue.extend(myToast);const toastComponent = new ToastComponent({propsData: {title}})toastComponent.$mount(document.createElement('div'));document.body.appendChild(toastComponent.$el);
}
在需要弹框的地方调用方法
// ....某vue页面
mounted() {this.$toast("测试");
}
let vm = new VueComponent(options)
的注意点:
- 传递的props配置需要配置到propsData属性中
- 使用VueX、
VueRoter
等第三方模块,需要把这些模块挂载到options上 - 使用插槽需要通过vm.$scopedSlots传递
源码分析
你可以在源码目录src/core/global-api/extend.js
下找到这个函数的定义
Vue.extend = function (extendOptions: any): typeof Component {extendOptions = extendOptions || {}// this指的是Vueconst Super = this// 每个组件构造函数都有唯一的cidconst SuperId = Super.cid// 创建完的VueComponent构造函数,会保存到_Ctor中// 如果下次传入相同的extendOptions和SuperId,就直接取用缓存内的值const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})if (cachedCtors[SuperId]) {return cachedCtors[SuperId]}// 获取组件nameconst name =getComponentName(extendOptions) || getComponentName(Super.options)if (__DEV__ && name) {// 校验组件namevalidateComponentName(name)}// 创建VueComponent构造函数const Sub = function VueComponent(this: any, options: any) {this._init(options)} as unknown as typeof Component// 重点:实现了原型链继承,让VueComponent的原型指向Vue的原型// Vue的原型的所有方法和属性,在VueComponent也存在Sub.prototype = Object.create(Super.prototype)Sub.prototype.constructor = Sub// 生成唯一cidSub.cid = cid++// 传入的extendOptions和Vue.options合并Sub.options = mergeOptions(Super.options, extendOptions)Sub['super'] = Super// 配置props的响应式if (Sub.options.props) {initProps(Sub)}// 配置computed的响应式if (Sub.options.computed) {initComputed(Sub)}// 继承静态方法Sub.extend = Super.extendSub.mixin = Super.mixinSub.use = Super.use// ASSET_TYPES = ['component', 'directive', 'filter']ASSET_TYPES.forEach(function (type) {Sub[type] = Super[type]})if (name) {Sub.options.components[name] = Sub}// 保存基础配置Sub.superOptions = Super.optionsSub.extendOptions = extendOptionsSub.sealedOptions = extend({}, Sub.options)// 设置缓存cachedCtors[SuperId] = Subreturn Sub}
Vue.extend关键在于继承Vue,抛开其他功能代码,主要实现继承的代码:
// 继承原型
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
// 继承静态方属性和方法
// 继承静态方法
Sub.extend = Super.extend
Sub.mixin = Super.mixin
Sub.use = Super.use
// ASSET_TYPES = ['component', 'directive', 'filter']
ASSET_TYPES.forEach(function (type) {Sub[type] = Super[type]
})
相关文章:
Vue.extend和VueComponent的关系源码解析
目录 0.概念解释 前言 需求分析 Vue.extend 编程式的使用组件 源码分析 0.概念解释 Vue.extend和VueComponent是Vuejs框架中创建组件的两种不同方式。Vue.extend方法能够让你根据Vue对象(继承)来定义一个新的可重用的组件构造器。而VueComponent方…...

【动态规划】01背包问题(滚动数组 + 手画图解)
01背包除了可以用形象的二维动态数组表示外,还可以使用空间复杂度更低的一维滚动数组。 目录 文章目录 前言 一、滚动数组的基本理解 二、确定dp及其下标含义 三、确定递推公式 四、确定初始化 五、确定遍历顺序 1.用物品(正序)遍历背…...

javaEE 初阶 — 超时重传机制
文章目录超时重传机制1. 数据重复传输问题2. 如何解决数据重复传输问题3. 重传次数问题TCP 的工作机制:确认应答机制 超时重传机制 如果传输数据的时候丢包了该怎么办? 利用 超时重传,也就是超过了一定的时间,如果还没响应就重新…...
小米5x wlan无法打开解决
诱因:想要利用空置设备做节点服务器或者边缘计算,因此解锁并刷了magisk,印象中在刷之前wlan已经无法打开无法进行wifi联网 表现: 1 WLAN开关无法打开,或者虚假打开,无法扫描wifi 2 设置->我的设备->全…...
负载均衡之最小活跃数算法
文章目录[toc]一、概念二、场景与设计思路三、实现四、代码下载一、概念 活跃数 集群中各实例未处理的请求数。 最小活跃数 集群中各个实例,哪个实例未处理的请求数据最小,就称之为最小活跃数。 二、场景与设计思路 场景 以获取微服务地址为场景。 设计…...

JavaScript 评测代码运行速度的几种方法
一、使用 performance.now() API 在 JavaScript 中,可以使用 performance.now() API 来评测代码的运行速度。该 API 返回当前页面的高精度时间戳,您可以在代码执行前后调用它来计算代码执行所需的时间。 例如: let t0 performance.now();…...

Linux 编译器 gcc/g++
本文已收录至《Linux知识与编程》专栏! 作者:ARMCSKGT 演示环境:CentOS 7 目录 前言 正文 gcc/g常用命令 自定义可执行程序名命令-o 预处理指令-E 编译指令-S 汇编指令-c 链接指令gcc 命令巧记口诀 链接库 动态库-动态链接 静态库…...

2.Java基础【Java面试第三季】
2.Java基础【Java面试第三季】前言推荐2.Java基础01_字符串常量Java内部加载-上58同城的java字符串常量池面试code讲解intern()方法---源码解释02_字符串常量Java内部加载-下whyOpenJDK8底层源码说明递推步骤总结考查点03_闲聊力扣算法第一题字节跳动两数求和题目说明面试题解法…...

Java高级-多线程
本篇讲解java多线程 基本概念: 程序、进程、线程 **程序(program)**是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程,或是正在运行的一个程序。是一个动态的过程…...

mysql高级(事务、存储引擎、索引、锁、sql优化、MVCC)
文章目录1.事务1.1 四大特性ACID1.2 并发事务2.存储引擎2.1 InnoDB2.2 MyISAM2.3 Memory2.4 存储引擎特点2.5 存储引擎的选择3.性能分析3.1 查看执行频次3.2 慢查询日志3.3 profile3.4 explain4.索引4.1 索引结构B-TreeBTreeHash面试题4.2 索引分类思考题4.3 语法4.4 使用规则最…...

Java后端开发功能模块思路
文章目录前言一、查找接口及参数信息1.1 找访问路径1.2 参数及返回结果信息1.3 编写功能模块函数二、代码设计思路三、总结前言 对于正在学习Java后端开发的同学来说,对于Java后端功能模块的开发过程及思路要有一个整体清晰的流程。才能保证在开发过程中更加的顺畅…...

CAPL(vTESTStudio) - DoIP - TCP发送_05
TCP发送 参数定义 版本号:02 FD or 01 FE or 其他任意值数据类型:00 05 or 00 06 or 80 01 or其他任意值数据长度:想要发送的任意长度...

使用IntelliJ IDEA搭建datax-web开发环境
记录:372场景:使用IntelliJ IDEA搭建datax-web开发环境,以及datax-web基本使用。版本:JDK 1.8Python 2.7.5datax-web开源地址:https://github.com/WeiYe-Jing/datax-web1.配置Maven环境1.1安装目录目录:D:\…...

[SSD固态硬盘技术 14] GC垃圾回收太重要了
今天介绍臭名昭著的垃圾收集 过程(或“GC”),maybe 这是对JAVA 工程师而言。当遇到GC导致速度降低时候, 他们真的想跳脚。 我想到我的小孩打疫苗,哭的哇哇叫, 在他的眼里疫苗应该也是讨厌的吧, 但事实真的如此吗? 但首先,让我们考虑一下如果根本没有 GC,闪存系统会发…...

lamada表达式、stream、collect整理
lamada表达式格式 格式:( parameter-list ) -> { expression-or-statements } 实例:简化匿名内部类的写法 原本写法: public class LamadaTest { public static void main(String[] args) { new Thread(new Runnable() { …...

Nacos 入门微服务项目实战
Nacos 核心源码精讲 - IT贱男 - 掘金小册全方位源码精讲,深度剖析 Nacos 注册中心和配置中心的核心思想。「Nacos 核心源码精讲」由IT贱男撰写,375人购买https://s.juejin.cn/ds/BuC3Vs9/ Hi,大家好,欢迎大家来学习《Nacos 核心源…...

【c++】类和对象:让你明白“面向一个对象有多重要”:构造函数,析构函数,拷贝构造函数的深入学习
文章目录 什么是面向对象?一:类是什么? 1.类的访问限定符 2.封装 3.类的实例化 4.this指针二:类的6个默认成员函数 1.构造函数 2.析构函数 3.拷贝构造函数什么是面向对象? c语言是面向…...

职场IT老手教你3步教你玩转可视化大屏设计,让领导眼前一亮!
我是制造企业的IT中心的研发人员,平常工作就是配合业务部门出出报表,选型一些商业软件,并在内部负责实施运维。最近领导出去参观了一些数字化转型比较领先的工厂和制造企业,回来就甩给我几张图,问能不能我们也做几个这…...

【光伏功率预测】基于EMD-PCA-LSTM的光伏功率预测模型(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

大数据Kylin(二):Kylin安装使用
文章目录 Kylin安装使用 一、Kylin安装要求 二、Kylin安装 1、Kylin安装前环境准备...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
Bean 作用域有哪些?如何答出技术深度?
导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答,…...