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

react實(shí)現(xiàn)拖拽模態(tài)框

 更新時(shí)間:2022年08月26日 15:07:30   作者:_Kay_  
這篇文章主要為大家詳細(xì)介紹了react實(shí)現(xiàn)拖拽模態(tài)框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

前言

實(shí)際開(kāi)發(fā)中,模態(tài)框展現(xiàn)數(shù)據(jù)會(huì)經(jīng)常出現(xiàn).但不幸的是有時(shí)功能開(kāi)發(fā)完了,UI同學(xué)突然提出需求希望模態(tài)框能拖拽.本文使用的模態(tài)框由 ant design 3.0 的 Modal 組件封裝而成,如何在不修改原來(lái)代碼的基礎(chǔ)上實(shí)現(xiàn)拖拽呢.最終效果圖如下:

實(shí)踐

1.創(chuàng)建高階組件DragHoc

新建文件ModalDrag/index.js,將下面代碼copy進(jìn)去

DragObj是具體拖拽的原生js代碼,后面再看

  • DragHoc是創(chuàng)建高階組件的函數(shù),其中參數(shù)InnerComponent是需要被改造的模態(tài)框組件,函數(shù)最終的返回值是增強(qiáng)后的組件
  • render方法中直接返回了 <InnerComponent/> ,并沒(méi)有返回一個(gè)新組件.整個(gè)高階組件的作用只是在輸入組件上加了一個(gè)ref屬性.有了ref,init方法中可以通過(guò) ReactDOM.findDOMNode 獲取到傳入的任意組件的原生dom.拿到dom以后就可以做底層的dom操作或事件綁定以實(shí)現(xiàn)拖拽
  • init方法里加了一個(gè)延時(shí)0s的定時(shí)器,由于筆者的項(xiàng)目中InnerComponent是用ant design里面的Modal封裝而成.在調(diào)試的過(guò)程中發(fā)現(xiàn),ReactDOM.findDOMNode 只能返回已經(jīng)掛載到頁(yè)面上的dom元素,否則返回null.而ant design里面的Modal渲染內(nèi)容是異步的,因此要使用定時(shí)器等到下一幀才能使用findDOMNode得到組件的dom元素.如果InnerComponent里面不包含異步渲染的代碼,下面的定時(shí)器可以刪除
  • 組件卸載時(shí)調(diào)用destory方法將所有綁定的事件釋放掉

拖拽一個(gè)元素通常需要傳入兩個(gè)參數(shù).一個(gè)是推拽后能移動(dòng)的區(qū)域,對(duì)應(yīng)著上圖中的整個(gè)導(dǎo)出表格控件,控件的類(lèi)名為main_class.另外一個(gè)是監(jiān)聽(tīng)拖拽的區(qū)域,對(duì)應(yīng)著上圖中的頭部,只有當(dāng)鼠標(biāo)在頭部按下時(shí)再移動(dòng)才能拖動(dòng)表格.頭部的類(lèi)名為title_class.兩個(gè)參數(shù)都從外部傳入.如果兩個(gè)參數(shù)都不傳,默認(rèn)直接監(jiān)聽(tīng)child_node并拖拽child_node

import React from 'react';
import ReactDOM from 'react-dom';
import DragObj from './drag';

//main_class和title_class都是類(lèi)名
export const DragHoc = (InnerComponent,main_class,title_class) =>
? class extends React.Component {
? ? componentDidMount() {
? ? ? this.init();
? ? }

? ? init = () => {
? ? ? setTimeout(() => {
? ? ? ? const child_node = ReactDOM.findDOMNode(this.refs.child); //獲取到原生的dom元素
? ? ? ? if (child_node) {
? ? ? ? ? this.drag_obj = new DragObj(
? ? ? ? ? ? main_class?child_node.querySelector(`.${main_class}`):child_node, //只拖拽類(lèi)名為 ${main_class} 的div
? ? ? ? ? ? title_class?child_node.querySelector(`.${title_class}`):child_node //當(dāng)鼠標(biāo)按在類(lèi)名為 ${title_class} 的div上時(shí)才允許拖拽
? ? ? ? ? );
? ? ? ? }
? ? ? }, 0);
? ? };

? ? componentWillUnmount() {
? ? ? if (this.drag_obj) {
? ? ? ? this.drag_obj.destory();
? ? ? }
? ? }

? ? render() {
? ? ? return <InnerComponent {...this.props} ref="child" />;
? ? }
? };

如果在實(shí)踐中發(fā)現(xiàn)拖拽無(wú)效,請(qǐng)務(wù)必將上面代碼中的child_node打印出來(lái),觀察是否獲取到了真實(shí)的dom以及它內(nèi)部是否渲染完整.如果沒(méi)有渲染完全,說(shuō)明InnerComponent包含異步渲染的代碼,要等到渲染完畢后再進(jìn)行拖拽事件綁定

2.創(chuàng)建拖拽類(lèi)DragObj

新建文件ModalDrag/drag.js,將下面代碼copy進(jìn)去

下面是實(shí)現(xiàn)拖拽的原生代碼.主要負(fù)責(zé)對(duì)dom元素進(jìn)行事件綁定以及改變位置等

export default class DragObj {
? start_x0 = 0;
? start_y0 = 0;
? start_x1 = 0;
? start_y1 = 0;
? state = false; //記錄鼠標(biāo)按鍵是否松開(kāi)
? delta_x = 0; //相對(duì)于原始位置的橫向偏移量
? delta_y = 0; //相對(duì)于原始位置的縱向偏移量

? constructor(target, move_item) {
? ? this.target = target; //被移動(dòng)的dom元素
? ? this.move_item = move_item; //接受觸發(fā)移動(dòng)行為的dom元素,一般為模態(tài)框的頭部
? ? this.init();
? }

? init() {
? ? this.move_item.style.cursor = 'move';
? ? this.bindEvent();
? }

? destory() {
? ? this.move_item.removeEventListener('mousedown', this.moveStartFun);
? ? document.removeEventListener('mousemove', this.movingFun);
? ? document.removeEventListener('mouseup', this.moveEndFun);
? }

? bindEvent() {
? ? this.moveStartFun = this.moveStart.bind(this);
? ? this.movingFun = this.moving.bind(this);
? ? this.moveEndFun = this.moveEnd.bind(this);
? ? this.move_item.addEventListener('mousedown', this.moveStartFun);
? ? document.addEventListener('mousemove', this.movingFun);
? ? document.addEventListener('mouseup', this.moveEndFun);
? }

? moveStart(e) {
? ? e.stopPropagation();
? ? this.state = true; //檢測(cè)鼠標(biāo)是否處于按下的狀態(tài)
? ? this.start_x0 = e.pageX;
? ? this.start_y0 = e.pageY;
? }

? moving(e) {
? ? //鼠標(biāo)移動(dòng)時(shí)的默認(rèn)操作
? ? e.stopPropagation();
? ? e.preventDefault();
? ? if (!this.state) {
? ? ? return false;
? ? }

? ? this.start_x1 = e.pageX;
? ? this.start_y1 = e.pageY;
? ? this.render();
? }

? moveEnd(e) {
? ? if (!this.state) {
? ? ? return false;
? ? }
? ? this.state = false;
? ? this.delta_x = this.start_x1 - this.start_x0 + this.delta_x;
? ? this.delta_y = this.start_y1 - this.start_y0 + this.delta_y;
? }

? render() {
? ? this.target.style.transform = `translate(${
? ? ? this.start_x1 - this.start_x0 + this.delta_x
? ? }px,${this.start_y1 - this.start_y0 + this.delta_y}px)`;
? }
}

3.外部調(diào)用

引入高階函數(shù)DragHoc,引入需要增強(qiáng)的模態(tài)框組件ToastExport

由于筆者在項(xiàng)目中使用 ant design 3.0 中的 Modal 組件做模態(tài)框,讓其拖拽只需要傳遞類(lèi)名 “ant-modal-content” 和 “ant-modal-header”.

其他場(chǎng)景需要根據(jù)靜態(tài)模態(tài)框組件的dom結(jié)構(gòu)分析哪一部分是要移動(dòng)的,哪一部分是監(jiān)聽(tīng)拖拽的,將這兩部分的類(lèi)名作為參數(shù)傳入

import { DragHoc } from "./index.js";
import ToastExport from "../components/ToastExport/index.js";
//引入靜態(tài)的模態(tài)框組件(用戶(hù)自已定義的模態(tài)框組件)
const ToastExportv2 = DragHoc(ToastExport,"ant-modal-content","ant-modal-header"); 
//生成了具備拖拽功能的模態(tài)框組件

調(diào)用DragHoc函數(shù)生成ToastExportv2后,接下來(lái)就可以頁(yè)面上直接使用.如果業(yè)務(wù)上需要傳遞參數(shù)直接加在屬性上

const { visible } = this.props; ?//visible控制顯示隱藏模態(tài)框
{visible?<ToastExportv2 visible={visible}/>:null}

調(diào)用時(shí)需要注意,當(dāng)visible為true時(shí)再渲染ToastExportv2,為了防止綁定事件時(shí)dom還沒(méi)開(kāi)始渲染.visible為false時(shí),組件銷(xiāo)毀會(huì)自動(dòng)調(diào)用destory方法解綁已注冊(cè)的事件

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • react創(chuàng)建項(xiàng)目啟動(dòng)報(bào)錯(cuò)的完美解決方法

    react創(chuàng)建項(xiàng)目啟動(dòng)報(bào)錯(cuò)的完美解決方法

    這篇文章主要介紹了react創(chuàng)建項(xiàng)目啟動(dòng)報(bào)錯(cuò)的完美解決方法,全稱(chēng)為Node Package Manager,是隨同NodeJS一起安裝的包管理工具,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • React使用react-sortable-hoc如何實(shí)現(xiàn)拖拽效果

    React使用react-sortable-hoc如何實(shí)現(xiàn)拖拽效果

    這篇文章主要介紹了React使用react-sortable-hoc如何實(shí)現(xiàn)拖拽效果問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • redux持久化之redux-persist結(jié)合immutable使用問(wèn)題

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

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

    關(guān)于hooks中useEffect()的使用總結(jié)

    這篇文章主要介紹了關(guān)于hooks中useEffect()的使用總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • react進(jìn)階教程之異常處理機(jī)制error?Boundaries

    react進(jìn)階教程之異常處理機(jī)制error?Boundaries

    在react中一旦出錯(cuò),如果每個(gè)組件去處理出錯(cuò)情況則比較麻煩,下面這篇文章主要給大家介紹了關(guān)于react進(jìn)階教程之異常處理機(jī)制error?Boundaries的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • React和Vue組件更新的實(shí)現(xiàn)及區(qū)別

    React和Vue組件更新的實(shí)現(xiàn)及區(qū)別

    React 和 Vue 都是當(dāng)今最流行的前端框架,它們都實(shí)現(xiàn)了組件化開(kāi)發(fā)模式,本文將從React和Vue的組件更新原理入手,剖析兩者虛擬DOM difer算法的異同點(diǎn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • React 如何使用時(shí)間戳計(jì)算得到開(kāi)始和結(jié)束時(shí)間戳

    React 如何使用時(shí)間戳計(jì)算得到開(kāi)始和結(jié)束時(shí)間戳

    這篇文章主要介紹了React 如何拿時(shí)間戳計(jì)算得到開(kāi)始和結(jié)束時(shí)間戳,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-09-09
  • React實(shí)現(xiàn)文件分片上傳和下載的方法詳解

    React實(shí)現(xiàn)文件分片上傳和下載的方法詳解

    在當(dāng)今的前端開(kāi)發(fā)中,處理文件流操作已經(jīng)成為一個(gè)常見(jiàn)的需求,無(wú)論是上傳、下載、讀取、展示還是其他的文件處理操作,都需要高效且可靠地處理二進(jìn)制數(shù)據(jù),本文將深入探討如何使用 React 實(shí)現(xiàn)文件分片上傳和下載,并介紹相關(guān)的基本概念和技術(shù),需要的朋友可以參考下
    2023-08-08
  • React動(dòng)態(tài)更改html標(biāo)簽的實(shí)現(xiàn)方式

    React動(dòng)態(tài)更改html標(biāo)簽的實(shí)現(xiàn)方式

    這篇文章主要介紹了React動(dòng)態(tài)更改html標(biāo)簽的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 使用React Native創(chuàng)建以太坊錢(qián)包實(shí)現(xiàn)轉(zhuǎn)賬等功能

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

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

最新評(píng)論

五指山市| 大城县| 韶山市| 扬州市| 瓮安县| 饶阳县| 隆化县| 五家渠市| 清涧县| 新乐市| 马公市| 铁力市| 上饶县| 诸城市| 大丰市| 沭阳县| 杨浦区| 新宾| 白河县| 庆阳市| 安达市| 浮山县| 宜良县| 准格尔旗| 西乡县| 桓台县| 拜泉县| 精河县| 郎溪县| 长治县| 苍梧县| 台南县| 绵竹市| 唐海县| 灌阳县| 邢台县| 栾川县| 安多县| 南京市| 邵阳市| 昆明市|