組件設計要求

来源:https://www.cnblogs.com/fshmjl/archive/2022/05/10/16253936.html
-Advertisement-
Play Games

前言 在我們日常代碼開發過程中,組件的使用是必不可少的,我們也會去封裝組件。但是大家寫組件的風格各式各樣,沒有一個統一的準則。而且也沒有遵循軟體開發的原則:高內聚、低耦合;因為我是給行業提供代碼的,行業給交付提供代碼。我們要儘量去減少大家的接入成本,降低接入成本的最好方案就是我們在設計組件的時候編寫 ...


前言

在我們日常代碼開發過程中,組件的使用是必不可少的,我們也會去封裝組件。但是大家寫組件的風格各式各樣,沒有一個統一的準則。而且也沒有遵循軟體開發的原則:高內聚、低耦合;因為我是給行業提供代碼的,行業給交付提供代碼。我們要儘量去減少大家的接入成本,降低接入成本的最好方案就是我們在設計組件的時候編寫好文檔,保證職責單一,不要耦合業務,就在很多程度上降低了成本了。在我們平時開發過程中,也遇到過一些組件,一個組件的實現有上千行代碼,那種組件我是直接不想看的。所以我們在開發組件的時候如果你的代碼超過了300行,那你就需要好好思考一下,是否有需要優化的了,設計是否合理,是否有重覆的代碼可以封裝等等。

大家在看這個文檔時可以先詳細閱讀一下這個文檔

組件職責單一

比如商品列表篩選條件組件,提供篩選功能,輸出一個選擇的form提供給外部組件請求列表數據。

一個很簡單的功能,為了保證組件的功能的單一,不允許其他模塊往這個組件中新增篩選條件,如果在不修改組件的情況下可以直接使用這個組件

<template>
  <!--過濾器-->
  <el-form
    style="padding-right: 20px"
    inline
    class="goods-list-filter"
    :model="filter"
    ref="filter"
    label-position="right"
    label-width="120px"
  >
    <!-- 關鍵字搜索 -->
    <el-form-item label="商品標題:" prop="itemMainTitle">
      <el-input
        class="w220"
        placeholder="請輸入"
        size="mini"
        v-model.trim="filter.itemMainTitle"
        @input="checkFilterParam('itemMainTitle', 80)"
      />
    </el-form-item>

    <!-- barcode條形碼搜索 -->
    <el-form-item v-if="showBarcode" label="條形碼:" prop="barcode">
      <el-input
        class="w220"
        placeholder="條形碼搜索"
        prefix-icon="el-icon-search"
        size="mini"
        v-model.trim="filter.barcode"
        @input="checkFilterParam('barcode', 20)"
      />
    </el-form-item>

    <el-form-item label="商品分類:" prop="categoryId">
      <goods-category-cascader
        class="w220"
        :active-goods-type="goodsType"
        :with-all="true"
        size="mini"
        v-model="filter.categoryId"
        :reset-selecte="resetSelecte"
        @changeRestStatus="changeRestStatus"
      />
    </el-form-item>

    <el-form-item label="售賣類型:" prop="saleType">
      <el-select class="w220" v-model="filter.saleType" size="mini" placeholder="售賣類型">
        <el-option label="全部類型" :value="null"></el-option>
        <el-option label="普通售賣" :value="SaleChannel.Normal"></el-option>
        <el-option label="活動售賣" :value="SaleChannel.Activity"></el-option>
      </el-select>
    </el-form-item>

    <!-- 上下架狀態 -->
    <el-form-item v-if="showStatus" prop="itemActiveStatus" label="狀態:">
      <el-select class="w220" v-model="filter.itemActiveStatus" size="mini">
        <el-option label="全部狀態" :value="null"></el-option>
        <el-option label="啟用" :value="GoodsStatus.PullShelves"></el-option>
        <el-option label="禁用" :value="GoodsStatus.RemoveShelves"></el-option>
      </el-select>
    </el-form-item>

    <el-form-item label="是否支持退款:" prop="notAllowRefund">
      <el-select class="w220" v-model="filter.notAllowRefund" size="mini" placeholder="是否支持退款">
        <el-option label="全部狀態" :value="null"></el-option>
        <el-option label="支持" :value="AllowRefund.Yes"></el-option>
        <el-option label="不支持" :value="AllowRefund.No"></el-option>
      </el-select>
    </el-form-item>

    <el-form-item v-if="showPerformance" label="履約主體:" prop="performanceBuId">
      <slot></slot>
    </el-form-item>

    <el-button type="primary" @click="onFilter">搜索</el-button>
    <el-button v-if="!showLabel" plain @click="handleReset" style="margin-top: 2px">重置</el-button>
  </el-form>
</template>

體積要小

為了不讓組件去耦合業務,要儘可能的保證組件的純粹性,如上面講到的篩選條件組件,只需要保證輸出的篩選欄位正確性,而篩選的條件的值可以由外部組件提供(如商品分類的數據),

為什麼數據要外部傳入?

這是因為一般情況下存在的篩選條件,列表也肯定會有,而有時候後端在返回數據時只返回了id,就需要我們去通過id解析出對應的name,這就需要使用到對應的數據,這個時候就可以共用數據。

這樣也可以進一步降低耦合與體積

遵循使用習慣

很多組件都有他們的慣用方法,比如表單組件會使用 v-model 來進行綁定表單值、模態框我們會使用visible 或 show() 方法來控制顯示。

遵循這些慣用方法, 可以減少開發者的心智負擔,維持介面的統一性,另外也更容易地被組合/集成(比如在 Ant-design 中 Form.Item 就依賴於這個協議)。

舉個例子,頭像選擇器:

export default {
  name: 'AvatarSelect',
  props: ['avatar'],
	methods: {
    handleSelect() {
			// ...
			this.$emit('avatar-change', value)
		}
  }
}

<avatar-select :avatar="form.avatar" @avatar-change="form.avatar = $event" />

謹防樣式污染

  • 每個組件應該有一個命名空間。且這個命名空間最好避免和其他組件衝突。

    <template>
    	<div class="my-component">
        ...
      </div>
    </template>
    
    <style lang="scss">
      .my-component {
    		// 下級組件樣式
    	}
    <style>
    
  • 總是開啟 Scoped CSS. 這是一種最簡便的防止污染的方式

    <style scoped>
    .example {
      color: red;
    }
    </style>
    
    <template>
      <div class="example">hi</div>
    </template>
    
  • CSS 類嵌套不要超過兩級。否則從可讀性和可維護性上都會大打折扣

    .foo {
      .bar {
    		.baz {
    		  // 幾百幾千行代碼
    			}
    		// 幾百幾千行代碼
    	}
    }
    
  • 推薦使用 BEM 來作為CSS 類名。讓CSS 的語義和組件結構關聯起來。

    .my-component {
      &__head {/*...*/}
      &__footer {/*...*/}
    }
    
  • 通過 class 或 style 來定製組件的樣式。不要使用直接給標簽加樣式

    // ❌
    <el-input />
    <style>
      .el-input {
    		// 樣式覆蓋
    	}
    </style>
    
    // ✅
    <el-input class="my-input" />
    <style>
    	.my-input {
    		// 樣式覆蓋
    	}
    </style>
    

組件擴展

由於我們是基礎產品,那提供的組件也要儘量豐富,豐富並不是說要在組件中加各種判斷,而是在職責單一、體積、耦合間權衡利弊,也可以創建同類型組件,在同一個文件index.jsexport

單向數據流

  • 只通過 props 向下級傳遞狀態。不要通過 ref 這類方式,過程式地去影響下級組件的狀態。

  • 下級組件只通過 event 向上級通信。

  • 下級組件不准修改 props 源數據。

  • 遵循 v-model, update:* 協議。

  • v-model 遵循數據不可變原則。即你不能直接修改 value,而是應該創建一個新的 value。

    // 假設 value 是一個列表
    handleRemove(item) {
      const idx = this.value.indexOf(item)
      if (idx !== -1) {
        const newValue = [...this.value]
    		newValue.splice(idx, 1)
        this.$emit('input', newValue)
    	}
    }
    
  • 使用 computed 來衍生數據。保持源數據的純潔。

  • 分離業務狀態和視圖狀態。比如列表項的激活狀態就是視圖狀態,而後端返回的數據就是業務狀態。

    // 推薦
    <item :checked="item.id in checked" @click="checked.add(item.id)" />
    
    // 不推薦: 直接在源數據上添加了一個欄位,污染了原有的數據。
    <item :checked="item.checked" @click="item.checked = true" />
    

進階篇

用 JSX 賦能 Vue

Vue 本身是完全支持 JSX 渲染的,但是大部分情況我們還是習慣或者推薦使用模板。

如果你習慣了 React 的 renderProps ,覺得 Vue 的 slot 不夠用,那麼可以上 JSX。

使用依賴註入

為了更好點交流和學習,請大家在參閱博客後,留下你的疑問和寶貴意見。謝謝!!!!
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文和接下來的幾篇文章為閱讀郭霖先生所著《第一行代碼:Android(篇第2版)》的學習筆記,按照書中的內容順序進行記錄,書中的Demo本人全部都做過了。 每一章節本人都做了詳細的記錄,以下是我學習記錄(包含大量書中內容的整理和自己在學習中遇到的各種bug及解決方案),方便以後閱讀和查閱。最後,感激 ...
  • 本文和接下來的幾篇文章為閱讀郭霖先生所著《第一行代碼:Android(篇第2版)》的學習筆記,按照書中的內容順序進行記錄,書中的Demo本人全部都做過了。 每一章節本人都做了詳細的記錄,以下是我學習記錄(包含大量書中內容的整理和自己在學習中遇到的各種bug及解決方案),方便以後閱讀和查閱。最後,非常 ...
  • OpenHarmony電話子系統為 OS 提供了基礎的無線通信能力。支持 TD-LTE/FDD-LTE/TD-SCDMA/WCDMA/EVDO/CDMA1X/GSM 等網路制式的通信模塊,能夠提供高速的無線數據傳輸、互聯網接入等業務,具備語音、簡訊、彩信、SIM 卡等功能。 ...
  • 在直播、語聊房、K 歌房場景中,為增加趣味性和互動性,玩家可以通過變聲來搞怪,通過混響烘托氣氛,通過立體聲使聲音更具立體感。ZegoExpress SDK 提供了多種預設的變聲、混響、混響回聲、立體聲效果,開發者可以靈活設置自己想要的聲音,如果需要試聽,可以啟用耳返進行測試。 ...
  • 在 OpenHarmony 生態發展過程中,涌現了大批優秀的代碼貢獻者,本專題旨在表彰貢獻、分享經驗,文中內容來自嘉賓訪談,不代表 OpenHarmony 工作委員會觀點。 ...
  • 如今,身材管理已成為人們日常生活中重點關註的內容,除了運動之外,熱量的攝入也是重中之重,想要維持理想的身體健康和體重狀態,人們需要長期測量自己每日攝入食物的體量、熱量和營養價值,這需要實踐者有極強的耐心、執行力和知識儲備,從而成為了一部分身材管理道路上的攔路虎。 因此很多運動健康類App中支持食物識 ...
  • 今天內容挺多,因為想的是必須在一天內把這個vuex完成,說實話這裡面要記得東西還是蠻多的,主要是分為原生的和簡便方法兩種都是vue官方定義的,只不過看你要用哪種,vuex感覺要是用熟練了不得了,直接可以把vue起飛了,數據到處用,那種起飛的感覺,曾經體驗過,所以這個應該還是可以多練練的。 明天進入v ...
  • 8 個你應該立即停止使用的無效 HTML 元素 HTML 規範的開發是一個漸進的過程,有時會出現問題。隨著時間的推移,許多元素和屬性被添加到 HTML 中,直到後來 Web 社區集體意識到有更好的方法時才被刪除。由於已棄用和過時的元素和屬性已經存在於網路上,因此許多現代瀏覽器繼續支持它們的使用。儘管 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...