低代码3之撤销与重做操作以及快捷键ctrl+z与ctrl+y

  • 安装依赖
    • npm i mitt
  • 功能:
    • 撤销与重做
      • 需要在useMenuDragger.js之中抛出事件events.emit('start'); // 拖拽前与events.emit('end'); // 拖拽后
      • 需要在useBlockDragger.js之中 标记一个拖拽的状态dragging=> 用于标记从后台渲染后的组件是否被拖拽的状态、并且在mousemove和mouseup之中抛出事件
      • useCommand.js 之中 处理撤销和重做功能

    • mitt 为bus总线

src / package / useCommand.js

// 菜单拖拽功能
import {
   
    
     events } from "./events"
export function useMenuDragger (containerRef,data){
   
    
    
  let currentComponent = null // 当前拖拽的组件
  const dragstart = (e,component)=>{
   
    
    
    // dragenter 进入元素中,添加一个移动标识
    // dragover 在目标元素经过 必须要组织默认事件 否则不能触发drop
    // dragleave 离开元素的时候 需要增加一个禁用的标识
    // drop 松手的时候 根据拖拽的组件 添加一个组件
    containerRef.value.addEventListener('dragenter',dragenter)
    containerRef.value.addEventListener('dragover',dragover)
    containerRef.value.addEventListener('dragleave',dragleave)
    containerRef.value.addEventListener('drop',drop)
    currentComponent = component;
    events.emit('start'); // 拖拽前
  }
  // 拖拽结束 去掉事件 + 清空当前组件
  const dragend = (e)=>{
   
    
    
    containerRef.value.removeEventListener('dragenter',dragenter)
    containerRef.value.removeEventListener('dragover',dragover)
    containerRef.value.removeEventListener('dragleave',dragleave)
    containerRef.value.removeEventListener('drop',drop)
    currentComponent = null;
    events.emit('end'); // 拖拽后
  }
  const dragenter = (e)=>{
   
    
    
    e.dataTransfer.dropEffect = 'move'; // 移动标识
  }
  const dragover = (e)=>{
   
    
    
    e.preventDefault(); // 阻止默认行为
  }
  const dragleave = (e)=>{
   
    
    
    e.dataTransfer.dropEffect = 'none'; // 离开 设置禁用
  }
  const drop = (e)=>{
   
    
    
    let blocks = data.value.blocks; // 内部渲染的组件
    // 更新data的数据 触发更新app传递进来的v-model数据
    data.value = {
   
    
    
      ...data.value, 
      blocks:[
        ...blocks,
        // 拿到拖拽入容器的组件 位置 与 key值
        {
   
    
     top:e.offsetY, left:e.offsetX ,zIndex:1,
          key:currentComponent.key,
          alignCenter:true // 松手时居中 需要在editor-blick.jsx之中配置
        }
      ]
    }
    currentComponent = null
  }
  return {
   
    
    
    dragstart,
    dragend
  }
}

src / package / events.js

import mitt from "mitt";
export const events = mitt(); // 导出一个发布订阅的对象 (类型vue2的bus)

src / package / useCommand.js

import deepcopy from "deepcopy";
import {
   
    
     onUnmounted } from "vue";
import {
   
    
     events } from "./events";
export function useCommand(data) {
   
    
    
  const state = {
   
    
    
    // 前进和后退都需要指针
    current: -1, // 前进后退的索引
    queue: [], // 存放所有的操作指令
    commands: {
   
    
    }, // 制作命令和执行功能一个映射表 undo: ()=>{} ; redo: ()=>{}
    commandArray: [], // 存放所有的命令
    destoryArray: [], // 销毁的命令
  };

  const regeister = (command) => {
   
    
    
    state.commandArray.push(command);
    state.commands[command.name] = () => {
   
    
    
      // 命令名字 映射 执行函数
      const {
   
    
     redo, undo } = command.execute();
      redo();
      if 

猜你喜欢

转载自blog.csdn.net/weixin_43845137/article/details/131322385