AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

Vue 中可重用組件的 3 個主要問題

來源: 責編: 時間:2023-10-17 09:38:38 243觀看
導讀當我們談論或討論在 Vue 中創(chuàng)建用戶界面組件時,經(jīng)常會提到可重用性。沒錯,Vue 的關鍵原則之一就是其基于組件的架構,這促進了可重用性和模塊化。但這到底意味著什么呢?比方說,你創(chuàng)建了一個可重復使用的組件:你或你的同事真
當我們談論或討論在 Vue 中創(chuàng)建用戶界面組件時,經(jīng)常會提到可重用性。沒錯,Vue 的關鍵原則之一就是其基于組件的架構,這促進了可重用性和模塊化。但這到底意味著什么呢?

比方說,你創(chuàng)建了一個可重復使用的組件:oM628資訊網(wǎng)——每日最新資訊28at.com

  • 你或你的同事真的能在系統(tǒng)的另一個部分重復使用它嗎?
  • 有了新的需求,你可能不得不考慮修改 "可重復使用的組件"。
  • 如果需要拆分 "可重用組件",以便將拆分后的組件應用到其他地方,該怎么辦?

在 Vue 中創(chuàng)建真正的可重用組件可能很棘手。在本文中,我將探討可重用組件的概念、應用這些組件時面臨的問題,以及為什么必須盡可能克服這些問題。oM628資訊網(wǎng)——每日最新資訊28at.com

什么是可重用組件?

可重用組件是用戶界面構件,可用于應用程序的不同部分,甚至多個項目。它們封裝了特定的功能或用戶界面模式,可以輕松集成到應用程序的其他部分,而無需進行大量修改。oM628資訊網(wǎng)——每日最新資訊28at.com

可重復使用組件的優(yōu)勢

  • 效率:允許開發(fā)人員一次編寫代碼并多次重復使用。這樣可以減少冗余,節(jié)省寶貴的開發(fā)時間。
  • 標準化:促進整個 Vue 項目的一致性和標準化。它們可確保在整個應用程序中保持相同的設計模式、樣式和功能。
  • 可擴展性:隨著項目的增長,更容易擴展和調整項目。通過將應用程序分解成更小的、可重復使用的組件,可以更容易地處理復雜功能和添加新功能。
  • 協(xié)作:促進團隊成員在 Vue 項目中的協(xié)作。它們提供了團隊中每個人都能使用和理解的共享詞匯和用戶界面元素集。

應用可重復使用概念時的 3 個問題

雖然可重用性是 Vue. 組件的一個理想特性,但有幾個問題會使其難以實現(xiàn):oM628資訊網(wǎng)——每日最新資訊28at.com

  • 修改現(xiàn)有組件:一個問題是修改應用程序中已經(jīng)使用的現(xiàn)有組件。可能需要對組件進行修改,以同時支持現(xiàn)有需求和新需求。對應用程序其他部分已經(jīng)使用的組件進行修改,可能會帶來意想不到的副作用,并破壞其他部分的功能。在變更需求與保持兼容性之間取得平衡可能很復雜。
  • 設計組件的一致性和靈活性:另一個問題是在可重復使用組件的不同實例之間保持一致性,同時允許自定義和靈活性。可重用組件應具有足夠的通用性,以適應不同的設計要求和風格。然而,在提供定制選項的同時又不犧牲組件的核心功能和一致性可能會很棘手。
  • 管理組件依賴關系和狀態(tài):使用可重復使用的組件需要管理依賴關系,并確保每個組件保持自足和獨立。組件不應緊密依賴外部資源或應用程序的狀態(tài)管理系統(tǒng)。這樣可以輕松集成到不同的項目中,減少沖突或意外副作用的可能性。

案例

比方說,客戶想要一個內部員工目錄系統(tǒng)。該項目采用敏捷方法,開發(fā)前無法收集所有需求。項目分為三個階段(原型、第一階段和第二階段)。在本演示中,我將重點介紹一個卡片組件,如下所示:oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

原型

作為原型階段的一部分,我需要提供一個用戶配置文件頁面。用戶配置文件將包含一個基本的用戶卡組件,其中包括用戶頭像和姓名。oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

// Prototype.vue<script setup lang="ts">    import { defineProps, computed, Teleport, ref } from "vue";    interface Props {        firstName: string;        lastName: string;        image?: string;    }    const props = defineProps<Props>();</script><template>    <div class="app-card">        <img            class="user-image"            :src="image"            alt="avatar" />        <div>            <div>                <label> {{ firstName }} {{ lastName }} </label>            </div>        </div>    </div></template><style scoped>    .app-card {        padding-left: 10px;        padding-right: 10px;        padding-top: 5px;        padding-bottom: 5px;        background: white;        box-shadow: 0 0 5px;        border-radius: 5px;        border: none;        font-size: 1.5em;        transition: 0.3s;        display: flex;        align-items: center;    }    .app-card label {        font-weight: 600;    }    .app-card:hover {        background: rgba(128, 128, 128, 0.5);    }    .user-image {        width: 100px;    }</style>

第 1 階段

在第一階段,客戶希望在用戶卡組件中添加用戶詳細信息(生日、年齡、電話號碼和電子郵件)。oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

//Phase1.vue<script setup lang="ts">    import { defineProps, computed } from "vue";    interface Props {        firstName: string;        lastName: string;        image?: string;        birthDay?: string;        phone?: string;        email?: string;    }    const props = defineProps<Props>();    const age = computed(() => {        if (!props.birthDay) {            return "0";        }        const birthYear = new Date(props.birthDay).getFullYear();        const currentYear = new Date().getFullYear();        return currentYear - birthYear;    });</script><template>    <div        ref="cardRef"        class="app-card">        <img            class="user-image"            :src="image"            alt="avatar" />        <div>            <div>                <label> {{ firstName }} {{ lastName }} </label>            </div>            <div>                <div>                    <label> Birth day: </label>                    <span>                        {{ birthDay }}                    </span>                </div>                <div>                    <label> Age: </label>                    <span>                        {{ age }}                    </span>                </div>                <div>                    <label> Phone number: </label>                    <span>                        {{ phone }}                    </span>                </div>                <div>                    <label> Email: </label>                    <span>                        {{ email }}                    </span>                </div>            </div>        </div>    </div></template><style scoped>    .app-card {        padding-left: 10px;        padding-right: 10px;        padding-top: 5px;        padding-bottom: 5px;        background: white;        box-shadow: 0 0 5px;        border-radius: 5px;        border: none;        font-size: 1.5em;        transition: 0.3s;        display: flex;        align-items: center;    }    .app-card label {        font-weight: 600;    }    .app-card:hover {        background: rgba(128, 128, 128, 0.5);        color: black;    }    .user-image {        width: 100px;    }</style>

此外,客戶還希望添加員工名錄頁面,并以卡片格式顯示用戶資料。oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

// SearchPage<template>    <div>        <SearchInput v-model:value="searchValue" />        <template            :key="item.id"            v-for="item of list">            <div style="margin-bottom: 5px; margin-top: 5px">                <UserCard v-bind="item" />            </div>        </template>    </div></template><script lang="ts">    import SearchInput from "../components/SearchInput.vue";    import UserCard from "../components/Phase1.vue";    import { ref, watch } from "vue";    export default {        name: "Search",        components: {            SearchInput,            UserCard,        },        setup() {            const searchValue = ref<string>();            const list = ref();            fetch("https://dummyjson.com/users")                .then((res) => res.json())                .then((res) => (list.value = res.users));            watch(searchValue, (v) => {                fetch(`https://dummyjson.com/users/search?q=${v}`)                    .then((res) => res.json())                    .then((res) => (list.value = res.users));            });            watch(list, (v) => console.log(v));            return {                searchValue,                list,            };        },    };</script>

在這一階段,用戶卡組件可在兩個頁面上重復使用。oM628資訊網(wǎng)——每日最新資訊28at.com

第二階段

用戶反饋 "員工名錄 "頁面雜亂無章。過多的信息使頁面難以使用。因此,客戶希望在鼠標懸停時以工具提示的形式顯示用戶詳細信息。用戶設置頁面的要求保持不變。oM628資訊網(wǎng)——每日最新資訊28at.com

// Phase 2<script setup lang="ts">import {  defineProps,  computed,  Teleport,  ref,  onMounted,  onBeforeUnmount,} from "vue";interface Props {  firstName: string;  lastName: string;  image?: string;  birthDate?: string;  phone?: string;  email?: string;  address?: string;}const props = defineProps<Props>();const targetRef = ref<HTMLDiveElement>();const isMouseOver = ref(false);const dropdownRef = ref<HTMLDivElement>();const dropdownStyle = ref({});// add modal element in body to prevent overflow issueconst modalElement = document.createElement("div");modalElement.id = "modal";document.body.appendChild(modalElement);const age = computed(() => {  if (!props.birthDate) {    return "0";  }  const birthYear = new Date(props.birthDate).getFullYear();  const currentYear = new Date().getFullYear();  return currentYear - birthYear;});const onMouseOver = () => {  if (isMouseOver.value) {    return;  }  isMouseOver.value = true;  const dimension = targetRef.value.getBoundingClientRect();  dropdownStyle.value = {    width: `${dimension.width}px`,    left: `${dimension.x}px`,    top: `${window.scrollY + dimension.y + dimension.height + 5}px`,  };};const onMouseLeave = () => {  isMouseOver.value = false;};</script><template>  <div    ref="targetRef"    @mouseover="onMouseOver"    @mouseleave="onMouseLeave"    class="app-card"  >    <img class="user-image" :src="image" alt="avatar" />    <div>      <div>        <label> {{ firstName }} {{ lastName }} </label>      </div>    </div>  </div>  <Teleport to="#modal">    <div      ref="dropdownRef"      :style="dropdownStyle"      style="position: absolute"      v-show="isMouseOver"    >      <div class="app-card">        <div>          <div>            <label> Birth day: </label>            <span>              {{ birthDate }}            </span>          </div>          <div>            <label> Age: </label>            <span>              {{ age }}            </span>          </div>          <div>            <label> Phone number: </label>            <span>              {{ phone }}            </span>          </div>          <div>            <label> Email: </label>            <span>              {{ email }}            </span>          </div>        </div>      </div>    </div>  </Teleport></template><style scoped>.app-card {  padding-left: 10px;  padding-right: 10px;  padding-top: 5px;  padding-bottom: 5px;  background: white;  box-shadow: 0 0 5px;  border-radius: 5px;  border: none;  font-size: 1.5em;  transition: 0.3s;  display: flex;  align-items: center;}.app-card label {  font-weight: 600;}.app-card:hover {  background: rgba(128, 128, 128, 0.5);  color: black;}.user-image {  width: 100px;}</style>

這項新要求令人頭疼:oM628資訊網(wǎng)——每日最新資訊28at.com

  • 我是否要修改現(xiàn)有的用戶卡組件以支持工具提示要求,并冒著影響用戶設置頁面中的用戶卡組件的風險?或者
  • 是否要復制現(xiàn)有的用戶卡組件并添加工具提示功能?

因為我們不想破壞已經(jīng)投入生產的項目,所以我們傾向于選擇后一種方案。起初,這可能是有道理的,但它可能會造成相當大的損害,尤其是對于大型和連續(xù)性項目而言:oM628資訊網(wǎng)——每日最新資訊28at.com

  1. 代碼庫龐大:導致代碼庫擴大,因為每個重復的組件都會增加不必要的代碼行。變得難以維護,因為每當需要更新或修復錯誤時,開發(fā)人員都需要在多個地方進行修改。這還會增加不一致的可能性。
  2. 短期收益,長期痛苦:在短期內,特別是在處理緊迫的期限或緊急需求時,這似乎是一個快速而簡單的解決方案。然而,隨著項目的增長,維護重復組件變得越來越困難和耗時。對重復組件的修改或更新需要在多個實例中復制,導致出錯的幾率增加。
  3. 系統(tǒng)性能:會對系統(tǒng)性能產生負面影響。冗余代碼會增加應用程序的大小,導致渲染時間變慢和內存使用量增加。這會導致用戶體驗不佳,系統(tǒng)效率降低。

如何克服上述問題

在整個項目中,可重復使用的組件可能不會始終保持不變,這一點要有心理準備。這聽起來可能很老套,但仔細想想,需求總是在不斷變化的。你無法控制未來,只能盡力而為。當然,經(jīng)驗會幫助你設計出更好的組件,但這需要時間oM628資訊網(wǎng)——每日最新資訊28at.com

重構可重用組件

根據(jù)我的經(jīng)驗,我將重新設計和重構可重用的組件。重構是一個在不改變代碼原有功能的前提下重組代碼的過程。我相信重構的方法有很多,對我來說,我會重構并將組件分解成更小的組件。較小的組件可以在整個系統(tǒng)中靈活應用。讓我們看看我將如何應用上述案例研究。oM628資訊網(wǎng)——每日最新資訊28at.com

注意:重構用戶界面組件需要嚴謹?shù)膽B(tài)度。此外,有時這也很具有挑戰(zhàn)性,因為需要在項目交付期限和更簡潔的代碼之間取得平衡。oM628資訊網(wǎng)——每日最新資訊28at.com

將解決方案應用于案例研究

首先,我將把現(xiàn)有的用戶卡組件拆分成 4 個組件:oM628資訊網(wǎng)——每日最新資訊28at.com

  • Card component 卡片組件
  • Avatar component 頭像組件
  • Name component 名稱組件
  • User detail component 用戶詳情組件

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

** Card.vue**

// Card.vue<template>    <div class="app-card">        <slot></slot>    </div></template><style scoped>    .app-card {        padding-left: 15px;        padding-right: 15px;        padding-top: 10px;        padding-bottom: 10px;        border-radius: 5px;        border: none;        background: white;        color: black;        font-size: 1.5em;        transition: 0.3s;        display: flex;        align-items: center;        box-shadow: 0 0 5px;    }    .app-card:hover {        background: rgba(128, 128, 128, 0.5);        color: black;    }</style>

Avatar.vue

// Avatar.vue<script setup lang="ts">    import { defineProps } from "vue";    interface Props {        image: string;    }    const props = defineProps<Props>();</script><template>    <img        class="user-image"        :src="image"        alt="avatar" /></template><style scoped>    .user-image {        width: 100px;    }</style>

UserName.vue

// UserName.vue<script setup lang="ts">    import { defineProps } from "vue";    interface Props {        firstName: string;        lastName: string;    }    const props = defineProps<Props>();</script><template>    <label> {{ firstName }} {{ lastName }} </label></template>

Description Item

efineProps } from "vue";    interface Props {        label: string;        value: string | number;    }    const props = defineProps<Props>();</script><template>    <div>        <label> {{ label }}: </label>        <span>            {{ value }}        </span>    </div></template><style scoped>    label {        font-weight: 600;    }</style>

UserDescription.vue

// UserDescription.vue<script setup lang="ts">    import DescriptionItem from "./DescriptionItem.vue";    import { defineProps, computed } from "vue";    interface Props {        birthDate: string;        phone: string;        email: string;    }    const props = defineProps<Props>();    const age = computed(() => {        if (!props.birthDate) {            return "0";        }        const birthYear = new Date(props.birthDate).getFullYear();        const currentYear = new Date().getFullYear();        return currentYear - birthYear;    });</script><template>    <div>        <DescriptionItem            label="Birth day"            :value="birthDate" />        <DescriptionItem            label="Age"            :value="age" />        <DescriptionItem            label="Phone number"            :value="phone" />        <DescriptionItem            label="Email"            :value="email" />    </div></template>

之后,我將創(chuàng)建一個工具提示組件。創(chuàng)建一個單獨的工具提示可以讓我在系統(tǒng)的其他部分重復使用它。oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

Tooltip.vue

// Tooltip.vue<script setup lang="ts">import {  Teleport,  computed,  ref,  onMounted,  onBeforeUnmount,  watch,} from "vue";const isMouseOver = ref(false);const targetRef = ref<HTMLDivElement>();const dropdownStyle = ref({});const dropdownRef = ref<HTMLDivElement>();const existModalElement = document.getElementById("modal");if (!existModalElement) {  // add modal element in body to prevent overflow issue  const modalElement = document.createElement("div");  modalElement.id = "modal";  document.body.appendChild(modalElement);}const onMouseOver = () => {  if (isMouseOver.value) {    return;  }  isMouseOver.value = true;  const dimension = targetRef.value.getBoundingClientRect();  dropdownStyle.value = {    width: `${dimension.width}px`,    left: `${dimension.x}px`,    top: `${window.scrollY + dimension.y + dimension.height + 5}px`,  };};const onMouseLeave = () => {  isMouseOver.value = false;};</script><template>  <div @mouseover="onMouseOver" @mouseleave="onMouseLeave" ref="targetRef">    <slot name="default" />  </div>  <Teleport to="#modal">    <div      ref="dropdownRef"      :style="dropdownStyle"      style="position: absolute"      v-show="isMouseOver"    >      <Card>        <slot name="overlay" />      </Card>    </div>  </Teleport></template>

最后,我將把這些組件組合在一起,如下所示。oM628資訊網(wǎng)——每日最新資訊28at.com

在用戶設置頁面,我將使用用戶卡組件,它由卡片、頭像、姓名組件和用戶詳情組件組成。oM628資訊網(wǎng)——每日最新資訊28at.com

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

// UserWithDescription.vue<script setup lang="ts">import AppCard from "./Card.vue";import DescriptionItem from "./DescriptionItem.vue";import Avatar from "./Avatar.vue";import UserName from "./UserName.vue";import UserDescription from "./UserDescription.vue";import { defineProps } from "vue";interface Props {  firstName: string;  lastName: string;  image?: string;  birthDate?: string;  phone?: string;  email?: string;  address?: string;}const props = defineProps<Props>();</script><template>  <AppCard>    <Avatar :image="image" />    <div>      <div>        <UserName :firstName="firstName" :lastName="lastName" />      </div>      <UserDescription v-bind="props" />    </div>  </AppCard></template>

至于 "員工名錄 "頁面,我計劃由兩個部分組成oM628資訊網(wǎng)——每日最新資訊28at.com

  • 基本用戶卡組件由卡、頭像和名稱組件組成。
  • 用戶工具提示組件由卡片、工具提示和用戶詳情組件組成。

圖片圖片oM628資訊網(wǎng)——每日最新資訊28at.com

UserCard.vue

// UserCard.vue<script setup lang="ts">    import AppCard from "./Card.vue";    import DescriptionItem from "./DescriptionItem.vue";    import Avatar from "./Avatar.vue";    import UserName from "./UserName.vue";    import { defineProps } from "vue";    interface Props {        firstName: string;        lastName: string;        image?: string;    }    const props = defineProps<Props>();</script><template>    <AppCard>        <Avatar :image="image" />        <div>            <div>                <UserName                    :firstName="firstName"                    :lastName="lastName" />            </div>        </div>    </AppCard></template>

** UserCardWithTooltip.vue**

// UserCardWithTooltip.vue<script setup lang="ts">    import ToolTip from "./Tooltip.vue";    import UserDescription from "./UserDescription.vue";    import UserCard from "./UserCard.vue";    import Card from "./Card.vue";    import { defineProps } from "vue";    interface Props {        firstName: string;        lastName: string;        image?: string;        birthDate?: string;        phone?: string;        email?: string;    }    const props = defineProps<Props>();</script><template>    <ToolTip>        <UserCard v-bind="props" />        <template #overlay>            <Card>                <UserDescription v-bind="props" />            </Card>        </template>    </ToolTip></template>

注:你可能會注意到,所提供的解決方案基于原子設計概念。該概念首先可以將 "可重用性 "挑戰(zhàn)降至最低。如果您對如何將其應用于 Vue.js 感興趣,請參閱我同事的文章。oM628資訊網(wǎng)——每日最新資訊28at.com

單元測試有幫助嗎?

有些人可能會認為,為可重用組件編寫單元測試會緩解這一問題。的確,全面的測試覆蓋有助于確保對組件的修改和增強不會意外破壞功能。oM628資訊網(wǎng)——每日最新資訊28at.com

然而,單元測試并不能使組件變得更可重用。它只是讓組件更健壯而已。事實上,重構為更小的組件可以將任務分解為特定的部分,使單元測試的編寫更易于管理。oM628資訊網(wǎng)——每日最新資訊28at.com

結論

在 Vue中創(chuàng)建實際的可重用組件可能具有挑戰(zhàn)性,這是因為需要解決修改現(xiàn)有組件、保持一致性以及管理依賴關系和狀態(tài)等相關問題。然而,可重用組件的好處使得克服這些問題是值得的。可重用組件能加強代碼組織、提高開發(fā)效率,并有助于創(chuàng)建一致的用戶界面。當我們面對新的需求或任務時,我們將不斷改進,以便更好地設計可重用組件。oM628資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-13635-0.htmlVue 中可重用組件的 3 個主要問題

聲明:本網(wǎng)頁內容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Python的變量和數(shù)據(jù)類型

下一篇: 不可不知的FPGA設計妙招,使用Makerchip進行在線虛擬開發(fā)(附案例)

標簽:
  • 熱門焦點
Top