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

React實(shí)現(xiàn)antdM的級(jí)聯(lián)菜單實(shí)例

 更新時(shí)間:2022年10月08日 16:01:18   作者:jie19100  
這篇文章主要為大家介紹了React實(shí)現(xiàn)antdM的級(jí)聯(lián)菜單實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

效果圖

需求分析

級(jí)聯(lián)菜單分為兩部分:head與body。

body

包含兩部分:已選項(xiàng)列表,候選菜單

已選項(xiàng)列表

  • body展示當(dāng)前菜單的所有option,可上下滾動(dòng)。
  • body中選一個(gè)option后,會(huì)在head的已選列表中進(jìn)行展示,并且body將顯示下一級(jí)的菜單。
  • 選中的option,背景色和字體需要改變,以示區(qū)分。

候選菜單

  • 依次顯示每個(gè)選中的option,當(dāng)所有option的長(zhǎng)度超過屏幕寬度時(shí),可左右滾動(dòng)
  • 每個(gè)option固定寬度,超出寬度顯示省略號(hào)。
  • 當(dāng)點(diǎn)擊其中一個(gè)option時(shí)候,該項(xiàng)高亮,并且body顯示為該級(jí)的菜單。

head

  • 包含取消和確定兩個(gè)按鈕。
  • 點(diǎn)擊取消,將不做任何處理
  • 確定按鈕需要在級(jí)聯(lián)菜單選到?jīng)]有下一級(jí)的時(shí)候才可點(diǎn)擊
  • 點(diǎn)擊確定,將觸發(fā)回調(diào),攜帶已選的參數(shù)

項(xiàng)目結(jié)構(gòu)

├─ src
│  ├─ App.js
│  ├─ components
│  │  └─ Cascader
│  │     ├─ CascaderContent // content部分
│  │     │  ├─ CascaderContent.js
│  │     │  └─ style.js
│  │     ├─ CascaderHead // head部分
│  │     │  ├─ CascaderHead.js
│  │     │  └─ style.js
│  │     ├─ index.js // 入口
│  │     ├─ style.js
│  │     ├─ Cascader.js
│  │     └─ testData // 測(cè)試數(shù)據(jù)
│  │        └─ data.js
│  ├─ index.css
│  └─ index.js

實(shí)現(xiàn)body部分

levels

根據(jù)數(shù)據(jù)源dataSource與value生成一個(gè)數(shù)組,數(shù)據(jù)結(jié)構(gòu)如下。

數(shù)組的長(zhǎng)度為已選項(xiàng)數(shù)加一,最大為數(shù)據(jù)源的最大深度

onChange

點(diǎn)擊菜單項(xiàng),如果為不可選狀態(tài),則return。如果有onSelect回調(diào),則將已選的value傳遞給回調(diào)函數(shù)

value

初始化的時(shí)候,value為默認(rèn)值,后面在此基礎(chǔ)上進(jìn)行修改

loading

有時(shí)候數(shù)據(jù)可能是異步請(qǐng)求獲取的,增加一個(gè)定時(shí)器,可以在數(shù)據(jù)未加載完的時(shí)候,顯示loading效果。

tabActiveIndex

當(dāng)前候選的菜單的索引,,選中一項(xiàng)后,值加一,如果已經(jīng)選到了最大深度,那么索引為最后一頁(yè)。

classPrefix

是一個(gè)變量,方便設(shè)置公共變量

import React, { useMemo, useState } from "react";
import { useCallback, useEffect } from "react";
import { Wrapper } from "./style";
const classPrefix = `antdm-cascader-view`
export const CascaderContent = function ({ visible = false, ...props }) {
  // 當(dāng)前頁(yè)
  const [tabActiveIndex, setTabActiveIndex] = useState(0);
  // 初始值
  const [value, setValue] = useState(props.value || props.defaultValue || []);
  // loading效果
  const [loading, setLoading] = useState(true);
  const levels = useMemo(() => {
    const ret = []
    let currentOptions = props.options
    let reachedEnd = false
    for (const v of value) {
      const target = currentOptions.find(option => option.value === v)
      ret.push({
        selected: target,
        options: currentOptions,
      })
      // 沒有下一項(xiàng)的時(shí)候中止遍歷
      if (!target || !Array.isArray(target.children) || target.children.length === 0) {
        reachedEnd = true
        break
      }
      currentOptions = target.children
    }
    if (!reachedEnd) {
      ret.push({
        selected: undefined,
        options: currentOptions,
      })
    }
    return ret;
  }, [props.options, value])
  // 點(diǎn)擊選項(xiàng)的時(shí)候
  const onChange = useCallback((item, index) => {
    if (item?.disabled) {
      return
    }
    const newValue = [...value.slice(0, index), item.value];
    setValue(newValue);
    props.onSelect?.(newValue)
  }, [value, props.onSelect])
  // 選中數(shù)據(jù)后,切換下一級(jí)菜單
  useEffect(() => {
    const max = levels.length - 1
    if (tabActiveIndex > max) {
      setTabActiveIndex(max)
    }
  }, [tabActiveIndex, levels])
  useEffect(() => {
    setTabActiveIndex(levels.length - 1)
  }, [value])
  useEffect(() => {
    if (visible) {
      setValue(props.value || props.defaultValue || []);
    }
  }, [visible])
  useEffect(() => {
    setValue(props.value || props.defaultValue || [])
  }, [props.value, props.defaultValue])
  // 設(shè)置定時(shí)器,使用loading效果
  useEffect(() => {
    const timer = setTimeout(() => {
      if (props.options?.length === 0) {
        setLoading(false)
      }
      return () => {
        clearTimeout(timer)
      }
    }, 3000);
  }, [])
  // 數(shù)據(jù)加載完畢后取消loading效果
  useEffect(() => {
    if (props.options.length !== 0) {
      setLoading(false)
    }
  }, [props.options])
  return <Wrapper>
    <div className={classPrefix}>
      <div className={`${classPrefix}-tabs`}>
        {levels.map((item, index) => {
          return <div
            key={index}
            onClick={() => { setTabActiveIndex(index) }}
            className={`${classPrefix}-tab ${tabActiveIndex === index && classPrefix + "-tab-active"}`}>
            {item?.selected?.label ? item?.selected?.label : item?.selected?.label === "" ? "" : "請(qǐng)選擇"}
          </div>
        })}
      </div>
      <div className={`${classPrefix}-content`}>
        {!loading ? levels.map((item, index) => {
          return <div
            key={index.toString()}
            style={{ display: index === tabActiveIndex ? "block" : "none" }}
            className={`${classPrefix}-list`} >
            {item.options.map((o, i) => {
              return <div key={i.toString()} className={`${classPrefix}-item ${o.value === item?.selected?.value && classPrefix + "-item-active"}`}>
                <div
                  onClick={() => onChange(o, index)}
                  className={`${classPrefix}-item-main ${o?.disabled && classPrefix + "-item-disabled"}`}>
                  {o.label}
                </div>
                {o.value === item?.selected?.value && <div className={`${classPrefix}-item-extra`}>?</div>}
              </div>
            })}
          </div>
        }) : "loading..."}
      </div>
    </div>
  </Wrapper>
}

實(shí)現(xiàn)head部分

當(dāng)已經(jīng)沒有下一級(jí)菜單的時(shí)候,確定按鈕變?yōu)榭牲c(diǎn)擊狀態(tài)

import React from "react";
import { Wrapper } from "./style";
const classPrefix = `antdm-cascader`
export const CascaderHead = function (props) {
  return <Wrapper>
    <div className={classPrefix}>
      <div className={`${classPrefix}-header`}>
        <a
          className={`${classPrefix}-header-button`}
          onClick={() => {
            props.onCancel?.()
          }}
        >
          {props.cancelText || "取消"}
        </a>
        <div className={`${classPrefix}-header-title`}>{props.title}</div>
        <a
          className={`${classPrefix}-header-button ${props.canCommit ? '' : classPrefix + '-header-confirm-disable'}`}
          onClick={() => {
            props.canCommit && props.onConfirm?.();
          }}
        >
          {props.confirmText || "確定"}
        </a>
      </div>
    </div>
  </Wrapper>
}

整合head與body

import React, { useState, useCallback, useEffect } from "react";
import { Popup } from "antd-mobile";
import { CascaderHead } from "./CascaderHead/CascaderHead";
import { CascaderContent } from "./CascaderContent/CascaderContent";
import { Wrapper } from "./style";
export const CascaderModal = function (props) {
  const [value, setValue] = useState(props.value || props.defaultValue || []);
  const [canCommit, setCanCommit] = useState(false);
  const onChange = useCallback((v) => {
    setValue(v);
    props.onSelect?.(v)
  }, [props.onSelect])
  // 將選擇的數(shù)據(jù)提交出去
  const onConfirm = useCallback(() => {
    props.onConfirm?.(value)
  }, [props.onConfirm, value])
  // 取消
  const onCancel = useCallback(() => {
    props.onCancel?.()
  }, [props.onCancel])
  useEffect(() => {
    if (value.length === 0) {
      return;
    }
    let children = props.options;
    let i = 0;
    for (i; i < value.length; i++) {
      const obj = children.find(item => item.value === value[i]);
      if (!obj) {
        children = undefined;
        break;
      } else {
        children = obj.children
      }
    }
    setCanCommit(!Array.isArray(children) || children.length === 0)
  }, [value, props.options])
  useEffect(() => {
    setValue(props.value || props.defaultValue || [])
  }, [props.value, props.defaultValue])
  useEffect(() => {
    if (props.visible) {
      setCanCommit(false);
    }
  }, [props.visible])
  return <Wrapper>
    <Popup
      className="antdm-cascader-modal"
      visible={props.visible}
      onClose={onCancel}
      animationType="slide-up"
      popup={true}
    >
      <CascaderHead {...props} canCommit={canCommit} onCancel={onCancel} onConfirm={onConfirm} />
      <CascaderContent {...props} visible={props.visible} onSelect={onChange} />
    </Popup>
  </Wrapper>
}

以上就是React實(shí)現(xiàn)antdM的級(jí)聯(lián)菜單實(shí)例的詳細(xì)內(nèi)容,更多關(guān)于React antdM級(jí)聯(lián)菜單的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React狀態(tài)管理的簡(jiǎn)明指南

    React狀態(tài)管理的簡(jiǎn)明指南

    Redux 是React最常用的集中狀態(tài)管理工具,本文主要介紹了React狀態(tài)管理的簡(jiǎn)明指南,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • React Native仿美團(tuán)下拉菜單的實(shí)例代碼

    React Native仿美團(tuán)下拉菜單的實(shí)例代碼

    本篇文章主要介紹了React Native仿美團(tuán)下拉菜單的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • react性能優(yōu)化達(dá)到最大化的方法 immutable.js使用的必要性

    react性能優(yōu)化達(dá)到最大化的方法 immutable.js使用的必要性

    這篇文章主要為大家詳細(xì)介紹了react性能優(yōu)化達(dá)到最大化的方法,一步一步優(yōu)化react性能的過程,告訴大家使用immutable.js的必要性,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • react 路由跳轉(zhuǎn)的7種方式實(shí)現(xiàn)

    react 路由跳轉(zhuǎn)的7種方式實(shí)現(xiàn)

    本文介紹了React中六種常見的路由跳轉(zhuǎn)方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • react native 文字輪播的實(shí)現(xiàn)示例

    react native 文字輪播的實(shí)現(xiàn)示例

    這篇文章主要介紹了react native 文字輪播的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • 詳解React中的todo-list

    詳解React中的todo-list

    這篇文章主要介紹了React中的todo-list的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-07-07
  • React事件節(jié)流效果失效的原因及解決

    React事件節(jié)流效果失效的原因及解決

    這篇文章主要介紹了React事件節(jié)流效果失效的原因及解決,幫助大家更好的理解和學(xué)習(xí)使用React框架,感興趣的朋友可以了解下
    2021-04-04
  • React如何動(dòng)態(tài)控制偽元素樣式

    React如何動(dòng)態(tài)控制偽元素樣式

    這篇文章主要介紹了React如何動(dòng)態(tài)控制偽元素樣式問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 詳解React中傳入組件的props改變時(shí)更新組件的幾種實(shí)現(xiàn)方法

    詳解React中傳入組件的props改變時(shí)更新組件的幾種實(shí)現(xiàn)方法

    這篇文章主要介紹了詳解React中傳入組件的props改變時(shí)更新組件的幾種實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • React函數(shù)式組件與類組件的不同你知道嗎

    React函數(shù)式組件與類組件的不同你知道嗎

    這篇文章主要為大家詳細(xì)介紹了React函數(shù)式組件與類組件的不同,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評(píng)論

奉化市| 马边| 曲阳县| 新密市| 会理县| 神池县| 新乡市| 益阳市| 修文县| 治多县| 昔阳县| 乌苏市| 翁牛特旗| 景德镇市| 抚州市| 津南区| 叶城县| 宜兰县| 巴里| 保德县| 吐鲁番市| 巴彦淖尔市| 额尔古纳市| 苏州市| 大田县| 上杭县| 乾安县| 基隆市| 盱眙县| 富民县| 甘南县| 隆昌县| 平原县| 津南区| 清流县| 得荣县| 玉门市| 龙山县| 高台县| 宜都市| 通河县|