欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue中extends繼承和組件復(fù)用性詳解

 更新時間:2023年11月01日 11:02:00   作者:是席木木啊  
這篇文章主要給大家介紹了關(guān)于Vue中extends繼承和組件復(fù)用性的相關(guān)資料,組件(Component)是Vue.js最強(qiáng)大的功能之一,組件可以擴(kuò)展HTML元素,封裝可重用的代碼,需要的朋友可以參考下

前言

提到extends繼承,最先想到的可能是ES6中的class、TS中的interface、面向?qū)ο缶幊陶Z言中中的類和接口概念等等,但是我們今天的關(guān)注點在于:如何在Vue中使用extends繼承特性。

再開始探討Vue繼承相關(guān)的內(nèi)容之前,有必要回顧一下創(chuàng)建Vue組件實例的幾種方式,個人總結(jié)如下,

構(gòu)造函數(shù)方式:new Vue

這種方式是較為常見的,在Vue-cli腳手架構(gòu)建的前端項目中,經(jīng)??吹饺缦滤镜拇a段,

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

這就是在以Vue構(gòu)造函數(shù)的方式創(chuàng)建實例,然后將其掛載到id選擇器為app的DOM元素上。

Vue.extend方式

Vue.js開發(fā)庫提供了Vue.extend()API,用于創(chuàng)建一個組件。

Vue.extend()方法的源碼如下,內(nèi)部主要是創(chuàng)建了一個Vue組件對象,并通過外部配置項,將其props、computed、mixin等選項設(shè)置為可用,最終將對象返回,

/**
       * 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()方法的源碼,我們會發(fā)現(xiàn),它內(nèi)部是在調(diào)用Vue原型對象上面的_init()方法來完成組件初始化,通過如下圖所示的一些核心配置,使其成為一個名副其實的Vue組件實例,

那么我們自己如何調(diào)用Vue.extend()方法創(chuàng)建組件呢?示例代碼如下,

    /**
     * 方式1-Vue.extend-使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個組件
     * PS:此種方式中,data必須為函數(shù)
     * */
    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用途之一:將組件注冊到全局環(huán)境

Vue.component方式

 Vue.component()方法有兩個作用,其①:將組件注冊全局可用的組件;其②:以給定的id,創(chuàng)建一個全局范圍內(nèi)可用的組件。使用此接口創(chuàng)建一個Vue組件的示例代碼如下,

    /**
     * 方式2-Vue.component-間接調(diào)用Vue.extend,創(chuàng)建一個組件
     * PS:此種方式中,data必須為函數(shù)
     * */
    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創(chuàng)建的組件無需再注冊

render渲染函數(shù)方式

也可以通過Vue.js提供的render()渲染函數(shù)創(chuàng)建一個Vue組件,如下示例代碼,通過render函數(shù)的函數(shù),根據(jù)props參數(shù)level來創(chuàng)建了一個級別為level的h標(biāo)簽,并提供插槽供開發(fā)者對其進(jìn)行拓展。

 //方式3:基于渲染函數(shù)構(gòu)造函數(shù)式組件-[基于slot插槽方式提供組件內(nèi)容1]
    const ITitle = Vue.component(
      "i-title",
      {
      render: function (createElement) {
        return createElement(
          'h' + this.level,   // 標(biāo)簽名稱
          this.$slots.default // 子節(jié)點數(shù)組
        )
      },
      props: {
        level: {
          type: Number,
          required: true
        }
      }
    });

對象方式

通過對象的形式定義組件-這也是我們在Vue前端應(yīng)用開發(fā)中最常使用的方式,然后通過export default導(dǎo)出。示例代碼如下,

    //方式4-通過對象的形式定義組件-這也是我們在Vue前端應(yīng)用開發(fā)中最常使用的方式,然后通過export default導(dǎo)出
    const InfoBox = {
      name: "InfoBox",
      template: `<div class="box" :style="styleObject">{{content}}</div>`,
      data() {
        return {
          content: '消息內(nèi)容',
          styleObject: {
            boxSizing: "border-box",
            padding: "25px",
            width: '300px',
            height: '200px',
            backgroundColor: 'rgba(0,0,0,0.3)'
          }
        }
      }
    }
    Vue.component('info-box', InfoBox);//Vue.component用途之一:將組件注冊到全局環(huán)境

Vue:extends繼承特性

第一部分只介紹了如何創(chuàng)建一個組件,并沒有介紹如何去提高一個組件的復(fù)用性。既然談到復(fù)用性,可行的方法有很多,例如:slot插槽、mixix混入、Vue.directive自定義一個可復(fù)用的指令、通過Install方法開發(fā)一個可復(fù)用的插件、通過Vue.filter定義一個可復(fù)用的過濾器等。關(guān)于如上內(nèi)容,Vue官網(wǎng)都有詳細(xì)的介紹。

而接下來要討論的就是Vue官網(wǎng)里面介紹比較含蓄的一種方法:借助extends實現(xiàn)組件的繼承。

那么具體如何操作呢?我們先來定義一個基礎(chǔ)列表組件IList,并以事件委托的方式為每一個列表元素注冊點擊事件,示例代碼如下,

<!--
 * @Description: IList列表組件,基于事件委托機(jī)制對列表事件回調(diào)做了優(yōu)化處理
 * @Author: Xwd
 * @Date: 2023-02-16 00:21:49
 * @LastEditors: Xwd
 * @LastEditTime: 2023-02-19 17:03:25
 * @Attention: 此列表組件的clickHandler()點擊事件默認(rèn)基于index下標(biāo)來選擇性的返回item的值,在一些場景下存在風(fēng)險-->
<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: {
    /**
     * 列表元素點擊事件-回調(diào)函數(shù)
     * @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、點擊回調(diào)函數(shù)中的具體邏輯是什么?所以我們可以將次組件作為一個基組件,在后續(xù)使用過程中,在子組件TownList.vue中通過extends的選項,來繼承IList組件,實現(xiàn)復(fù)用。示例代碼如下,

<!--
 * @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:{
     /**
     * 列表元素點擊事件-回調(diào)函數(shù),覆寫父組件方法,基于元素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來區(qū)分每一個元素,并覆寫了父組件中的clickHandler——點擊事件回調(diào)方法。最終效果如下,

此種方式的不足之處在于:無法在子組件中添加template節(jié)點,否則會直接覆蓋掉原有的template模板。

總結(jié)

到此這篇關(guān)于Vue中extends繼承和組件復(fù)用性的文章就介紹到這了,更多相關(guān)Vue extends繼承和組件復(fù)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論