国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

在 TypeScript中擴展HTML元素的屬性

在我參與過的大多數(shù)大型應用程序和項目中,我經(jīng)常發(fā)現(xiàn)自己構(gòu)建了一堆組件,這些組件實際上是標準 HTML 元素之上的超集或抽象。一些示例包括自定義按鈕元素,這些元素可能采用一個 prop 來定義該按鈕是否應該是主按鈕或輔助按鈕,或者可能指示它將調(diào)用危險操作,例如從數(shù)據(jù)庫中刪除或刪除項目。除了我想添加的道具之外,我仍然希望我的按鈕具有按鈕的所有屬性。

另一個常見的情況是,我最終將創(chuàng)建一個允許我同時定義標簽和輸入字段的組件。我不想重新添加元素所<input />具有的所有屬性。我希望我的自定義組件的行為就像輸入字段一樣,但也采用一個字符串作為標簽,并自動連接htmlFor上的 prop<label />以與id上的相對應<input />。

在 JavaScript 中,我可以將{...props}任何 props 傳遞給底層 HTML 元素。這在 TypeScript 中可能有點棘手,我需要顯式定義組件將接受哪些 props。雖然對組件接受的確切類型進行細粒度控制很好,但必須手動為每個屬性添加類型信息可能很乏味。

在某些情況下,我需要一個可適應的組件,例如<div>,它可以根據(jù)當前主題更改樣式。例如,也許我想根據(jù)用戶是否手動啟用 UI 的淺色或深色模式來定義應使用哪些樣式。我不想為每個塊元素(例如<section>、<article>、<aside>等)重新定義此組件。它應該能夠表示不同語義的 HTML 元素,并且 TypeScript 自動調(diào)整以適應這些變化。

我們可以采用以下幾種策略:

  • 對于僅對一種元素創(chuàng)建抽象的組件,我們可以擴展該元素的屬性。

  • 對于想要定義不同元素的組件,我們可以創(chuàng)建多態(tài)組件。多態(tài)組件是設計為呈現(xiàn)為不同的 HTML 元素或組件,同時保持相同的屬性和行為的組件。它允許我們指定一個 prop 來確定其渲染的元素類型。多態(tài)組件提供了靈活性和可重用性,而無需我們重新實現(xiàn)組件。舉個具體的例子,你可以看看Radix 的多態(tài)組件的實現(xiàn)。(https://www.radix-ui.com/primitives/docs/utilities/polymorphic)

在本教程中,我們將了解第一個策略。

鏡像和擴展 HTML 元素的屬性

讓我們從簡介中提到的第一個示例開始。我們想要創(chuàng)建一個帶有適當樣式的按鈕,以便在我們的應用程序中使用。在 JavaScript 中,我們也許可以做這樣的事情:

鏡像和擴展 HTML 元素的屬性

讓我們從簡介中提到的第一個示例開始。我們想要創(chuàng)建一個帶有適當樣式的按鈕,以便在我們的應用程序中使用。在 JavaScript 中,我們也許可以做這樣的事情:

const Button = (props) => {
  return <button className="button" {...props} />;
};

在 TypeScript 中,我們只需添加我們知道需要的內(nèi)容即可。例如,我們知道children如果我們希望自定義按鈕的行為與 HTML 按鈕相同,則需要:

const Button = ({ children }: React.PropsWithChildren) => {
  return <button className="button">{children}</button>;
};

您可以想象一次添加一個屬性可能會有點乏味。<button>相反,我們可以告訴 TypeScript 我們想要匹配它在 React 中用于元素的相同屬性:

const Button = (props: React.ComponentProps<'button'>) => {
  return <button className="button" {...props} />;
};

但我們有一個新問題?;蛘吒_切地說,我們遇到了JavaScript 示例中也存在的問題,但我們忽略了它。如果有人使用我們的新Button組件傳遞一個classNameprop,它將覆蓋我們的className. 我們可以(并且我們將會)添加一些代碼來處理這個問題,但我不想錯過向您展示如何在 TypeScript 中使用實用程序類型的機會,以表示“我想使用所有來自 HTML 按鈕的 props,除了一個(或多個)”:

type ButtonProps = Omit<React.ComponentProps<'button'>, 'className'>;

const Button = (props: ButtonProps) => {
  return <button className="button" {...props} />;
};

現(xiàn)在,TypeScript 將阻止我們或其他任何人將className屬性傳遞到我們的Button組件中。如果我們只想使用傳入的內(nèi)容擴展類列表,我們可以通過幾種不同的方式來實現(xiàn)。我們可以將其附加到列表中:

type ButtonProps = React.ComponentProps<'button'>;

const Button = (props: ButtonProps) => {
  const className = 'button ' + props.className;

  return <button className={className.trim()} {...props} />;
};

我喜歡在處理類時使用clsx庫,因為它代表我們處理大多數(shù)此類事情:

import React from 'react';
import clsx from 'clsx';

type ButtonProps = React.ComponentProps<'button'>;

const Button = ({ className, ...props }: ButtonProps) => {
  return <button className={clsx('button', className)} {...props} />;
};

export default Button;

我們學習了如何限制組件接受的 props。為了擴展 props,我們可以使用交集:

type ButtonProps = React.ComponentProps<'button'> & {
  variant?: 'primary' | 'secondary';
};

我們現(xiàn)在說的是Button接受元素接受的所有 props<button>加上一個:variant。該道具將與我們繼承的所有其他道具一起顯示HTMLButtonElement。

Variant 顯示為 Button 組件上的一個 prop

我們Button也可以添加對添加此類的支持:

const Button = ({ variant, className, ...props }: ButtonProps) => {
  return (
    <button
      className={clsx(
        'button',
        variant === 'primary' && 'button-primary',
        variant === 'secondary' && 'button-secondary',
        className,
      )}
      {...props}
    />
  );
};

我們現(xiàn)在可以更新src/application.tsx以使用新的按鈕組件:

diff --git a/src/application.tsx b/src/application.tsx
index 978a61d..fc8a416 100644
--- a/src/application.tsx
+++ b/src/application.tsx
@@ -1,3 +1,4 @@
+import Button from './components/button';
 import useCount from './use-count';

 const Counter = () => {
@@ -8,15 +9,11 @@ const Counter = () => {
       <h1>Counter</h1>
       <p className="text-7xl">{count}</p>
       <div className="flex place-content-between w-full">
-        <button className="button" onClick={decrement}>
+        <Button onClick={decrement}>
           Decrement
-        </button>
-        <button className="button" onClick={reset}>
-          Reset
-        </button>
-        <button className="button" onClick={increment}>
-          Increment
-        </button>
+        </Button>
+        <Button onClick={reset}>Reset</Button>
+        <Button onClick={increment}>Increment</Button>
       </div>
       <div>
         <form
@@ -32,9 +29,9 @@ const Counter = () => {
         >
           <label htmlFor="set-count">Set Count</label>
           <input type="number" id="set-count" name="set-count" />
-          <button className="button-primary" type="submit">
+          <Button variant="primary" type="submit">
             Set
-          </button>
+          </Button>
         </form>
       </div>
     </main>

您可以在本教程的 GitHub 存儲庫分支中button找到上述更改。(https://github.com/stevekinney/polymorphic/tree/button)

創(chuàng)建復合組件

我通常最終為自己制作的另一個常見組件是分別使用正確的for和屬性正確連接標簽和輸入元素的組件。id我往往會厭倦一遍又一遍地輸入以下內(nèi)容:

<label htmlFor="set-count">Set Count</label>
<input type="number" id="set-count" name="set-count" />

如果不擴展 HTML 元素的 props,我最終可能會根據(jù)需要慢慢添加 props:

type LabeledInputProps = {
  id?: string;
  label: string;
  value: string | number;
  type?: string;
  className?: string;
  onChange?: ChangeEventHandler<HTMLInputElement>;
};

正如我們在按鈕中看到的那樣,我們可以以類似的方式重構(gòu)它:

type LabeledInputProps = React.ComponentProps<'input'> & {
  label: string;
};

除了label我們要傳遞給(呃)標簽(我們經(jīng)常希望將其與輸入分組)之外,我們還手動將道具一一傳遞。我們要添加嗎autofocus?最好添加另一個道具。最好做這樣的事情:

import { ComponentProps } from 'react';

type LabeledInputProps = ComponentProps<'input'> & {
  label: string;
};

const LabeledInput = ({ id, label, ...props }: LabeledInputProps) => {
  return (
    <>
      <label htmlFor={id}>{label}</label>
      <input {...props} id={id} readOnly={!props.onChange} />
    </>
  );
};

export default LabeledInput;

我們可以在以下位置交換新組件src/application.tsx:

<LabeledInput
  id="set-count"
  label="Set Count"
  type="number"
  onChange={(e) => setValue(e.target.valueAsNumber)}
  value={value}
/>

我們可以取出需要使用的東西,然后將其他所有東西傳遞給組件<input />,然后在接下來的日子里假裝它是一個標準HTMLInputElement。

TypeScript 并不關(guān)心,因為HTMLElement它非常靈活,因為 DOM 早于 TypeScript。如果我們把一些完全令人震驚的東西扔進去,它只會抱怨。

您可以在本教程的 GitHub 存儲庫分支中input查看上述所有更改。(https://github.com/stevekinney/polymorphic/tree/input)


文章來源地址http://www.zghlxwxcb.cn/article/424.html

到此這篇關(guān)于在 TypeScript中擴展HTML元素的屬性的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

原文地址:http://www.zghlxwxcb.cn/article/424.html

如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請聯(lián)系站長進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • HTML 元素的屬性有哪些?

    HTML 元素的屬性有哪些?

    前端入門之旅:探索Web開發(fā)的奇妙世界 歡迎來到前端入門之旅!感興趣的可以訂閱本專欄哦!這個專欄是為那些對Web開發(fā)感興趣、剛剛踏入前端領(lǐng)域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發(fā)者,這里都將為你提供一個系統(tǒng)而又親切的學習平臺。在這個

    2024年02月14日
    瀏覽(21)
  • HTML 元素中的name 屬性

    name 屬性是 HTML 元素中常用的屬性之一。它用于指定表單元素的名稱,以便在提交表單時將其值與對應的鍵關(guān)聯(lián)起來。 每個表單元素(例如 input 、 select 和 textarea )都可以具有一個 name 屬性,該屬性為元素提供一個唯一的標識符。當用戶在提交表單時,瀏覽器會將表單元素的

    2024年02月13日
    瀏覽(23)
  • HTML元素和屬性快速參考指南

    HTML元素和屬性快速參考指南

    ? 以下是幾個與HTML元素和屬性相關(guān)的參考資料網(wǎng)站鏈接: HTML Reference - 提供所有HTML元素和屬性的免費指南。 W3Schools HTML Reference - W3Schools 提供一個廣泛的HTML標簽和屬性參考。 freeCodeCamp HTML Cheat Sheet - freeCodeCamp 提供了一個HTML元素列表參考,適合初學者。 ????????

    2024年02月21日
    瀏覽(17)
  • 【html】Video元素的屬性介紹和用法

    HTML video 元素 用于在 HTML 或者 XHTML 文檔中嵌入媒體播放器,用于支持文檔內(nèi)的視頻播放。 平常若涉及到視頻內(nèi)容,就會使用到它。 只有一個視頻源 只有一個視頻的話,在video元素中的src屬性填入即可。 多個視頻源。 多個視頻源,需要搭配source元素指定視頻源,然后瀏覽器

    2024年01月18日
    瀏覽(17)
  • HTML 元素的 class 和 id 屬性有何區(qū)別?

    HTML 元素的 class 和 id 屬性有何區(qū)別?

    前端入門之旅:探索Web開發(fā)的奇妙世界 歡迎來到前端入門之旅!感興趣的可以訂閱本專欄哦!這個專欄是為那些對Web開發(fā)感興趣、剛剛踏入前端領(lǐng)域的朋友們量身打造的。無論你是完全的新手還是有一些基礎的開發(fā)者,這里都將為你提供一個系統(tǒng)而又親切的學習平臺。在這個

    2024年02月13日
    瀏覽(21)
  • 【溫故而知新】HTML元素/屬性/標題/注釋/段落/文本格式/頭部/主體

    HTML(HyperText Markup Language,超文本標記語言)是用于創(chuàng)建網(wǎng)頁的標準標記語言。它被用來描述網(wǎng)頁的結(jié)構(gòu)和內(nèi)容,并且是網(wǎng)頁瀏覽器能夠解析和渲染網(wǎng)頁的基礎。HTML5 是 HTML 的最新版本,增加了許多新的元素和功能,以適應現(xiàn)代網(wǎng)頁開發(fā)的需求。 HTML5 提供了許多新的元素和

    2024年01月16日
    瀏覽(84)
  • 【HTML 往日冒險 01】標簽 元素 屬性 注釋 文本格式化 顏色 CSS

    【HTML 往日冒險 01】標簽 元素 屬性 注釋 文本格式化 顏色 CSS

    說在前面 HTML 對于現(xiàn)在的我來說,熟悉又陌生,熟悉的是其標簽的結(jié)構(gòu)清晰,陌生的是其豐富的使用細節(jié),長期不使用難免會失去許多相關(guān)的記憶,但是不妨讓我們與W3school教程一同補全往日的冒險日志…(主要是從中提煉關(guān)鍵的信息,具體的知識點還是參考相關(guān)手冊) 重新開

    2024年02月07日
    瀏覽(23)
  • 前端基礎知識學習——獲取dom對象、獲取html屬性、獲取內(nèi)容、更改樣式、創(chuàng)建dom元素、刪除元素、代替元素(十)
  • 〖大前端 - 基礎入門三大核心之JS篇?〗- DOM改變元素節(jié)點的css樣式、HTML屬性

    〖大前端 - 基礎入門三大核心之JS篇?〗- DOM改變元素節(jié)點的css樣式、HTML屬性

    說明:該文屬于 大前端全棧架構(gòu)白寶書專欄, 目前階段免費 , 如需要項目實戰(zhàn)或者是體系化資源,文末名片加V! 作者:不渴望力量的哈士奇(哈哥),十余年工作經(jīng)驗, 從事過全棧研發(fā)、產(chǎn)品經(jīng)理等工作,目前在公司擔任研發(fā)部門CTO。 榮譽: 2022年度博客之星Top4、2023年度超

    2024年02月04日
    瀏覽(98)
  • 項目中拖拽元素,可以使用html的draggable屬性,當然也可以用第三方插件interact

    項目中拖拽元素,可以使用html的draggable屬性,當然也可以用第三方插件interact

    html的draggable屬性需要自己寫邏輯,用人家封裝好的代碼簡單邏輯清楚,非常香 鏈接: https://blog.csdn.net/vvv3171071/article/details/122705408

    2024年02月08日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包