欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解

 更新時(shí)間:2023年03月06日 11:58:46   作者:samwangdd  
這篇文章主要為大家介紹了React結(jié)合Drag?API實(shí)現(xiàn)拖拽示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

認(rèn)識(shí)拖拽

鼠標(biāo)拖拽是一個(gè)常見(jiàn)的交互場(chǎng)景,在這個(gè)熟悉的過(guò)程將會(huì)發(fā)生哪些事件?

拖拽事件指用戶(hù)通過(guò)鼠標(biāo)(或其他指針設(shè)備)將元素移到一個(gè)新的位置上。拖拽過(guò)程涉及兩個(gè)對(duì)象:被拖拽元素(上圖中 A )和可釋放目標(biāo)(上圖中 B )

被拖拽元素

默認(rèn)情況下,圖片、鏈接和文本是可拖動(dòng)的。HTML5 在所有 HTML 元素上規(guī)定了一個(gè) draggable 屬性, 表示元素是否可以拖動(dòng)。圖片和鏈接的 draggable 屬性自動(dòng)被設(shè)置為 true,而其他所有元素此屬性的默認(rèn)值為 false。

某個(gè)元素被拖動(dòng)時(shí),會(huì)依次觸發(fā)以下事件:

  • ondragstart:拖動(dòng)開(kāi)始,當(dāng)鼠標(biāo)按下并且開(kāi)始移動(dòng)鼠標(biāo)時(shí),觸發(fā)此事件;整個(gè)周期只觸發(fā)一次;
  • ondrag:只要元素仍被拖拽,就會(huì)持續(xù)觸發(fā)此事件;
  • ondragend:拖拽結(jié)束,當(dāng)鼠標(biāo)松開(kāi)后,會(huì)觸發(fā)此事件;整個(gè)周期只觸發(fā)一次。

可釋放目標(biāo)

當(dāng)把拖拽元素移動(dòng)到一個(gè)有效的放置目標(biāo)時(shí),目標(biāo)對(duì)象會(huì)觸發(fā)以下事件:

  • ondragenter:只要一把拖拽元素移動(dòng)到目標(biāo)時(shí),就會(huì)觸發(fā)此事件;
  • ondragover:拖拽元素在目標(biāo)中拖動(dòng)時(shí),會(huì)持續(xù)觸發(fā)此事件;
  • ondragleaveondrop:拖拽元素離開(kāi)目標(biāo)時(shí)(沒(méi)有在目標(biāo)上放下),會(huì)觸發(fā)ondragleave;當(dāng)拖拽元素在目標(biāo)放下(松開(kāi)鼠標(biāo)),則觸發(fā)ondrop事件。

?? 目標(biāo)元素默認(rèn)是不能夠被拖放的,即不會(huì)觸發(fā) ondrop 事件,可以通過(guò)在目標(biāo)元素的 ondragover 事件中取消默認(rèn)事件來(lái)解決此問(wèn)題。

生命周期

拖拽操作中的數(shù)據(jù)傳輸

除非數(shù)據(jù)受影響,否則簡(jiǎn)單的拖放并沒(méi)有實(shí)際意義。為實(shí)現(xiàn)拖動(dòng)操作中的數(shù)據(jù)傳輸,event 對(duì)象上暴露了 dataTransfer 對(duì)象,用于從被拖動(dòng)元素向放置目標(biāo)傳遞字符串?dāng)?shù)據(jù)。我們使用它來(lái)通知畫(huà)布,當(dāng)前需要渲染的組件是什么。

dataTransfer 對(duì)象主要有兩個(gè)方法:getData() 和 setData(),分別用來(lái)獲取和存儲(chǔ)值。setData()的第一個(gè)參數(shù)以及 getData()的唯一參數(shù)是一個(gè)字符串,表示要設(shè)置的數(shù)據(jù)類(lèi)型:"text"或"URL"

?? 雖然這兩種數(shù)據(jù)類(lèi)型是 IE 最初引入的,但 HTML5 已經(jīng)將其擴(kuò)展為允許任何 MIME 類(lèi)型。為向后 兼容,HTML5 還會(huì)繼續(xù)支持"text"和"URL",但它們會(huì)分別被映射到"text/plain"和"text/uri-list”

需要注意的是:存儲(chǔ)在 dataTransfer 對(duì)象中的數(shù)據(jù)只能在放置事件中讀取。如果沒(méi)有在 ondrop 事件中取得這些數(shù)據(jù),dataTransfer 對(duì)象就會(huì)被銷(xiāo)毀,數(shù)據(jù)也會(huì)丟失。

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

我在項(xiàng)目中使用 React 來(lái)實(shí)現(xiàn),并且考慮到跨組件通信,我使用了 dva 來(lái)管理數(shù)據(jù)流。

如何標(biāo)記當(dāng)前拖拽的元素?

HTML5 支持的 data-x 屬性,我們可以將當(dāng)前組件的類(lèi)型 Rectangle 賦值給它,這樣處理和畫(huà)布組件通信方便一些

const Block = (props) => {
  const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {
    // 向拖拽數(shù)據(jù)中添加項(xiàng)目    
    e.dataTransfer.setData('text', e.target.dataset.index);
  };
  return (
    <div onDragStart={handleDragStart}>
      <Button draggable data-index="Rectangle">
        二維碼
      </Button>
    </div>
  );
};

在上文中講到,dataTransfer 的數(shù)據(jù)必須在 handleDrop 方法中獲取。實(shí)際的用來(lái)保存畫(huà)布中的所有組件的數(shù)據(jù):

function DragEditor(props) {
  const { dvaStore, dispatch } = props;
  // 阻止瀏覽器默認(rèn)事件,否則 ondrop 不會(huì)觸發(fā)
  const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
  };
  const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    // 獲取拖拽元素的組件類(lèi)型
    const type = e.dataTransfer.getData('text');
    // COMPONENT_LIST 定義了組件的數(shù)據(jù)格式,根據(jù) type 匹配
    const component = COMPONENT_LIST.filter(
      (i) => i.component === type,
    )[0];
    // 將組件數(shù)據(jù)添加到 store,畫(huà)布將會(huì)根據(jù)數(shù)據(jù)渲染出組件
    if (component) {
      dispatch?.({
        type: 'store/addComponent',
        payload: component,
      });
    }
  };
  return (...);
}

在畫(huà)布中拖動(dòng)

拖動(dòng)主要依賴(lài)組件的初始位置,鼠標(biāo)開(kāi)始位置、結(jié)束位置。根據(jù)后兩組得到鼠標(biāo)移動(dòng)的距離,和初始位置相加后,得到最終位置。

function DragEditor(props: IEditorProps) {
  const { dvaStore, dispatch } = props;
  const [startAxis, setStartAxis] = React.useState({ x: 0, y: 0 }); // 鼠標(biāo)開(kāi)始拖動(dòng)時(shí)的位置
  const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {
    setStartAxis({ x: e.clientX, y: e.clientY });
  };
  const handleDragEnd = (e: React.DragEvent<HTMLDivElement>, data: IComponentSchema) => {
    // 鼠標(biāo)移動(dòng)的距離
    const displacementX = e.clientX - startAxis.x;
    const displacementY = e.clientY - startAxis.y;
    // 計(jì)算組件的終點(diǎn)位置:初始位置 + 鼠標(biāo)移動(dòng)的距離
    const endX = Number(data.style.left) + displacementX;
    const endY = Number(data.style.top) + displacementY;
    // 限制坐標(biāo)的最小值為 0
    const top = Math.max(endY, 0);
    const left = Math.max(endX, 0);
    // 更新當(dāng)前組件樣式
    dispatch?.({
      type: 'store/setShapeStyle',
      payload: { top, left },
    });
  };
  return (
      {dvaStore.componentsData.map((i) => {
        return (
          <RenderComponent
            type={i.component}
            componentData={i}
            key={i.generateId}
            onDragStart={handleDragStart}
            onDragEnd={(e) => handleDragEnd(e, i)}
          />
        );
      })}
  );
}

數(shù)據(jù)結(jié)構(gòu)

最后,就是組件和數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),RenderComponent 是一個(gè)自定義的組件,會(huì)根據(jù)傳入的 type 屬性渲染對(duì)應(yīng)的組件。組件的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:

export const COMPONENT_LIST = [
  {
    component: 'Rectangle', // 組件名稱(chēng)
    label: '矩形', // 左側(cè) Blocks 組件列表中顯示的名字
    propValue: '', // 組件所使用的值
    icon: 'BorderOuterOutlined', // 左側(cè)組件列表中顯示的 icon 圖標(biāo)
    animations: [], // 動(dòng)畫(huà)列表
    events: {}, // 事件列表
    style: {    // 組件樣式
      width: 100,
      height: 100,
      top: 0,
      left: 0,
    },
  },
  {
    component: 'Text',
    label: '文字',
    propValue: '文字',
    icon: '',
    animations: [],
    events: {},
    style: {
      width: 200,
      height: 33,
      fontSize: 14,
      fontWeight: 500,
      lineHeight: '',
      letterSpacing: 0,
      textAlign: '',
      color: '',
    },
  },
];

總結(jié)

拖拽是非常有趣的一種交互,特別是在低代碼場(chǎng)景下非常重要。使用原生 API 能夠讓我們更加了解底層的一些細(xì)節(jié),React 社區(qū)也有一些優(yōu)秀的第三方框架,如:react-dragable, react-beautiful-dnd,大家有興趣不妨再多了解下。

Links HTML 拖放 API

以上就是React結(jié)合Drag API實(shí)現(xiàn)拖拽示例詳解的詳細(xì)內(nèi)容,更多關(guān)于React Drag API拖拽的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React實(shí)現(xiàn)todolist功能

    React實(shí)現(xiàn)todolist功能

    這篇文章主要介紹了React實(shí)現(xiàn)todolist功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • React函數(shù)組件與類(lèi)的區(qū)別有哪些

    React函數(shù)組件與類(lèi)的區(qū)別有哪些

    函數(shù)式組件的基本意義就是,組件實(shí)際上是一個(gè)函數(shù),不是類(lèi),下面這篇文章主要給大家介紹了關(guān)于React中函數(shù)組件與類(lèi)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • 使用useImperativeHandle時(shí)父組件第一次沒(méi)拿到子組件的問(wèn)題

    使用useImperativeHandle時(shí)父組件第一次沒(méi)拿到子組件的問(wèn)題

    這篇文章主要介紹了使用useImperativeHandle時(shí)父組件第一次沒(méi)拿到子組件的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vite搭建React項(xiàng)目的方法步驟

    Vite搭建React項(xiàng)目的方法步驟

    這篇文章主要介紹了Vite搭建React項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • React Hooks之使用useCallback和useMemo進(jìn)行性能優(yōu)化方式

    React Hooks之使用useCallback和useMemo進(jìn)行性能優(yōu)化方式

    這篇文章主要介紹了React Hooks之使用useCallback和useMemo進(jìn)行性能優(yōu)化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • JS跨域解決方案react配置反向代理

    JS跨域解決方案react配置反向代理

    這篇文章主要為大家介紹了JS跨域解決方案react配置反向代理的示例內(nèi)容詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • 關(guān)于react hook useState連續(xù)更新對(duì)象的問(wèn)題

    關(guān)于react hook useState連續(xù)更新對(duì)象的問(wèn)題

    這篇文章主要介紹了關(guān)于react hook useState連續(xù)更新對(duì)象的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • react父組件調(diào)用子組件的方式匯總

    react父組件調(diào)用子組件的方式匯總

    在react中常用props實(shí)現(xiàn)子組件數(shù)據(jù)到父組件的傳遞,但是父組件調(diào)用子組件的功能卻不常用,下面這篇文章主要給大家介紹了關(guān)于react父組件調(diào)用子組件的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 深入理解React與閉包的關(guān)系

    深入理解React與閉包的關(guān)系

    本文將深入探討React與閉包之間的關(guān)系,我們將首先介紹React和閉包的基本概念,然后詳細(xì)解釋React組件中如何使用閉包來(lái)處理狀態(tài)和作用域的問(wèn)題,希望通過(guò)本文的閱讀,你將對(duì)React中閉包的概念有更深入的理解,并能夠在開(kāi)發(fā)React應(yīng)用時(shí)更好地應(yīng)用閉包
    2023-07-07
  • 簡(jiǎn)單的React SSR服務(wù)器渲染實(shí)現(xiàn)

    簡(jiǎn)單的React SSR服務(wù)器渲染實(shí)現(xiàn)

    這篇文章主要介紹了簡(jiǎn)單的React SSR服務(wù)器渲染實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12

最新評(píng)論