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

react實現拖拽模態(tài)框

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

前言

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

實踐

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

新建文件ModalDrag/index.js,將下面代碼copy進去

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

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

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

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

//main_class和title_class都是類名
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, //只拖拽類名為 ${main_class} 的div
? ? ? ? ? ? title_class?child_node.querySelector(`.${title_class}`):child_node //當鼠標按在類名為 ${title_class} 的div上時才允許拖拽
? ? ? ? ? );
? ? ? ? }
? ? ? }, 0);
? ? };

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

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

如果在實踐中發(fā)現拖拽無效,請務必將上面代碼中的child_node打印出來,觀察是否獲取到了真實的dom以及它內部是否渲染完整.如果沒有渲染完全,說明InnerComponent包含異步渲染的代碼,要等到渲染完畢后再進行拖拽事件綁定

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

新建文件ModalDrag/drag.js,將下面代碼copy進去

下面是實現拖拽的原生代碼.主要負責對dom元素進行事件綁定以及改變位置等

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

? constructor(target, move_item) {
? ? this.target = target; //被移動的dom元素
? ? this.move_item = move_item; //接受觸發(fā)移動行為的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; //檢測鼠標是否處于按下的狀態(tài)
? ? this.start_x0 = e.pageX;
? ? this.start_y0 = e.pageY;
? }

? moving(e) {
? ? //鼠標移動時的默認操作
? ? 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.外部調用

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

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

其他場景需要根據靜態(tài)模態(tài)框組件的dom結構分析哪一部分是要移動的,哪一部分是監(jiān)聽拖拽的,將這兩部分的類名作為參數傳入

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

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

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

調用時需要注意,當visible為true時再渲染ToastExportv2,為了防止綁定事件時dom還沒開始渲染.visible為false時,組件銷毀會自動調用destory方法解綁已注冊的事件

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • React?模式之純組件使用示例詳解

    React?模式之純組件使用示例詳解

    這篇文章主要為大家介紹了React?模式之純組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • react實現移動端二級路由嵌套詳解

    react實現移動端二級路由嵌套詳解

    這篇文章主要介紹了react移動端二級路由嵌套的實現方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • React 路由react-router-dom示例詳解

    React 路由react-router-dom示例詳解

    一個路由就是一個映射關系(key:value),key為路徑, value可能是function或component,本文給大家介紹React 路由react-router-dom詳解,感興趣的朋友跟隨小編一起看看吧
    2024-01-01
  • React使用refs操作DOM方法詳解

    React使用refs操作DOM方法詳解

    React核心就在于虛擬DOM,也就是在React中不總是直接操作頁面真實的DOM元素,并且結合Diffing算法,可以做到最小化頁面重繪,有些時候不可避免的我們需要一種方法可以操作我們定義的元素標簽,并作出對應的修改。在React中提供了一種訪問DOM節(jié)點的方式,也就是這里的refs
    2022-11-11
  • React?之最小堆min?heap圖文詳解

    React?之最小堆min?heap圖文詳解

    這篇文章主要為大家介紹了React?之最小堆min?heap圖文詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • React父子組件互相通信的實現示例

    React父子組件互相通信的實現示例

    React中是單向數據流,數據只能從父組件通過屬性的方式傳給其子組件,本文主要介紹了React父子組件互相通信的實現示例,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • react實現阻止父容器滾動

    react實現阻止父容器滾動

    這篇文章主要介紹了react實現阻止父容器滾動方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • react native圖片解析流程詳解

    react native圖片解析流程詳解

    這篇文章主要為大家介紹了react native圖片解析流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • React常見跨窗口通信方式實例詳解

    React常見跨窗口通信方式實例詳解

    這篇文章主要為大家介紹了React常見跨窗口通信方式實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • 2個奇怪的react寫法

    2個奇怪的react寫法

    大家好,我卡頌。雖然React官網用大量篇幅介紹最佳實踐,但因JSX語法的靈活性,所以總是會出現奇奇怪怪的React寫法。本文介紹2種奇怪(但在某些場景下有意義)的React寫法。也歡迎大家在評論區(qū)討論你遇到過的奇怪寫法
    2023-03-03

最新評論