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

Vue3封裝全局函數(shù)式組件方法總結(jié)

 更新時(shí)間:2023年06月20日 10:49:45   作者:前端咸魚翻身  
函數(shù)式組件就是沒有管理任何狀態(tài),也沒有監(jiān)聽任何傳遞給它的狀態(tài),也沒有生命周期方法,它只是一個(gè)接受一些 prop 的函數(shù),下面這篇文章主要給大家介紹了關(guān)于Vue3封裝全局函數(shù)式組件方法的相關(guān)資料,需要的朋友可以參考下

前言

相信大家在 Vue 中考慮復(fù)用邏輯的時(shí)候經(jīng)常使用組件化開發(fā),也肯定使用過函數(shù)式組件,就是那種在 js 中也能夠?qū)胝{(diào)用的組件。那么如何去封裝這么一個(gè)函數(shù)式組件呢,這篇文章將采用Toast組件簡單介紹一下封裝的方法,封裝之后就能大大提高我們開發(fā)的效率了。

一、函數(shù)式組件是什么?

簡單介紹一下聲明式組件與函數(shù)式組件,大多數(shù)時(shí)候我們引入組件都采用聲明式的的方式,這里以 Vant 組件庫為例,類似 Button 按鈕這種就是聲明式組件:

<van-button type="primary">主要按鈕</van-button>

還有類似 <TheWelcome /> 這種自定義名稱且在 .vue 文件里引用其他 .vue 文件的就是聲明式組件

<template>
  <main>
    <TheWelcome />
  </main>
</template>
<script setup lang="ts">
import TheWelcome from '../components/TheWelcome.vue';
</script>

而函數(shù)式組件則是通過調(diào)用 API 的方式快速喚起全局的組件,還是以 Vant 組件庫為例,比如使用 Toast 組件,調(diào)用函數(shù)后會(huì)直接在頁面中渲染對應(yīng)的輕提示:

import { showToast } from 'vant';
showToast('提示內(nèi)容');

通常我們使用函數(shù)式組件是在某個(gè)交互完成時(shí)觸發(fā),又或者是在非.vue文件里喚起全局的組件,例如封裝axios,在axios.js中使用Toast組件顯示報(bào)錯(cuò)信息:

showToast('服務(wù)器響應(yīng)超時(shí),請刷新當(dāng)前頁');

二、創(chuàng)建一個(gè)函數(shù)式組件

下面將創(chuàng)建一個(gè)自己定義的toast組件,由于這個(gè)toast組件默認(rèn)是顯示成功的,所以稱之為“okToast”,先展示一下調(diào)用后的效果:

1. 封裝toast組件

與創(chuàng)建聲明式組件一致,在.vue文件里定義好組件接收的參數(shù)還有組件的樣式。代碼如下(示例):

<template>
  <!-- 加一點(diǎn)動(dòng)畫效果 -->
  <transition name="toast" @after-leave="onAfterLeave">
    <div class="toast" v-if="isShow" :style="{ width: toastWidth }">
      <!-- 手動(dòng)點(diǎn)擊隱藏彈窗 -->
      <div v-if="time < 0" class="cancel" @click="hidden"></div>
      <img
        v-if="type === 'success' || type === 'icon'"
        class="img"
        src="../../assets/images/7vip_web_toast_finish_icon_40x40@2x.png"
        alt="success"
      />
      <img v-if="type === 'warn'" class="img" src="../../assets/images/7vip_web_toast_warn.png" alt="warn" />
      <div v-if="content && type !== 'icon'" class="content" :style="{ textAlign }">{{ content }}</div>
    </div>
  </transition>
</template>
<script setup>
  import { ref, computed } from "vue";
  const props = defineProps({
    //文案內(nèi)容,默認(rèn)success
    content: {
      type: String,
      default: "success",
    },
    //顯示時(shí)間,默認(rèn)2s,傳小于0的值不自動(dòng)消失,需要手動(dòng)關(guān)閉
    time: {
      type: Number,
      default: 2000,
    },
    //寬度,默認(rèn)310px,這里考慮傳入的寬度可以用字符串也可以用數(shù)值,所以沒有定義類型
    width: {
      default: 310,
    },
    //彈窗文案文本對齊方式,默認(rèn)center
    textAlign: {
      type: String,
      default: "center",
    },
    //類型,默認(rèn)圖標(biāo)(√),傳'warn'顯示(?。瑐髌渌祫t不顯示icon,傳'icon'不顯示文本
    type: {
      type: String,
      default: "success",
    },
    //接收的函數(shù)方法
    hide: {
      type: Function,
      default: () => {},
    },
  });
  // 彈窗顯隱控制
  const isShow = ref(false);
  // 寬度控制,由于設(shè)計(jì)稿寬度是750px的寬度,這里通過計(jì)算屬性,根據(jù)設(shè)備屏幕寬度自適應(yīng)顯示彈窗的寬度
  const toastWidth = computed(() => (parseInt(props.width.toString()) / 750) * document.documentElement.clientWidth + "px");
  // 顯示彈窗方法
  const show = () => {
    isShow.value = true;
    if (props.time >= 0) {
      setTimeout(() => {
        isShow.value = false;
      }, props.time);
    }
  };
  // 隱藏彈窗方法
  const hidden = () => {
    isShow.value = false;
  };
  // 彈窗關(guān)閉后等動(dòng)畫結(jié)束再調(diào)用卸載邏輯
  const onAfterLeave = () => {
	props.hide();
  };
  // 將顯示彈窗方法暴露出去
  defineExpose({
    show,
  });
</script>
<style lang="scss" scoped>
  .toast-enter-active,
  .toast-leave-active {
    transition: opacity 0.3s ease-out;
  }
  .toast-enter-from,
  .toast-leave-to {
    opacity: 0;
  }
  .toast {
    position: fixed;
    top: 45%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 99;
    background: #333333;
    border-radius: 20px;
    padding: 40px;
    text-align: center;
    .cancel {
      background: url("../../assets/images/quxiao@2x.png") no-repeat center / contain;
      position: absolute;
      top: 10px;
      right: 10px;
      width: 40px;
      height: 40px;
      &::before {
        content: "";
        position: absolute;
        top: -10px;
        right: -10px;
        bottom: -10px;
        left: -10px;
      }
    }
    .img {
      width: 80px;
      height: 80px;
    }
    .content {
      margin-top: 20px;
      font-size: 32px;
      color: #ffcc99;
      line-height: 30px;
      text-align: initial;
    }
  }
</style>

2. 創(chuàng)建應(yīng)用實(shí)例

這是最關(guān)鍵的步驟,在 Vue2 的時(shí)候封裝函數(shù)式組件使用的是 Vue.extend,利用這個(gè)基礎(chǔ)的 Vue 構(gòu)造器,能創(chuàng)建Vue子類實(shí)例,然而在 Vue3 官方刪除了這個(gè)方法,但是也提供了新的api: createApp 給我們使用,利用 createApp 就能創(chuàng)建 Vue 應(yīng)用實(shí)例了。代碼如下(示例):

import { createApp } from "vue";
import OkToast from "./okToast.vue";
const okToast = options => {
  // 創(chuàng)建元素節(jié)點(diǎn)
  const rootNode = document.createElement("div");
  // 在body標(biāo)簽內(nèi)部插入此元素
  document.body.appendChild(rootNode);
  // 創(chuàng)建應(yīng)用實(shí)例(第一個(gè)參數(shù)是根組件。第二個(gè)參數(shù)可選,它是要傳遞給根組件的 props)
  const app = createApp(OkToast, {
    ...options,
    hide() {
      // 卸載已掛載的應(yīng)用實(shí)例
      app.unmount();
      // 刪除rootNode節(jié)點(diǎn)
      document.body.removeChild(rootNode);
    },
  });
  // 將應(yīng)用實(shí)例掛載到創(chuàng)建的 DOM 元素上
  return app.mount(rootNode);
};
// 注冊插件app.use()會(huì)自動(dòng)執(zhí)行install函數(shù)
okToast.install = app => {
  // 注冊全局屬性,類似于 Vue2 的 Vue.prototype
  app.config.globalProperties.$okToast = options => okToast(options).show();
};
// 定義show方法用于直接調(diào)用
okToast.show = options => okToast(options).show();
export default okToast;

3. 注冊插件(可省略)

代碼如下(示例):

// main.js
import okToast from './plugins/okToast/index';

app.use(okToast);

Q&A: 補(bǔ)充一些注釋

①:為什么采用調(diào)用函數(shù)方法的方式去控制顯隱

答:目的是為了那個(gè)顯示與消失的動(dòng)畫效果,當(dāng)組件創(chuàng)建后需要組件內(nèi) ”isShow“ 產(chǎn)生變化才能觸發(fā)<Transition> 的動(dòng)畫效果,所以這里寫了show函數(shù)方法。

②:函數(shù)式組件的這兩個(gè)文件之間的聯(lián)系

答:簡單來說,js文件傳參數(shù)及函數(shù)給vue文件,均可在 createApp 的第二個(gè)參數(shù)中傳遞,vue文件相當(dāng)于子組件,使用props的方式接收;vue文件傳值及函數(shù)給js文件,可以通過 defineExpose 方法暴露出去,js文件中在應(yīng)用實(shí)例創(chuàng)建完成后,就能拿到暴露出來的屬性及方法。

三、調(diào)用

1. 注冊插件后在.vue文件內(nèi)獲取全局方法

<script setup>
import { getCurrentInstance } from 'vue';
// 獲取當(dāng)前實(shí)例,在當(dāng)前實(shí)例相當(dāng)于 vue2 中的 this
const { proxy }: any = getCurrentInstance();
// 最簡單的調(diào)用方式,即可出來開頭所展示的效果
proxy.$okToast();
// 傳遞自定義參數(shù),與okToast.vue文件接收的參數(shù)對應(yīng)
setTimeout(() => {
  proxy.$okToast({
	content: 'Hello World'
  });
}, 2000);
</script>

2. 可不注冊插件,在.vue或.js文件內(nèi)直接調(diào)用方法

import $okToast from "./plugs/okToast";

$okToast.show({
  type: "warn",
  content: "Network error,try again later",
});

四、優(yōu)化改進(jìn)

上面封裝的Toast組件在創(chuàng)建多個(gè)實(shí)例的時(shí)候,它們之間是互不干擾的,不會(huì)存在組件參數(shù)異常的情況。那么實(shí)際觀察 DOM 元素我們會(huì)發(fā)現(xiàn)其在 DOM 上是存在多個(gè)的,只不過當(dāng)多次調(diào)用的時(shí)候,后面的會(huì)把前面還沒消失的Toast覆蓋了,這樣效果可能不那么友好。那么就存在兩個(gè)優(yōu)化方向:一是當(dāng)后續(xù)出現(xiàn)Toast的時(shí)候結(jié)束掉前面出現(xiàn)的Toast,二是調(diào)整后續(xù)Toast出現(xiàn)的位置。

1、單例模式(推薦)

先上代碼(示例):

let rootNode = null;
let app = null;
const okToast = options => {
  const dom = document.body.querySelector('.my-ok-toast');
  if (!dom) {
    rootNode = document.createElement('div');
    // 給創(chuàng)建的元素設(shè)置 class 屬性值
    rootNode.className = `my-ok-toast`;
    document.body.appendChild(rootNode);
  } else {
    // If you want to mount another app on the same host container, you need to unmount the previous app by calling `app.unmount()` first.
    app.unmount();
  }
  app = createApp(OkToast, {
    ...options,
    hide() {
      // 卸載已掛載的應(yīng)用實(shí)例
      if (app) {
        app.unmount();
        app = null;
      }
      // 刪除rootNode節(jié)點(diǎn)
      if (rootNode) {
        document.body.removeChild(rootNode);
        rootNode = null;
      }
    }
  });
  return app.mount(rootNode);
};

效果展示:

請?zhí)砑訄D片描述

怎么去結(jié)束前面出現(xiàn)的Toast呢,我們只需要確保全局只渲染一個(gè)Toast彈窗就行,所以可以使用單例模式,單例模式即一個(gè)類只能有一個(gè)實(shí)例。類似Vant的Toast組件,其默認(rèn)采用了單例模式,即同一時(shí)間只會(huì)存在一個(gè),這種做法應(yīng)該是普遍的彈窗做法。

2、多個(gè)提示彈窗

先上代碼(示例):

// 創(chuàng)建臨時(shí)變量保存高度值
let top = 0;
const okToast = options => {
  const rootNode = document.createElement('div');
  // 給創(chuàng)建的元素設(shè)置 class 屬性值
  rootNode.className = `my-ok-toast`;
  document.body.appendChild(rootNode);
  const dom = document.body.querySelector('.my-ok-toast');
  // 若DOM中存在該元素則將新元素高度往下移動(dòng)
  if (dom) {
    top += 120;
    rootNode.style.top = 80 + top + 'px';
  }
  const app = createApp(OkToast, {
    ...options,
    hide() {
      app.unmount();
      document.body.removeChild(rootNode);
    }
  });
  return app.mount(rootNode);
};

再將css樣式添加到全局上

.my-ok-toast {
  position: fixed;
  z-index: 99;
  top: 80px;
  left: 50%;
  transform: translateX(-50%);
}

效果展示:

請?zhí)砑訄D片描述

這里的做法提供給大家一種思路,實(shí)際的動(dòng)畫效果還有待優(yōu)化,由于本文篇幅有限所以就不展開了,以后遇到這種需求再深入探索吧。

總結(jié)

以上就是全部內(nèi)容,本文簡單介紹了 Vue3 函數(shù)式組件的封裝方法,將其以插件的方式使用app.use() 方法安裝在 Vue 上,使其作為全局功能的工具,這就是 Vue3 中邏輯復(fù)用的插件 (Plugins) 寫法。

如果此篇文章對您有幫助,歡迎您【點(diǎn)贊】、【收藏】!也歡迎您【評論】留下寶貴意見,共同探討一起學(xué)習(xí)~

擴(kuò)展閱讀

  1. Vue3 插件
  2. Vant Toast 輕提示

到此這篇關(guān)于Vue3封裝全局函數(shù)式組件方法的文章就介紹到這了,更多相關(guān)Vue3封裝全局函數(shù)式組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺入深出Vue之自動(dòng)化路由

    淺入深出Vue之自動(dòng)化路由

    這篇文章主要介紹了淺入深出Vue之自動(dòng)化路由,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • VUE實(shí)現(xiàn)注冊與登錄效果

    VUE實(shí)現(xiàn)注冊與登錄效果

    這篇文章主要為大家詳細(xì)介紹了VUE實(shí)現(xiàn)注冊與登錄效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • vue3+vite動(dòng)態(tài)加載路由,本地路由和線上路由匹配方式

    vue3+vite動(dòng)態(tài)加載路由,本地路由和線上路由匹配方式

    這篇文章主要介紹了vue3+vite動(dòng)態(tài)加載路由,本地路由和線上路由匹配方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 關(guān)于vue3編寫掛載DOM的插件問題

    關(guān)于vue3編寫掛載DOM的插件問題

    這篇文章主要介紹了vue3編寫掛載DOM的插件的問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-07-07
  • 基于mpvue的簡單彈窗組件mptoast使用詳解

    基于mpvue的簡單彈窗組件mptoast使用詳解

    這篇文章主要介紹了基于mpvue的簡單彈窗組件mptoast使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • 深入理解vue中的scoped屬性

    深入理解vue中的scoped屬性

    vue中的 scoped 屬性,其實(shí)就是給每一個(gè)dom節(jié)點(diǎn)元素都添加了不重復(fù)的自定義屬性(如:data-v-6810cbe5),本文給大家介紹vue中的scoped屬性相關(guān)知識,感興趣的朋友一起看看吧
    2023-12-12
  • vue ajax 攔截原理與實(shí)現(xiàn)方法示例

    vue ajax 攔截原理與實(shí)現(xiàn)方法示例

    這篇文章主要介紹了vue ajax 攔截原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了vue.js基于ajax攔截實(shí)現(xiàn)無刷新登錄的相關(guān)原理與操作技巧,需要的朋友可以參考下
    2019-11-11
  • Vue3中watch監(jiān)聽器及源碼學(xué)習(xí)

    Vue3中watch監(jiān)聽器及源碼學(xué)習(xí)

    本文主要介紹了Vue3中watch監(jiān)聽器及源碼學(xué)習(xí),Watch偵聽器在Vue3中特性進(jìn)行了一些改變和優(yōu)化,下面來詳解的介紹一下基本使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Vue3異步數(shù)據(jù)加載組件suspense的使用方法

    Vue3異步數(shù)據(jù)加載組件suspense的使用方法

    前端開發(fā)中異步請求是非常常見的事情,比如遠(yuǎn)程讀取圖片,調(diào)用后端接口等等,這篇文章主要給大家介紹了關(guān)于Vue3異步數(shù)據(jù)加載組件suspense的使用方法,suspense中文含義是懸念的意思,需要的朋友可以參考下
    2021-08-08
  • Vuex總體案例詳解

    Vuex總體案例詳解

    這篇文章主要介紹了Vuex總體案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09

最新評論