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

React自定義tab組合組件的實(shí)例詳解

 更新時(shí)間:2026年02月02日 10:08:48   作者:妙團(tuán)團(tuán)  
本文介紹了如何利用React的cloneElementAPI實(shí)現(xiàn)自定義Tab組合組件,通過將TabItem作為Tab的子組件,使用React.cloneElement方法傳遞props和事件處理函數(shù),實(shí)現(xiàn)了父子組件狀態(tài)聯(lián)動(dòng),本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),感興趣的朋友一起看看吧

前言

以前工作中一直使用的vue開發(fā),最近開始寫react的項(xiàng)目,發(fā)現(xiàn)好多基礎(chǔ)都不會(huì),導(dǎo)致在項(xiàng)目開發(fā)中踩坑。這個(gè)系列我打算,從學(xué)習(xí)中實(shí)踐,直到最后完全掌握react。

自定義Tab

我們平時(shí)用的React庫,Tab組件和子組件都是組合使用的,像element的React庫,Tabs.Item是套在Tabs組件里面的,在React的寫法里面,組件是作為children傳遞到父組件里面的。像這種組合的寫,父組件怎么拿到子組件的狀態(tài),從而產(chǎn)生聯(lián)動(dòng)。

既然能夠拿到children,那么通過children就可以監(jiān)聽到子組件的狀態(tài)變化了。這里要用到一個(gè)React的核心api,cloneElement。這個(gè)api克隆的是組件,不是元素。

const newElement = React.cloneElement(
  element,        // 要克隆的目標(biāo)元素(必須是合法的 React 元素,比如 <TabItem />)
  [props],        // 可選:要新增/覆蓋的 props(會(huì)和原元素 props 合并)
  [...children]   // 可選:要替換的子元素(不傳則保留原元素的子元素)
);

實(shí)現(xiàn)代碼

通過cloneElement這個(gè)方法我們可以對(duì)組件進(jìn)行處理,從而監(jiān)聽子組件的狀態(tài),實(shí)現(xiàn)聯(lián)動(dòng)。以下是完整代碼。

import React, { useState, useCallback } from 'react';
import './custom-test-tab.css';
export const TabItem = ({ 
  children, 
  label = '', 
  value, 
  onHandleClick,
  onClick = () => { }, 
  active = false 
}) => {
  const renderClass = () => {
    return `tab-item ${active ? 'active' : ''}`;
  }
  const handleClick = (e) => {
    onHandleClick && onHandleClick(value, e); 
    onClick(e);
  };
  return (
    <div className={renderClass()} onClick={handleClick}>
      { label || children }
    </div>
  );
};
export const Tab = function ({ children, active = '', onChange = () => { } }) {
  const [activeTab, setActiveTab] = useState(active);
  // 2. 修復(fù)handleClick參數(shù)邏輯 + 補(bǔ)充依賴數(shù)組
  const handleClick = useCallback((value) => {
    if (value === undefined) return; // 防止空值
    setActiveTab(value);
    onChange(value);
  }, [onChange]); // 依賴數(shù)組補(bǔ)充onChange,避免閉包問題
  const createdTabs = () => {
    return React.Children.map(children, (child) => {
      // 安全校驗(yàn):只處理TabItem類型的子組件
      if (!React.isValidElement(child) || child.type !== TabItem) {
        return child;
      }
      return React.cloneElement(child, {
        onHandleClick: handleClick, // 直接傳遞函數(shù),無需包裝
        active: activeTab === child.props.value,
      });
    });
  };
  return (
    <div className={'custom-test-tab'}>
      {createdTabs()}
    </div>/
  );
};
// 3. 確保Tab.Item正確掛載
Tab.Item = TabItem;
export default Tab;

使用自定義的Tab

import { useState} from "react";
import { Tab, TabItem } from "../components/custom-test-tab";
export const TestTab = () => {
  const [active, setActive] = useState('蘋果');
  const onChange = (value) => {
    setActive(value);
  };
  const tabList = [
    { label: "蘋果", value: "蘋果", bgColor: "#FF5252" },   // 蘋果 - 紅色
    { label: "香蕉", value: "香蕉", bgColor: "#FFC107" },   // 香蕉 - 黃色
    { label: "橘子", value: "橘子", bgColor: "#FF9800" },   // 橘子 - 橙色
    { label: "葡萄", value: "葡萄", bgColor: "#9C27B0" },   // 葡萄 - 紫色
    { label: "鳳梨", value: "鳳梨", bgColor: "#4CAF50" },   // 鳳梨 - 綠色
  ];
  const ContentView = ({ active }) => {
    const item = tabList.find(item => item.value === active);
    if (!item) return null;
    return (
      <div style={
        { 
          backgroundColor: item.bgColor,
          width: "100%",
          height: '200px'
         }
      }>
        {active === "蘋果" && <div>蘋果</div>}
        {active === "香蕉" && <div>香蕉</div>}
        {active === "橘子" && <div>橘子</div>}
        {active === "葡萄" && <div>葡萄</div>}
        {active === "鳳梨" && <div>鳳梨</div>}
      </div>
    );
  }; 
  return (
    <div>
      <h1>自定義組件</h1>
      <Tab onChange={onChange} active={active}>
        {
          tabList.map((item, index) => (
            <TabItem key={index} label={item.label} value={item.value}>
              {item.label}
            </TabItem>
          ))
        }
      </Tab>
      <Tab onChange={onChange} active={active}>
        {
          tabList.map((item, index) => (
            <Tab.Item key={index} label={item.label} value={item.value}>
              {item.label}
            </Tab.Item>
          ))
        }
      </Tab>
      <ContentView active={active} />
    </div>
  );
};
export default TestTab;

渲染效果

總結(jié)

證明封裝的Tab組件是可以的,通過這個(gè)Tab組件的封裝,不止是學(xué)會(huì)了封裝這個(gè)組件,還通過這個(gè)過程學(xué)會(huì)了,組合組件封裝的過程。

到此這篇關(guān)于React學(xué)習(xí)之自定義tab組合組件的文章就介紹到這了,更多相關(guān)React自定義tab組合組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用React-router+Webpack快速構(gòu)建react程序

    利用React-router+Webpack快速構(gòu)建react程序

    目前 React、Webpack 等技術(shù)如火如荼,你是不是還在愁苦如何把這些雜亂的知識(shí)怎么學(xué)習(xí)一下,開啟一段新的前端開發(fā)之路呢?那么這篇將給大家運(yùn)用示例代碼詳細(xì)的介紹使用React-router和Webpack如何快速構(gòu)建一個(gè)react程序,感興趣的朋友們下面來一起看看吧。
    2016-10-10
  • React Native驗(yàn)證碼倒計(jì)時(shí)工具類分享

    React Native驗(yàn)證碼倒計(jì)時(shí)工具類分享

    這篇文章主要為大家分享了React Native驗(yàn)證碼倒計(jì)時(shí)工具類,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • 如何在React中通過URL預(yù)覽Excel文件

    如何在React中通過URL預(yù)覽Excel文件

    這篇文章主要為大家詳細(xì)介紹了如何在React中通過URL預(yù)覽Excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • React高階組件優(yōu)化文件結(jié)構(gòu)流程詳解

    React高階組件優(yōu)化文件結(jié)構(gòu)流程詳解

    高階組件就是接受一個(gè)組件作為參數(shù)并返回一個(gè)新組件(功能增強(qiáng)的組件)的函數(shù)。這里需要注意高階組件是一個(gè)函數(shù),并不是組件,這一點(diǎn)一定要注意,本文給大家分享React 高階組件HOC使用小結(jié),一起看看吧
    2023-01-01
  • antd-react使用Select組件defaultValue踩的坑及解決

    antd-react使用Select組件defaultValue踩的坑及解決

    這篇文章主要介紹了antd-react使用Select組件defaultValue踩的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案

    ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案

    這篇文章主要為大家介紹了ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • React經(jīng)典面試題之倒計(jì)時(shí)組件詳解

    React經(jīng)典面試題之倒計(jì)時(shí)組件詳解

    這些天也都在面試,面試的內(nèi)容也大多千篇一律,無外乎vue、react這些框架的一些原理,和使用方法,但是也遇到些有趣的題目,這篇文章主要給大家介紹了關(guān)于React經(jīng)典面試題之倒計(jì)時(shí)組件的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • 使用React Native創(chuàng)建以太坊錢包實(shí)現(xiàn)轉(zhuǎn)賬等功能

    使用React Native創(chuàng)建以太坊錢包實(shí)現(xiàn)轉(zhuǎn)賬等功能

    這篇文章主要介紹了使用React Native創(chuàng)建以太坊錢包,實(shí)現(xiàn)轉(zhuǎn)賬等功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • React+Antd+Redux實(shí)現(xiàn)待辦事件的方法

    React+Antd+Redux實(shí)現(xiàn)待辦事件的方法

    這篇文章主要介紹了React+Antd+Redux實(shí)現(xiàn)待辦事件的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • redux持久化之redux-persist結(jié)合immutable使用問題

    redux持久化之redux-persist結(jié)合immutable使用問題

    這篇文章主要為大家介紹了redux持久化之redux-persist結(jié)合immutable使用問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評(píng)論

历史| 锡林浩特市| 内丘县| 台南市| 永胜县| 响水县| 徐水县| 麻城市| 酉阳| 榆树市| 临武县| 武安市| 长沙市| 依安县| 绵阳市| 剑阁县| 威远县| 社旗县| 潢川县| 中方县| 高青县| 峨眉山市| 明光市| 汝城县| 青浦区| 读书| 黄龙县| 永寿县| 汕尾市| 通许县| 宁德市| 黄龙县| 虞城县| 泰州市| 芦山县| 滨海县| 古浪县| 多伦县| 晴隆县| 清徐县| 昌邑市|