Vue:extends继承组件复用性
提到extends继承,最先想到的可能是ES6中的class、TS中的interface、面向对象编程语言中中的类和接口概念等等,但是我们今天的关注点在于:如何在Vue中使用extends继承特性。
目录
Vue:创建Vue实例的方式
构造函数方式:new Vue
Vue.extend方式
Vue.component方式
render渲染函数方式
对象方式
Vue:extends继承特性
Vue:创建Vue实例的方式
再开始探讨Vue继承相关的内容之前,有必要回顾一下创建Vue组件实例的几种方式,个人总结如下,
构造函数方式:new Vue
这种方式是较为常见的,在Vue-cli脚手架构建的前端项目中,经常看到如下所示的代码段,
new Vue({router,store,render: h => h(App)
}).$mount('#app')
这就是在以Vue构造函数的方式创建实例,然后将其挂载到id选择器为app的DOM元素上。
Vue.extend方式
Vue.js开发库提供了Vue.extend()API,用于创建一个组件。

Vue.extend()方法的源码如下,内部主要是创建了一个Vue组件对象,并通过外部配置项,将其props、computed、mixin等选项设置为可用,最终将对象返回,
/*** Class inheritance*/Vue.extend = function (extendOptions) {extendOptions = extendOptions || {};//外部配置项-即:Vue组件的选项配置console.log(extendOptions)var Super = this;//指向Vue自身实例的引用var SuperId = Super.cid;var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});if (cachedCtors[SuperId]) {return cachedCtors[SuperId];}var name = getComponentName(extendOptions) || getComponentName(Super.options);if (name) {validateComponentName(name);}var Sub = function VueComponent(options) {this._init(options);};Sub.prototype = Object.create(Super.prototype);Sub.prototype.constructor = Sub;Sub.cid = cid++;Sub.options = mergeOptions(Super.options, extendOptions);Sub['super'] = Super;// For props and computed properties, we define the proxy getters on// the Vue instances at extension time, on the extended prototype. This// avoids Object.defineProperty calls for each instance created.if (Sub.options.props) {initProps(Sub);}if (Sub.options.computed) {initComputed(Sub);}// allow further extension/mixin/plugin usageSub.extend = Super.extend;Sub.mixin = Super.mixin;Sub.use = Super.use;// create asset registers, so extended classes// can have their private assets too.ASSET_TYPES.forEach(function (type) {Sub[type] = Super[type];});// enable recursive self-lookupif (name) {Sub.options.components[name] = Sub;}// keep a reference to the super options at extension time.// later at instantiation we can check if Super's options have// been updated.Sub.superOptions = Super.options;Sub.extendOptions = extendOptions;Sub.sealedOptions = extend({}, Sub.options);// cache constructorcachedCtors[SuperId] = Sub;return Sub;}
通过查看Vue.extend()方法的源码,我们会发现,它内部是在调用Vue原型对象上面的_init()方法来完成组件初始化,通过如下图所示的一些核心配置,使其成为一个名副其实的Vue组件实例,

那么我们自己如何调用Vue.extend()方法创建组件呢?示例代码如下,
/*** 方式1-Vue.extend-使用基础 Vue 构造器,创建一个组件* PS:此种方式中,data必须为函数* */const IButton = Vue.extend({name: "IButton",template: `<button class="btn" @click="clickBtnHandler($event)">Click</button>`,methods: {clickBtnHandler(e) {console.log(e.target.dataset)}},})Vue.component('i-button', IButton);//Vue.component用途之一:将组件注册到全局环境
Vue.component方式

Vue.component()方法有两个作用,其①:将组件注册全局可用的组件;其②:以给定的id,创建一个全局范围内可用的组件。使用此接口创建一个Vue组件的示例代码如下,
/*** 方式2-Vue.component-间接调用Vue.extend,创建一个组件* PS:此种方式中,data必须为函数* */const IList = Vue.component('i-list', {template: `<div><p>列表</p><ul><li v-for="n in number">{{n}}</li></ul></div>`,data: function () {return {number: 5}}})// Vue.component('i-list', IList);//Vue.component创建的组件无需再注册
render渲染函数方式

也可以通过Vue.js提供的render()渲染函数创建一个Vue组件,如下示例代码,通过render函数的函数,根据props参数level来创建了一个级别为level的h标签,并提供插槽供开发者对其进行拓展。
//方式3:基于渲染函数构造函数式组件-[基于slot插槽方式提供组件内容1]const ITitle = Vue.component("i-title",{render: function (createElement) {return createElement('h' + this.level, // 标签名称this.$slots.default // 子节点数组)},props: {level: {type: Number,required: true}}});
对象方式

通过对象的形式定义组件-这也是我们在Vue前端应用开发中最常使用的方式,然后通过export default导出。示例代码如下,
//方式4-通过对象的形式定义组件-这也是我们在Vue前端应用开发中最常使用的方式,然后通过export default导出const InfoBox = {name: "InfoBox",template: `<div class="box" :style="styleObject">{{content}}</div>`,data() {return {content: '消息内容',styleObject: {boxSizing: "border-box",padding: "25px",width: '300px',height: '200px',backgroundColor: 'rgba(0,0,0,0.3)'}}}}Vue.component('info-box', InfoBox);//Vue.component用途之一:将组件注册到全局环境
Vue:extends继承特性
第一部分只介绍了如何创建一个组件,并没有介绍如何去提高一个组件的复用性。既然谈到复用性,可行的方法有很多,例如:slot插槽、mixix混入、Vue.directive自定义一个可复用的指令、通过Install方法开发一个可复用的插件、通过Vue.filter定义一个可复用的过滤器等。关于如上内容,Vue官网都有详细的介绍。
而接下来要讨论的就是Vue官网里面介绍比较含蓄的一种方法:借助extends实现组件的继承。

那么具体如何操作呢?我们先来定义一个基础列表组件IList,并以事件委托的方式为每一个列表元素注册点击事件,示例代码如下,
<!--* @Description: IList列表组件,基于事件委托机制对列表事件回调做了优化处理* @Author: Xwd* @Date: 2023-02-16 00:21:49* @LastEditors: Xwd* @LastEditTime: 2023-02-19 17:03:25* @Attention: 此列表组件的clickHandler()点击事件默认基于index下标来选择性的返回item的值,在一些场景下存在风险-->
<template><div class="i-list"><p v-if="!!title" class="i-title">{{ title }}</p><!-- <div class="split-horizon"></div> --><div v-if="(list || []).length > 0" class="i-content" @click="clickHandler($event)"><div class="i-item" v-for="(item, index) in list" :key="index"><img class="i-item-icon" :src="item.image || noImage" /><div class="i-item-body"><div class="i-item-title">{{ item.title }}<span class="iconfont" title="地图定位" :data-id="item.id":data-index="index"></span></div><div class="i-item-desc" :title="item.desc">{{ item.desc }}</div></div></div></div></div>
</template>
<script>
import noImage from '@/assets/images/no.png';
export default {name: "IList",props: {title: {type: String,required: false,default: "",},list: {type: Array,required: false,default: () => [],}},mounted() { },methods: {/*** 列表元素点击事件-回调函数* @param {*} event */clickHandler(event) {const index = event.target.dataset.index;if (typeof index !== "undefined" && index !== null) {this.$emit("click", this.list[Number(index)], Number(index));}}}
}
</script>
<style lang="less" scoped></style>
而由于我们存在一些不确定因素,例如:props中的list是否具有唯一id、点击回调函数中的具体逻辑是什么?所以我们可以将次组件作为一个基组件,在后续使用过程中,在子组件TownList.vue中通过extends的选项,来继承IList组件,实现复用。示例代码如下,
<!--* @Description: * @Author: Xwd* @Date: 2023-02-19 16:50:16* @LastEditors: Xwd* @LastEditTime: 2023-02-19 16:56:57
-->
<script>
import IList from '@/components/layout/IList.vue';
export default {name:"TownList",extends:IList,methods:{/*** 列表元素点击事件-回调函数,覆写父组件方法,基于元素id值重定义处理逻辑* @param {*} event 事件对象*/clickHandler(event) {const id = event.target.dataset.id;console.log(`id=${id}`)if (typeof id !== "undefined" && id !== null) {const dataIndex = this.list.findIndex(item => item.id == id);dataIndex !== -1 & this.$emit("click", this.list[dataIndex], dataIndex)}}}
}
</script>
此处我们通过id来区分每一个元素,并覆写了父组件中的clickHandler——点击事件回调方法。最终效果如下,

此种方式的不足之处在于:无法在子组件中添加template节点,否则会直接覆盖掉原有的template模板。
相关文章:
Vue:extends继承组件复用性
提到extends继承,最先想到的可能是ES6中的class、TS中的interface、面向对象编程语言中中的类和接口概念等等,但是我们今天的关注点在于:如何在Vue中使用extends继承特性。 目录 Vue:创建Vue实例的方式 构造函数方式࿱…...
ChatGPT 的一些思考
最近 ChatGPT3.5 在全世界范围内掀起了一次 AI 的潮流,ChatGPT1.0/ChatGPT2.0 当时也是比较火爆,但是那个当时感觉还是比较初级的应用,相当于是一个进阶版的微软小冰,给人的感觉是有一点智能,但不多。其实从早期版本开…...
GEE学习笔记 六十九:【GEE之Python版教程三】Python基础编程一
环境配置完成后,那么可以开始正式讲解编程知识。之前我在文章中也讲过,GEE的python版接口它是依赖python语言的。目前很多小伙伴是刚开始学习GEE编程,之前或者没有编程基础,或者是没有学习过python。为了照顾这批小伙伴࿰…...
大数据全系安装
内容版本号CentOS7.6.1810ZooKeeper3.4.6Hadoop2.9.1HBase1.2.0MySQL5.6.51HIVE2.3.7Sqoop1.4.6flume1.9.0kafka2.8.1scala2.12davinci3.0.1spark2.4.8flink1.13.5 1. 下载CentOS 7镜像 CentOS官网 2. 安装CentOS 7系统——采用虚拟机方式 2.1 新建虚拟机 2.2.1 [依次选择]-&…...
stable-diffusion-webui 安装使用
文章目录1.github 下载,按教程运行2.安装python 忘记勾选加入环境变量,自行加入(重启生效)3.环境变量添加后,清理tmp ,venv重新运行4.运行报错,无法升级pip,无法下载包,5…...
3D点云处理:点云聚类--FEC: Fast Euclidean Clustering for Point Cloud Segmentation
文章目录 聚类结果一、论文内容1.1 Ground Surface Removal1.2 Fast Euclidean Clustering题外:欧几里得聚类Fast Euclidean Clustering二、参考聚类结果 原始代码中采用的是pcl中的搜索方式,替换为另外第三方库,速度得到进一步提升。 一、论文内容 论文中给出的结论:该…...
华为OD机试题 - 射击比赛(JavaScript)| 代码+思路+重要知识点
最近更新的博客 华为OD机试题 - 括号检查(JavaScript) 华为OD机试题 - 最小施肥机能效(JavaScript) 华为OD机试题 - 子序列长度(JavaScript) 华为OD机试题 - 众数和中位数(JavaScript) 华为OD机试题 - 服务依赖(JavaScript) 华为OD机试题 - 字符串加密(JavaScript)…...
流程引擎之Flowable简介
背景Flowable 是一个流行的轻量级的采用 Java 开发的业务流程引擎,通过 Flowable 流程引擎,我们可以部署遵循 BPMN2.0 协议的流程定义(一般为XML文件)文件,并能创建流程实例,查询和访问流程相关的实例与数据…...
AcWing:4861. 构造数列、4862. 浇花(C++)
目录 4861. 构造数列 问题描述: 实现代码: 4862. 浇花 问题描述: 实现代码: 4861. 构造数列 问题描述: 我们规定如果一个正整数满足除最高位外其它所有数位均为 00,则称该正整数为圆数。 例如&…...
进程的概念
进程的概念 程序的概念 这里说的是一个可执行文件,passive的意思可以理解为我们这个执行文件需要我们进行双击才会被被执行。 双击后,程序入口地址读入寄存器,程序加载入主存,成为一个进程 进程是主动去获取想要的资源࿰…...
自动化测试5年经验,分享一些心得
自动化测试介绍 自动化测试(Automated Testing),是指把以人为驱动的测试行为转化为机器执行的过程。实际上自动化测试往往通过一些测试工具或框架,编写自动化测试用例,来模拟手工测试过程。比如说,在项目迭代过程中,持…...
independentsoft.de/MSG .NET Framework Crack
MSG .NET 是用于 .NET Framework / .NET Core 的 Microsoft Outlook .msg 文件 API。API 允许您轻松创建/读取/解析/转换 .msg 文件等。API 不需要在机器上安装 Microsoft Outlook 或任何其他第三方应用程序或库即可工作。 以下示例向您展示了如何打开现有文件并显示消息的某些…...
基于Transformer的NLP处理管线
HuggingFace transformers 是一个整合了跨语言、视觉、音频和多模式模态与最先进的预训练模型并且提供用户友好的 API 的AI开发库。 它由 170 多个预训练模型组成,支持 PyTorch、TensorFlow 和 JAX 等框架,能够在代码之间进行互操作。 这个库还易于部署&…...
二叉树OJ(一)二叉树的最大深度 二叉搜索树与双向链表 对称的二叉树
二叉树的最大深度 二叉树中和为某一值的路径(一) 二叉搜索树与双向链表 对称的二叉树 二叉树的最大深度 描述 求给定二叉树的最大深度, 深度是指树的根节点到任一叶子节点路径上节点的数量。 最大深度是所有叶子节点的深度的最大值。 (注:…...
使用Fairseq进行Bart预训练
文章目录前言环境流程介绍数据部分分词部分预处理部分训练部分遇到的问题问题1可能遇到的问题问题1问题2前言 本文是使用 fairseq 做 Bart 预训练任务的踩坑记录huggingface没有提供 Bart 预训练的代码 facebookresearch/fairseq: Facebook AI Research Sequence-to-Sequence…...
n阶数字回转方阵 ← 模拟法
【问题描述】 请编程输出如下数字回旋方阵。 【算法代码】 #include <bits/stdc.h> using namespace std;const int maxn100; int z[maxn][maxn];void matrix(int n) {int num2;z[0][0]1;int i0,j1;while(i<n && j<n) {while(i<j) z[i][j]num;while(j&…...
【人工智能AI】二、NoSQL 基础知识《NoSQL 企业级基础入门与进阶实战》
写一篇介绍 NoSQL 基础知识的技术文章,分5个章节,每个章节细分到3级目录,重点介绍一下NoSQL 数据模型,NoSQL 数据库架构,NoSQL 数据库特性等,不少于2000字。 NoSQL 基础知识 NoSQL(Not Only SQ…...
Camera Rolling Shutter和Global Shutter的区别
卷帘快门(Rolling Shutter)与全局快门(Global Shutter)的区别 什么是快门 快门是照相机用来控制感光片有效曝光时间的机构。 快门是照相机的一个重要组成部分,它的结构、形式及功能是衡量照相机档次的一个重要因素。 …...
模版之AnyType
title: 模版之AnyType date: 2023-02-19 21:49:53 permalink: /pages/54a0bf/ categories: 通用领域编程语言C tags:C元编程 author: name: zhengzhibing link: https://azmddy.top/pages/54a0bf/ 模版之AnyType 在研究C的编译期反射时,发现了AnyType很有意思。 首…...
【汇编】一、环境搭建(一只 Assember 的成长史)
嗨~你好呀! 我是一名初二学生,热爱计算机,码龄两年。最近开始学习汇编,希望通过 Blog 的形式记录下自己的学习过程,也和更多人分享。 这篇文章主要讲述汇编环境的搭建过程。 话不多说~我们开始吧! 系统环…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
