最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端必學(xué)之完美組件封裝原則(適用react、vue)

 更新時(shí)間:2025年09月14日 11:53:27   作者:藍(lán)精靈001  
對(duì)于當(dāng)今的前端開發(fā),模塊化已經(jīng)成了一種通用的解決方案,不管是vue還是React還是Angular,其中都會(huì)涉及的組件的封裝,這篇文章主要介紹了前端必學(xué)之完美組件封裝原則的相關(guān)資料,需要的朋友可以參考下

前言

此文總結(jié)了我多年組件封裝經(jīng)驗(yàn),以及拜讀 antd、element-plusvant、fusion等多個(gè)知名組件庫(kù)所提煉的完美組件封裝的經(jīng)驗(yàn);是一個(gè)開發(fā)者在封裝項(xiàng)目組件,公共組件等場(chǎng)景時(shí)非常有必要遵循的一些原則,希望和大家一起探討,也希望世界上少一些半吊子組件

下面以react為例,但是思路是相通的,在vue上也適用

1. 基本屬性綁定原則

任何組件都需要繼承classNamestyle 兩個(gè)屬性

import classNames from 'classnames';
export interface CommonProps {
  /** 自定義類名 */
  className?: string;
  /** 自定義內(nèi)斂樣式 */
  style?: React.CSSProperties;
}
export interface MyInputProps extends CommonProps {
  /** 值 */
  value: any
}
const MyInput = forwardRef((props: MyInputProps, ref: React.LegacyRef<HTMLDivElement>) => {
  const { className, ...rest } = props;
  const displayClassName = classNames('chc-input', className);
  return (
    <div ref={ref} {...rest} className={displayClassName}>
      <span></span>
    </div>
  );
});
export default ChcInput

2. 注釋使用原則

  • 原則上所有的propsref屬性類型都需要有注釋
  • 且所有屬性(propsref屬性)禁用 // 注釋內(nèi)容 語(yǔ)法注釋,因?yàn)榇俗⑨尣粫?huì)被ts識(shí)別,也就是鼠標(biāo)懸浮的時(shí)候不會(huì)出現(xiàn)對(duì)應(yīng)注釋文案
  • 常用的注視參數(shù) @description 描述, @version 新屬性的起始版本, @deprecated 廢棄的版本, @default 默認(rèn)值
  • 面向國(guó)際化使用的組件一般描述語(yǔ)言推薦使用英文

bad ?

interface MyInputsProps {
  // 自定義class
  className?: string
}
const test: MyInputsProps = {}
test.className

應(yīng)該使用如下注釋方法

after good ?

interface MyInputsProps {
  /**  custom class */
  className?: string
  /**
   * @description Custom inline style
   * @version 2.6.0
   * @default ''
   */
  style?: React.CSSProperties;
  /**
   * @description Custom title style
   * @deprecated 2.5.0 廢棄
   * @default ''
   */
  customTitleStyle?: React.CSSProperties;
}
const test: MyInputsProps = {}
test.className

3. export暴露

  • 組件props類型必須export導(dǎo)出
  • 如有 useImperativeHandle 則ref類型必須export導(dǎo)出
  • 組件導(dǎo)出funtion必須有名稱
  • 組件funtion一般export default默認(rèn)導(dǎo)出

在沒(méi)有名稱的組件報(bào)錯(cuò)時(shí)不利于定位到具體的報(bào)錯(cuò)組件

bad ?

interface MyInputProps {
    ....
}
export default (props: MyInputProps) => {
  return <div></div>;
};

after good ?

// 暴露 MyInputProps 類型
export interface MyInputProps {
    ....
}
funtion MyInput(props: MyInputProps) {
  return <div></div>;
};
// 也可以自己掛載一個(gè)組件名稱
if (process.env.NODE_ENV !== 'production') {
  MyInput.displayName = 'MyInput';
}
export default MyInput

index.ts

export * from './input'
export { default as MyInput } from './input';

當(dāng)然如果目標(biāo)組件沒(méi)有暴露相關(guān)的類型,可以通過(guò)ComponentPropsComponentRef來(lái)分別獲取組件的propsref屬性

type DialogProps = ComponentProps<typeof Dialog> 
type DialogRef = ComponentRef<typeof Dialog> 

4. 入?yún)㈩愋图s束原則

入?yún)㈩愋捅仨氉裱唧w原則

  • 確定入?yún)㈩愋偷目赡芮闆r下,切忌不可用基本類型一筆帶過(guò)
  • 公共組件一般不使用枚舉作為入?yún)㈩愋?,因?yàn)檫@樣在使用者需要引入此枚舉才可以不報(bào)錯(cuò)
  • 部分?jǐn)?shù)值類型的參數(shù)需要描述最大和最小值

bad ?

interface InputProps {
  status: string
}

after good ?

interface InputProps {
  status: 'success' | 'fail'
}

bad ?

interface InputProps {
  /** 總數(shù) */
  count: number
}

after good ?

interface InputProps {
  /** 總數(shù) 0-999 */
  count: number
}

5. class和style定義規(guī)則

  • 禁用 CSS module 因?yàn)榇祟悓懛〞?huì)讓使用者無(wú)法修改組件內(nèi)部樣式;vue 的話可以用 scoped 標(biāo)簽來(lái)防止樣式重復(fù) 也可以實(shí)現(xiàn)父親可修改組件內(nèi)部樣式。
  • 書寫組件時(shí),內(nèi)部的 class 一定要加上統(tǒng)一的前綴來(lái)區(qū)分組件內(nèi)外 class,避免和外部的 class 類有重復(fù)。
  • class 類的名稱需要語(yǔ)意化。
  • 組件內(nèi)部的所有 class 類都可以被外部使用者改變
  • 禁用 important,不到萬(wàn)不得已不用行內(nèi)樣式
  • 可以為顏色相關(guān) CSS 屬性留好 CSS 變量,方便外部開發(fā)主題切換

bad ?

import styles from './index.module.less'
export default funtion MyInput(props: MyInputProps) {
  return (
    <div className={styles.input_box}>
      <span className={styles.detail}>21312312</span>
    </div>
  );
};

after good ?

import './index.less'
const prefixCls = 'my-input' // 統(tǒng)一的組件內(nèi)部前綴
export default funtion MyInput(props: MyInputProps) {
  return (
    <div className={`${prefixCls}-box`}>
      <span className={`${prefixCls}-detail`}>21312312</span>
    </div>
  );
};

after good ?

.my-input-box {
  height: 100px;
  background: var(--my-input-box-background, #000);
}

6. 繼承透?jìng)髟瓌t

書寫組件時(shí)如果進(jìn)行了二次封裝切忌不可將傳入的屬性一個(gè)一個(gè)提取然后綁定,這有非常大的局限性,一旦你基礎(chǔ)的組件更新了或者需要增加使用的參數(shù)則需要再次去修改組件代碼

bad ?

import { Input } from '某組件庫(kù)'
export interface MyInputProps {
  /** 值 */
  value: string
  /** 限制 */
  limit: number
  /** 狀態(tài) */
  state: string
}
const MyInput = (props: Partail<MyInputProps>) => {
  const { value, limit, state } = props
  // ...一些處理
  return (
    <Input value={value} limit={limit} state={state}  />
  )
}
export default MyInput

extends繼承基礎(chǔ)組件的所有屬性,并用...rest 承接所有傳入的屬性,并綁定到我們的基準(zhǔn)組件上。

after good ?

import { Input, InputProps } from '某組件庫(kù)'
export interface MyInputProps extends InputProps {
  /** 值 */
  value: string
}
const MyInput = (props: Partial<MyInputProps>) => {
  const { value, ...rest } = props
  // ...一些處理
  return (
    <Input value={value} {...rest}  />
  )
}
export default MyInput

7.事件配套原則

任何組件內(nèi)部操作導(dǎo)致UI視圖改變都需要有配套的事件,來(lái)給使用者提供全量的觸發(fā)鉤子,提高組件的可用性

bad ?

export default funtion MyInput(props: MyInputProps) {
  // ...省略部分代碼
  const [open, setOpen] = useState(false)
  const [showDetail, setShowDetail] = useState(false)
  const currClassName = classNames(className, {
    `${prefixCls}-box`: true,
    `${prefixCls}-open`: open, // 是否采用打開樣式
  })
  const onCheckOpen = () => {
    setOpen(!open)
  }
  const onShowDetail = () => {
    setShowDetail(!showDetail)
  }
  return (
    <div className={currClassName} style={style} onClick={onCheckOpen}>
      <span onClick={onShowDetail}>{showDetail ? '123' : '...'}</span>
    </div>
  );
};

所有組件內(nèi)部會(huì)影響外部UI改變的事件都預(yù)留了鉤子

after good ?

export default funtion MyInput(props: MyInputProps) {
  const { onChange, onShowChange } = props
  // ...省略部分代碼
  const [open, setOpen] = useState(false)
  const [showDetail, setShowDetail] = useState(false)
  // ...省略部分代碼
  const currClassName = classNames(className, {
    `${prefixCls}-box`: true,
    `${prefixCls}-open`: open, // 是否采用打開樣式
  })
  const onCheckOpen = () => {
    setOpen(!open)
    onChange?.(!open) // 實(shí)現(xiàn)組件內(nèi)部open改變的事件鉤子
  }
  const onShowDetail = () => {
    setShowDetail(!showDetail)
    onShowChange?.(!showDetail) // 實(shí)現(xiàn)組件詳情展示改變的事件鉤子
  }
  return (
    <div className={currClassName} style={style} onClick={onCheckOpen}>
      <span onClick={onShowDetail}>{showDetail ? '123' : '...'}</span>
    </div>
  );
};

8. ref綁定原則

任何書寫的組件在有可能綁定ref情況下都需要暴露有ref屬性,不然使用者一旦掛載ref則會(huì)導(dǎo)致控制臺(tái)報(bào)錯(cuò)警告。

  • 原創(chuàng)組件:useImperativeHandle 或 直接ref綁定組件根節(jié)點(diǎn)
interface ChcInputRef {
  /** 值 */
  setValidView: (isShow?: boolean) => void,
  /** 值 */
  field: Field
}
const ChcInput = forwardRef<ChcInputRef, MyProps>((props, ref) => {
  const { className, ...rest } = props;
  useImperativeHandle(ref, () => ({
    setValidView(isShow = false) {
      setIsCheckBalloonVisible(isShow);
    },
    field
  }), []);
  return (
    <div className={displayClassName}>
          ...
    </div>
  );
});
export default ChcInput
const ChcInput = forwardRef((props: MyProps, ref: React.LegacyRef<HTMLDivElement>) => {
  const { className, ...rest } = props;
  const displayClassName = classNames('chc-input', className);
  return (
      <div ref={ref} className={displayClassName}>
          <span></span>
          ...
      </div>
  );
});
export default ChcInput
  • 二次封裝組件:則直接ref綁定在原基礎(chǔ)組件上 或 組件根節(jié)點(diǎn)
import { Input } from '某組件庫(kù)'
const ChcInput = forwardRef((props: InputProps, ref: React.LegacyRef<Input>) => {
  const { className, ...rest } = props;
  const displayClassName = classNames('chc-input', className);
  return <Input ref={ref} className={displayClassName} {...rest} />;
});
export default ChcInput

9. 自定義擴(kuò)展性原則

在組件封裝時(shí),遇到組件內(nèi)部會(huì)用一些固定邏輯來(lái)渲染UI或者計(jì)算時(shí),最好預(yù)留一個(gè)使用者可以隨意自定義的入口,而不是只能死板采用組件內(nèi)部邏輯,這樣可以

  • 增加組件的擴(kuò)展靈活性
  • 減少迭代修改

bad ?

export default funtion MyInput(props: MyInputProps) {
  const { value } = props
  const detailText = useMemo(() => {
      return value.split(',').map(item => `組件內(nèi)部復(fù)雜的邏輯:${item}`).join('\n')
  }, [value])
  return (
    <div>
      <span>{detailText}</span>
    </div>
  );
};

after good ?

export default funtion MyInput(props: MyInputProps) {
  const { value, render } = props
  const detailText = useMemo(() => {
      // render 用戶自定義渲染
      return render ? render(value) : value.split(',').map(item => `組件內(nèi)部復(fù)雜的邏輯:${item}`).join('\n')
  }, [value])
  return (
    <div>
      <span>{detailText}</span>
    </div>
  );
};

同理復(fù)雜的ui渲染也可以采用用戶自定義傳入render方法的方式進(jìn)行擴(kuò)展

10. 受控與非受控模式原則

對(duì)于react組件,我們往往都會(huì)要求組件在設(shè)計(jì)時(shí)需要包含受控和非受控兩個(gè)模式。

  • 非受控: 的情況可以實(shí)現(xiàn)更加方便的使用組件
  • 受控: 的情況可以實(shí)現(xiàn)更加靈活的使用組件,以增加組件的可用性

bad ?(只有一種受控模式)

import classNames from 'classnames';
const prefixCls = 'my-input' 
export default funtion MyInput(props: MyInputProps) {
  const { value, className, style, onChange } = props
  const currClassName = classNames(className, {
    `${prefixCls}-box`: true,
    `${prefixCls}-open`: value, // 是否采用打開樣式
  })
  const onCheckOpen = () => {
    onChange?.(!value)
  }
  return (
    <div className={currClassName} style={style} onClick={onCheckOpen}>
      <span>12312</span>
    </div>
  );
};

after good ?

import classNames from 'classnames';
const prefixCls = 'my-input' 
export default funtion MyInput(props: MyInputProps) {
  const { value, defaultValue = true, className, style, onChange } = props
  // 實(shí)現(xiàn)非受控模式
  const [open, setOpen] = useState(value || defaultValue)
  useEffect(() => {
    if(typeof value !== 'boolean') return
    setOpen(value)
  }, [value])
  const currClassName = classNames(className, {
    `${prefixCls}-box`: true,
    `${prefixCls}-open`: open, // 是否采用打開樣式
  })
  const onCheckOpen = () => {
    onChange?.(!open)
    // 非受控模式下 組件內(nèi)部自身處理
    if(typeof value !== 'boolean') {
      setOpen(!open)
    }
  }
  return (
    <div className={currClassName} style={style} onClick={onCheckOpen}>
      <span>12312</span>
    </div>
  );
};

11. 最小依賴原則

所有組件封裝都要遵循最小依賴原則,在條件允許的情況下,簡(jiǎn)單的方法需要引入新的依賴的情況下采用手寫方式。這樣避免開發(fā)出非常依賴融于的組件或組件庫(kù)

bad ?

import { useLatest } from 'ahooks'  // 之前組件庫(kù)無(wú)ahooks, 會(huì)引入新的依賴!
import classNames from 'classnames';
const ChcInput = forwardRef((props: InputProps, ref: React.LegacyRef<Input>) => {
  const { className, ...rest } = props;
  const displayClassName = classNames('chc-input', className);
  const funcRef = useLatest(func); // 解決回調(diào)內(nèi)無(wú)法獲取最新state問(wèn)題
  return <div className={displayClassName} {...rest}></div>;
});
export default ChcInput

after good ?

// hooks/index.tsx
import { useRef } from 'react';
export function useLatest(value) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
...
// 組件
import { useLatest } from '@/hooks'  // 之前組件庫(kù)無(wú)ahooks引入新的依賴!
import classNames from 'classnames';
const ChcInput = forwardRef((props: InputProps, ref: React.LegacyRef<Input>) => {
  const { className, ...rest } = props;
  const displayClassName = classNames('chc-input', className);
  const funcRef = useLatest(func); // 解決回調(diào)內(nèi)無(wú)法獲取最新state問(wèn)題
  return <div className={displayClassName} {...rest}></div>;
});
export default ChcInput

當(dāng)然依賴包是否引入也要參考當(dāng)時(shí)的使用情況,比如如果ahooks在公司內(nèi)部基本都會(huì)使用,那這個(gè)時(shí)候引入也無(wú)妨。

12. 功能拆分,單一職責(zé)原則

如果一個(gè)組件內(nèi)部能力很強(qiáng)大,可能包含多個(gè)功能點(diǎn),不建議將所有能力都只在組件內(nèi)部體現(xiàn),可以將這些功能拆分成其他的公共組件, 一個(gè)組件只處理一個(gè)功能點(diǎn)(單一職責(zé)原則),提高功能的復(fù)用性和靈活性。

當(dāng)然業(yè)務(wù)組件除外,業(yè)務(wù)組件可以在組件內(nèi)實(shí)現(xiàn)多個(gè)組件的整合完成一個(gè)業(yè)務(wù)能力的單一職責(zé)。

bad ?

const MyShowPage = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, imgList, ...rest } = props;
  return (
    <div>
      <Table ref={ref} data={data} {...rest}>
        {/* 表格顯示相關(guān)功能封裝 ...省略一堆代碼 */}
      </Table> 
      <div>
        {/* 圖例相關(guān)功能封裝  ...省略一堆代碼 */}
      </div>
    </div>
  )
});

將表格和圖例兩個(gè)功能點(diǎn)拆分成單獨(dú)的兩個(gè)公共組件

after good ?

const MyShowPage = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, imgList, ...rest } = props;
  return (
    <div>
      {/* 表格組件只處理表格內(nèi)容 */}
      <MyTable ref={ref} data={data} {...rest}></Table> 
      {/* 圖片組件只處理圖片展示能力 */}
      <MyImg data={imgList}>
    </div>
  )
});

當(dāng)然如果完全沒(méi)有復(fù)用價(jià)值的組件或功能點(diǎn)也是沒(méi)必要拆分的。

13. 業(yè)務(wù)組件去業(yè)務(wù)化

我們?cè)诜庋b業(yè)務(wù)組件的時(shí)候,切忌不可將相關(guān)復(fù)雜的業(yè)務(wù)邏輯以及運(yùn)算放到組件外面由使用者去實(shí)現(xiàn),在組件內(nèi)部只是一些簡(jiǎn)單的封裝;這很難達(dá)到業(yè)務(wù)組件的價(jià)值最大化,組件的通用性會(huì)降低,使用心智負(fù)擔(dān)也會(huì)加大。

比如:有個(gè)table組件,負(fù)責(zé)將傳入的數(shù)據(jù)進(jìn)行一個(gè)業(yè)務(wù)渲染和展示:

bad ?

const MyTable = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, ...rest } = props;
  return (
    <Table ref={ref} data={data} {...rest}>
      <Table.Column dataIndex="test1" title="標(biāo)題1"/>
      <Table.Column dataIndex="test2" title="標(biāo)題2"/>
      <Table.Column dataIndex="data" title="值"/>
    </Table>
  )
});

但是有一個(gè)業(yè)務(wù)是當(dāng)數(shù)據(jù)的type=1時(shí),data的值要乘2展示,則上面的組件使用者只能這樣使用:

const res = [...]
const data = useMemo(() => {
  return res.map(item => ({
    ...item,
    data: item.type === 1 ? item.data*2 : item.data
  }))
}, [res])
return (
  <MyTable data={data}/>
)

顯然這樣的封裝在使用者這邊會(huì)有一些心智負(fù)擔(dān),假如一個(gè)不熟悉業(yè)務(wù)的人來(lái)開發(fā)很容易會(huì)遺漏,所以這個(gè)時(shí)候需要業(yè)務(wù)組件去業(yè)務(wù)化,降低使用者的門檻

after good ?

const MyTable = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, ...rest } = props;
  const dataRender = (item: ListItem) => {
    return item.type === 1 ? item.data*2 : item.data
  }
  return (
    <Table ref={ref} data={data} {...rest}>
      <Table.Column dataIndex="test1" title="標(biāo)題1"/>
      <Table.Column dataIndex="test2" title="標(biāo)題2"/>
      <Table.Column dataIndex="data" title="值" render={dataRender}/>
    </Table>
  )
});

使用者無(wú)需關(guān)心業(yè)務(wù)也可以順利圓滿完成任務(wù):

const res = [...]
return (
  <MyTable data={res}/>
)

14. 最大深度擴(kuò)展性

當(dāng)組件傳入的數(shù)據(jù)可能會(huì)有樹形等有深度的格式,而組件內(nèi)部也會(huì)針對(duì)其渲染出有遞歸深度的UI時(shí),需要考慮到使用者對(duì)于數(shù)據(jù)深度的不可控性,組件內(nèi)部需要預(yù)留好無(wú)限深度的可能

如下渲染組件方式只有一層的深度,很有局限性

bad ?

interface Columns extends TableColumnProps {
   columns: TableColumnProps[]
}
const MyTable = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, columns = [], ...rest } = props;
  const renderColumn = useMemo(() => {
    return columns.map(item => {
       return item.columns ? (
         <Table.Column {...item}>
           {item.columns.map(column => <Table.Column {...column}/>)}
         </Table.Column>
       ) :  <Table.Column {...item}/>
    })
  }, [columns])
  return (
    <Table ref={ref} data={data} {...rest}>
      {renderColumn}
    </Table>
  )
});

after good ?

interface Columns extends TableColumnProps {
  columns: Columns[] // 改變?yōu)槔^承自己
}
const MyTable = forwardRef((props: MyTableProps, ref: React.LegacyRef<Table>) => {
  const { data, columns = [], ...rest } = props;
  return (
    <Table ref={ref} data={data} {...rest}>
      {/* 采用外部組件 */}
      <MyColumn columns={columns}/>
    </Table>
  )
});
const MyColumn = (props: MyColumnProps) => {
  const { columns = [] } = props
  return (
    item.columns ? (
     <Table.Column {...item}>
      {/* 遞歸渲染數(shù)據(jù),實(shí)現(xiàn)數(shù)據(jù)的深度無(wú)限性 */}
       <MyColumn columns={item.columns}/>
     </Table.Column>
   ) :  
   <Table.Column {...item}/>
  )
}

15. 多語(yǔ)言可配制化

  • 組件內(nèi)部所有的語(yǔ)言都需要可以修改,兼容多語(yǔ)言的使用場(chǎng)景
  • 默認(rèn)推薦英文
  • 內(nèi)部語(yǔ)言變量較多時(shí)可以統(tǒng)一暴露一個(gè)例如 strings 對(duì)象參數(shù),其內(nèi)部可以傳入所有可以替換文案的key

bad ?

const prefixCls = 'my-input' // 統(tǒng)一的組件內(nèi)部前綴
export default funtion MyInput(props: MyInputProps) {
  const { title = '標(biāo)題' } = props;
  return (
    <div className={`${prefixCls}-box`}>
      <span className={`${prefixCls}-title`}>{title}</span>
      <span className={`${prefixCls}-detail`}>詳情</span>
    </div>
  );
};

after good ?

const prefixCls = 'my-input' // 統(tǒng)一的組件內(nèi)部前綴
export default funtion MyInput(props: MyInputProps) {
  const { title = 'title', detail = 'detail' } = props;
  return (
    <div className={`${prefixCls}-box`}>
      <span className={`${prefixCls}-title`}>{title}</span>
      <span className={`${prefixCls}-detail`}>{detail}</span>
    </div>
  );
};

16.異常捕獲和提示

  • 對(duì)于用戶傳入意外的參數(shù)可能帶來(lái)錯(cuò)誤時(shí)要控制臺(tái) console.error 提示
  • 不要直接在組件內(nèi)部 throw error,這樣會(huì)導(dǎo)致用戶的白屏
  • 缺少某些參數(shù)或者參數(shù)不符合要求但不會(huì)導(dǎo)致報(bào)錯(cuò)時(shí)可以使用 console.warn 提示

bad ?

export default funtion MyCanvas(props: MyCanvasProps) {
  const { instanceId } = props;
  
  useEffect(() => {
     initDom(instanceId)
  }, [])
  return (
    <div>
      <canvas id={instanceId} />
    </div>
  );
};

after good ?

export default funtion MyCanvas(props: MyCanvasProps) {
  const { instanceId } = props;
  
  useEffect(() => {
    if(!instanceId){
      console.error('missing instanceId!')
      return
    }
     initDom(instanceId)
  }, [])
  return (
    <div>
      <canvas id={instanceId} />
    </div>
  );
};

17. 語(yǔ)義化原則

組件的命名,組件的api,方法,包括內(nèi)部的變量定義都要遵循語(yǔ)義化的原則,嚴(yán)格按照其代表的功能來(lái)命名。

到此這篇關(guān)于前端必學(xué)之完美組件封裝原則的文章就介紹到這了,更多相關(guān)前端組件封裝原則內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React深入了解原理

    React深入了解原理

    React是用于構(gòu)建用戶界面的JavaScript庫(kù),?[1]??起源于Facebook的內(nèi)部項(xiàng)目,該公司對(duì)市場(chǎng)上所有?JavaScript?MVC框架都不滿意,決定自行開發(fā)一套,用于架設(shè)Instagram的網(wǎng)站
    2022-07-07
  • react中如何對(duì)自己的組件使用setFieldsValue

    react中如何對(duì)自己的組件使用setFieldsValue

    react中如何對(duì)自己的組件使用setFieldsValue問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • react中Suspense的使用詳解

    react中Suspense的使用詳解

    這篇文章主要介紹了react中Suspense的使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Remix如何支持原生?CSS方法詳解

    Remix如何支持原生?CSS方法詳解

    這篇文章主要為大家介紹了Remix如何支持原生CSS的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • React中的setState使用細(xì)節(jié)和原理解析(最新推薦)

    React中的setState使用細(xì)節(jié)和原理解析(最新推薦)

    這篇文章主要介紹了React中的setState使用細(xì)節(jié)和原理解析(最新推薦),前面我們有使用過(guò)setState的基本使用, 接下來(lái)我們對(duì)setState使用進(jìn)行詳細(xì)的介紹,需要的朋友可以參考下
    2022-12-12
  • React中Redux Hooks的使用詳解

    React中Redux Hooks的使用詳解

    這篇文章主要介紹了React Redux Hooks的使用詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考

    基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考

    下面小編就為大家?guī)?lái)一篇基于react框架使用的一些細(xì)節(jié)要點(diǎn)的思考。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • react dva實(shí)現(xiàn)的代碼

    react dva實(shí)現(xiàn)的代碼

    dva是一個(gè)基于redux和redux-saga的數(shù)據(jù)流方案,然后為了簡(jiǎn)化開發(fā)體驗(yàn),dva額外內(nèi)置了react-router,fetch,可以激烈為一個(gè)輕量級(jí)的應(yīng)用框架,這篇文章主要介紹了react dva實(shí)現(xiàn),需要的朋友可以參考下
    2021-11-11
  • react中使用antd及immutable示例詳解

    react中使用antd及immutable示例詳解

    這篇文章主要為大家介紹了react中使用antd及immutable示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • React?Fiber?樹思想解決業(yè)務(wù)實(shí)際場(chǎng)景詳解

    React?Fiber?樹思想解決業(yè)務(wù)實(shí)際場(chǎng)景詳解

    這篇文章主要為大家介紹了React?Fiber?樹思想解決業(yè)務(wù)實(shí)際場(chǎng)景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12

最新評(píng)論

肇东市| 白银市| 佛坪县| 南江县| 青海省| 盐城市| 青冈县| 安宁市| 灵璧县| 格尔木市| 商丘市| 鲁甸县| 兴宁市| 台东县| 汕尾市| 班玛县| 西林县| 报价| 曲靖市| 青田县| 哈尔滨市| 武定县| 泰顺县| 舒城县| 封开县| 如皋市| 新田县| 邵阳县| 孝感市| 潞城市| 苗栗县| 云梦县| 八宿县| 阿合奇县| 益阳市| 乌审旗| 潜江市| 牙克石市| 罗城| 永嘉县| 科技|