web架构师编辑器内容-快捷键操作的实现

这篇具有很好参考价值的文章主要介绍了web架构师编辑器内容-快捷键操作的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

快捷键操作的需求

元素选择 前提都是在元素被选中的情况下

  • 拷贝图层 - ⌘C / Ctrl+C : 新建当前选择的元素的一个数据结构
  • 粘贴图层 - ⌘V / Ctrl+V : 将新建的元素添加到 components 数组中
  • 删除图层 - Backspace / Delete : 在 components 数组中删除选择的元素
  • 取消选中 - ESC : currentElement 设置为空

元素移动

  • 上下左右移动一像素 - ↑ ↓ → ← : 更新选中元素 props 的 top/left 值
  • 上下左右移动十像素 - Shift + ↑ ↓ → ←:更新选中元素 props 的 top/left 值

撤销/重做

  • 撤销 - ⌘Z / Ctrl+Z
  • 重做 - ⌘⇧Z / Ctrl+Shift+Z

好用的按键响应库 - HotKeys.js

之前我们在InlineEdit.vue组件中,使用到了useKeyPress帮助了我们对esc和enter进行了绑定:

const useKeyPress = (key: string, cb: () => any) => {
  const trigger = (event: KeyboardEvent) => {
    if (event.key === key) {
      cb()
    }
  }
  onMounted(() => {
    document.addEventListener('keydown', trigger)
  })
  onUnmounted(() => {
    document.removeEventListener('keydown', trigger)
  })
}

但是现在我们的需求复杂了很多,因为我们有很多的组合键,所以我们需要好用的第三方库来完成对应的工作:
项目地址:https://github.com/jaywcjlove/hotkeys
演示地址:https://wangchujiang.com/hotkeys/

完成对应的编码
// useHotKey.ts
import hotkeys, { KeyHandler } from 'hotkeys-js'
import { onMounted, onUnmounted } from 'vue'

const useHotKey = (keys: string, callback: KeyHandler) => {
  onMounted(() => {
    hotkeys(keys, callback)
  })
  onUnmounted(() => {
    hotkeys.unbind(keys, callback)
  })
}

export default useHotKey

对于快捷键的操作,是独立于整个应用,为了更好的交互,而单独添加的,看起来相对独立的功能,所以可以把整个模块称之为系统的插件。
创建plugins文件夹:

// plugins/hotKey.ts
import useHotKey from '../hooks/useHotKey'
export default function initHotKeys() {
  useHotKey('ctrl+c, command+c', () => {
    alert('ctrl+c, command+c')
  })
  useHotKey('ctrl+v, command+v', () => {
    alert('ctrl+v, command+v')
  })
}

// 在Editor.vue中的setup函数中进行调用,测试效果
setup(){
	initHotKeys()
}

完成ctrl+c快捷键的操作:

// plugins/hotKey.ts
import { useStore } from "vuex";
import { computed } from "vue";
import { GlobalDataProps } from "../store";

useHotKey("ctrl+c, command+c", () => {
  const store = useStore<GlobalDataProps>();
  const currentId = computed(() => store.state.editor.currentElement);
  store.commit("copyComponent", currentId.value);
}

// store/editor.ts mutations中的
copyComponent(state, id) {
  // 这里是在geeters定义了一个getElement,引入store,就可以在mutations中拿到getters中的属性了
  const currentComponent = store.getters.getElement(id)
  if (currentComponent) {
    state.copiedComponent = currentComponent;
    message.success('已拷贝当前图层', 1);
  }
},

// 在editoreProps中添加copiedComponent
interface EditorProps {
  // 供中间编辑器渲染的数组
  components: ComponentData[];
  // 当前编辑的是哪个元素,uuid
  currentElement: string;
  // 当然最后保存的时候还有有一些项目信息,这里并没有写出,等做到的时候再补充
  page: PageData;
  // 当前被复制的组件
  copiedComponent?: ComponentData;
}

完成ctrl+v快捷键的操作:

// plugins/hotKey.ts
useHotKey('ctrl+v, command+v', () => {
  store.commit('pasteCopiedComponent')
})

// store/editors.ts中mutations中的
pasteCopiedComponent(){
  if (state.copiedComponent) {
    state.components.push(state.copiedComponent)
    message.success('已黏贴当前图层', 1);
  }
 }

这里如果直接进行push操作,就会发现复制出来的元素也粘贴出来的元素是一摸一样的,最终就会导致在移动复制的元素的时候,被复制的元素也会被同样移动。所以我们要对pasteCopiedComponent进行稍微的改造,拷贝一下数据:

// store/editors.ts中mutations中的
pasteCopiedComponent: setDirtyWrapper((state) => {
  if (state.copiedComponent) {
   // 使用lodash中的cloneDeep进行拷贝,可以丧失响应式
    const clone = cloneDeep(state.copiedComponent);
    clone.id = uuidv4();
    clone.layerName = clone.layerName + '副本';
    state.components.push(clone);
    message.success('已黏贴当前图层', 1);
  }
}),

// 删除图层:
deleteComponent: setDirtyWrapper((state, id) => {
  const currentComponent = state.components.find(
    (component) => component.id === id
  );
  if (currentComponent) {
    state.components = state.components.filter(
      (component) => component.id !== id
    );
    message.success("删除当前图层成功", 1);
  }
}),

添加移动元素的快捷键:

// store/editors.ts
moveComponent(
	state,
	data: { direction: MoveDirection; amount: number; id: string }
) {
	const currentComponent = state.components.find(
		(component) => component.id === data.id
	);
	if (currentComponent) {
	    // 获取旧的值
		const oldTop = parseInt(currentComponent.props.top || "0");
		const oldLeft = parseInt(currentComponent.props.left || "0");
		const { direction, amount } = data;
		switch (direction) {
			case "Up": {
				const newValue = oldTop - amount + "px";
				store.commit("updateComponent", {
					key: "top",
					value: newValue,
					id: data.id,
				});
				break;
			}
			case "Down": {
				const newValue = oldTop + amount + "px";
				store.commit("updateComponent", {
					key: "top",
					value: newValue,
					id: data.id,
				});
				break;
			}
			case "Left": {
				const newValue = oldLeft - amount + "px";
				store.commit("updateComponent", {
					key: "left",
					value: newValue,
					id: data.id,
				});
				break;
			}
			case "Right": {
				const newValue = oldLeft + amount + "px";
				store.commit("updateComponent", {
					key: "left",
					value: newValue,
					id: data.id,
				});
				break;
			}
			default:
				break;
		}
	}
},

// hotKey.ts
function initHotKeys(){
  ...
  useHotKey('down', () => {
    store.commit('moveComponent', { direction: 'Down', amount: 1, id: currentId.value})
})
  useHotKey('left', () => {
    store.commit('moveComponent', { direction: 'Left', amount: 1, id: currentId.value})
})
  useHotKey('right', () => {
    store.commit('moveComponent', { direction: 'Right', amount: 1, id: currentId.value})
})
  useHotKey('shift+up', () => {
    store.commit('moveComponent', { direction: 'Up', amount: 10, id: currentId.value})
})
  useHotKey('shift+down', () => {
    store.commit('moveComponent', { direction: 'Down', amount: 10, id: currentId.value})
})
  useHotKey('shift+left', () => {
    store.commit('moveComponent', { direction: 'Left', amount: 10, id: currentId.value})
})
  useHotKey('shift+right', () => {
    store.commit('moveComponent', { direction: 'Right', amount: 10, id: currentId.value})
})
}

实现之后发现会有一个问题:如果滚动条在下面的话,滚动条会跟着一起移动。
滚动条跟随元素一起移动,这个行为是浏览器默认的一个行为,所以我们可以使用e.preventDefault来阻止浏览器默认行为,在useKotKey回调函数里面,第一个参数就是事件对象,我们可以在这里进行添加,其他事件也是如此。但是如果要是都是写同样的逻辑,是比较繁琐的,有什么办法能够完成无数个这样的逻辑呢?我们可以给回调函数在来一套包装,返回一个新的function,这就是高阶函数,高阶函数在处理多次逻辑重复的回调中比较适用:文章来源地址https://www.toymoban.com/news/detail-817219.html

const wrap = (callback: KeyHandler) => {
  const wrapperFn = (e: KeyboardEvent, event: HotkeysEvent) => {
    e.preventDefault()
    callback(e, event)
  }
  return wrapperFn
}

useHotKey('up', wrap(() => {
  store.commit('moveComponent', { direction: 'Up', amount: 1, id: currentId.value })
}))
useHotKey('down', wrap(() => {
  store.commit('moveComponent', { direction: 'Down', amount: 1, id: currentId.value})
}))

到了这里,关于web架构师编辑器内容-快捷键操作的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • web架构师编辑器内容-数据结构设计上面的难点

    组件的属性应该怎样设计 业务组件分为:样式属性和其他属性,样式属性就是css,其他属性拿文本来说,就是比如test还有点击事件等。 有两种方案: 方案一:把css作为统一的对象传入: 方案二:将所有的属性全部平铺传入 这两种方案,第二种方案相比于第一种比较好,第

    2024年01月22日
    浏览(39)
  • web架构师编辑器内容-编辑器组件图层面板功能开发-锁定隐藏、键盘事件功能的开发

    我们这一部分主要是对最右侧图层面板功能进行剖析,完成对应的功能的开发: 每个图层都对应编辑器上面的元素,有多少个元素就对应多少个图层,主要的功能如下: 锁定功能:点击锁定,在编辑器中没法编辑对应的组件属性,再次点击是取消锁定,恢复到可编辑的模式

    2024年01月18日
    浏览(28)
  • IDEA中/** 内容 */注释的快捷键

    在 IDEA 中,你可以使用快捷键 /** 来快速生成 /** 内容 */ 注释。 要使用此快捷键,请在你想要添加注释的代码行上按 Ctrl + / (Windows 系统)或 Command + / (Mac 系统)。如果你想要撤销注释,可以再次按一次快捷键即可。 注意,你必须在代码行的开头才能使用此快捷键。如果你在代码

    2024年02月15日
    浏览(34)
  • fiddler改网页内容(附常用快捷键)

    1、在fiddler中设置请求后阻断,或者按Alt+F11 2、网站中打开网页,fiddler闪烁,表示已经阻断网页到自己位置 3、在RAW中按Alt+F2,进行编辑 4、按Shift+F11,取消阻断 5、按进行到完成 6、到网页端,按回车看改后的效果 ------------------------------------------------------------------ F12    抓

    2023年04月23日
    浏览(20)
  • mac 系统中vscode 返回上一次文件编辑位置快捷键

    mac 系统中vscode 返回上一次文件编辑位置快捷键 以下内容由chatgpt中文网 动态生成,助力开发找我

    2024年01月17日
    浏览(32)
  • VSCode实用快捷键:复制粘贴内容不改变剪切板等

    VSCode里面有很多快捷键,接下来我讲一些我认为最实用的,可以帮助萌新提高代码编写速度 · 会改变剪切板的复制 ctrl+c 光标 定在那一行想复制的地方, 直接Ctrl+c,然后直接ctrl+v即可 , 不用选中内容 · 不改变剪切板 alt + shift + ↓ 或 ↑ 有时候剪切板复制了内容,不想复制

    2024年02月11日
    浏览(53)
  • Unity功能——编辑器模式下隐藏/显示游戏对象的快捷方法

    声明:本文为个人笔记,用于学习研究使用非商用,内容为个人研究及综合整理所得,若有违规,请联系,违规必改。 unity20XX.X.X VS20XX 在编辑器模式下,想快捷的显示/隐藏一个游戏对象. 实现原理: 对组件进行扩展方法.对MonoBehaviour ,Transform,GameObject 组件进行扩展方法 快捷键为

    2024年02月08日
    浏览(35)
  • FinalShell SSH工具安装教程及编辑窗口修改背景颜色,自定义背景图片,修改字体,修改快捷键(详细图文教程)

    FinalShell 在 Windows 上提供了一个方便、安全、功能完备的远程管理工具。它的中文支持和自定义功能让其适合国内 Linux 系统管理者使用。与 Xshell 等软件相比,FinalShell 更注重功能实用性。 参考其它博主的安装教程,链接为:添加链接描述 下载FinalShell安装包的链接:添加链接

    2024年02月12日
    浏览(52)
  • React 框架下自己写一个braft编辑器,然后将编辑器内容展示在网页端

    1.首先自己写一个编辑器 输入文字; 支持选择表情; 可添加小程序链接;可添加网页链接;并且可以编辑删除;效果如下 2.输入完毕后,点击文本输入框保存,将便携式内容回显, 渲染时,因为是html格式,所以采用dangerouslySetInnerHTML属性来渲染 添加样式,渲染后里面的链接

    2024年02月16日
    浏览(43)
  • AJAX + PHP 编辑器内容自动备份草稿保存到本地 (适用ueditor百度编辑器或其它) 内容变化后自动触发备份txt文件

    百度自带的自动备份功能enableAutoSave存在问题, 比如第一个文章他自动备份了.等发表第二个文章时,结果把第一个文章的内容自动填充进去了.关键你还不知情!出现过多次这种情况了. 一, 百度原版的 ,具体使用方法,看这里个文章 Ueditor百度编辑器内容自动保存到本地防数据丢失

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包