Vue:extends继承&组件复用性

这篇具有很好参考价值的文章主要介绍了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:extends继承&组件复用性

        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 usage
          Sub.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-lookup
          if (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 constructor
          cachedCtors[SuperId] = Sub;
          return Sub;
      }

        通过查看Vue.extend()方法的源码,我们会发现,它内部是在调用Vue原型对象上面的_init()方法来完成组件初始化,通过如下图所示的一些核心配置,使其成为一个名副其实的Vue组件实例,

Vue:extends继承&组件复用性

         那么我们自己如何调用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:extends继承&组件复用性

        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:extends继承&组件复用性

        也可以通过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:extends继承&组件复用性

        通过对象的形式定义组件-这也是我们在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实现组件的继承。

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">&#xe75d;</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——点击事件回调方法。最终效果如下,

Vue:extends继承&组件复用性

         此种方式的不足之处在于:无法在子组件中添加template节点,否则会直接覆盖掉原有的template模板。

 文章来源地址https://www.toymoban.com/news/detail-473620.html

 

到了这里,关于Vue:extends继承&组件复用性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【延伸学习】TS(JS)类的继承(prototype、call、apply,extends)

    PS:文末附上完整的代码(是在CocosCreator下运行的) 一. 基(父)类   基类包含三个成员变量(名字、年龄)还有一个后面用于测试的数组,两个原型方法(输出名字,输出年龄),还有一个类似静态函数的方法。 基类唯一测试的,就是用类名可以直接调用eat这个静态方法。

    2024年01月25日
    浏览(42)
  • vue复用组件出现data-v-xxx乱码无法通过css修改指定样式

    vue复用组件出现data-v-xxx乱码无法通过css修改指定样式解决方案如下 选择需要修改的样式 给最高级父级元素定义新的classname 与原有样式保持相同级联 修改指定样式 .demo_parent .demo_son .demo_grandson[data-v-73a2ee76]{ padding: 0; border-radius: 3px; background: #fff; } 改为指定的样式 .demo_parent_s

    2024年02月21日
    浏览(49)
  • vue2中,vue.extend使用场景

    extend是Vue.js提供的一个构造器,用于创建一个组件的子类。它接受一个组件选项对象作为参数,并返回一个新的组件构造函数。 Vue.component是一个全局方法,用于注册全局组件。它接受两个参数,第一个参数是组件名称,第二个参数是组件选项对象。 extend用于在父组件内部创

    2024年02月07日
    浏览(44)
  • 高阶组件/react组件复用

                               

    2024年02月13日
    浏览(41)
  • Vue源码系列讲解——全局API篇【一】(Vue.extend)

    1.1 用法回顾 其用法如下: 参数 : {Object} options 作用 : 使用基础  Vue  构造器,创建一个“子类”。参数是一个包含组件选项的对象。 data  选项是特例,需要注意 - 在  Vue.extend()  中它必须是函数 结果如下: 1.2 原理分析 通过用法回顾我们知道, Vue.extend 的作用是创建一

    2024年03月14日
    浏览(49)
  • 鸿蒙开发OpenHarmony组件复用案例

    在开发应用时,有些场景下的自定义组件具有相同的组件布局结构,仅有状态变量等承载数据的差异。这样的组件缓存起来,需要使用到该组件时直接复用, 减少重复创建和渲染的时间,从而提高应用页面的加载速度和响应速度。 在OpenHarmony应用开发时,自定义组件被@Reus

    2024年01月19日
    浏览(68)
  • 前端组件开发指南:构建可复用、高效的用户界面

    在现代Web开发中,前端组件扮演着重要的角色。它们是构建用户界面的基本构建块,能够使开发人员更高效地开发、测试和维护代码。本文将带您深入了解前端组件的概念、优势以及如何使用常见的前端框架构建可复用的组件。 前端组件是一种封装了HTML、CSS和JavaScript代码的

    2024年02月16日
    浏览(50)
  • 组件与Props:React中构建可复用UI的基石

    目录 组件:构建现代UI的基本单位 Props:组件之间的数据传递 Props的灵活性:构建可配置的组件 组件间的通信:通过回调函数传递数据 总结: 组件:构建现代UI的基本单位 组件是前端开发中的关键概念之一。它允许我们将UI拆分成独立、可复用的部分,使得代码更易于理解

    2024年02月06日
    浏览(41)
  • 如何二次封装一个el-table组件并二次复用

    *注:示例使用的是vue3和element+进行二次封装的 表格数据操作按钮区域 表格信息提示区域 表格主体内容展示区域 表格分页区域 表单搜索没有封装在这里是为了降低代码的耦合性(有兴趣的可以查看我之前写的搜索框封装如何封装一个后管的输入框按钮组件基础版(可多次复用

    2024年02月16日
    浏览(48)
  • web JS高德地图标点、点聚合、自定义图标、自定义窗体信息、换肤等功能实现和高复用性组件封装教程

    突然发现官方更新点聚合调用方式多包一层mapObj.plugin([“AMap.MarkerClusterer”],fn)来加载聚合功能,之前直接通过new方式不生效,具体可以看下第6点和示例代码已做更新,感谢读者反馈。 本文将讲述如何利用高德地图JS API实现地图标点、聚合点、自定义图标、点击窗体信息展

    2024年02月04日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包