国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

web架構(gòu)師編輯器內(nèi)容-快捷鍵操作的實現(xiàn)

這篇具有很好參考價值的文章主要介紹了web架構(gòu)師編輯器內(nèi)容-快捷鍵操作的實現(xiàn)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

快捷鍵操作的需求

元素選擇 前提都是在元素被選中的情況下

  • 拷貝圖層 - ?C / Ctrl+C : 新建當前選擇的元素的一個數(shù)據(jù)結(jié)構(gòu)
  • 粘貼圖層 - ?V / Ctrl+V : 將新建的元素添加到 components 數(shù)組中
  • 刪除圖層 - Backspace / Delete : 在 components 數(shù)組中刪除選擇的元素
  • 取消選中 - 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)
  })
}

但是現(xiàn)在我們的需求復雜了很多,因為我們有很多的組合鍵,所以我們需要好用的第三方庫來完成對應的工作:
項目地址: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

對于快捷鍵的操作,是獨立于整個應用,為了更好的交互,而單獨添加的,看起來相對獨立的功能,所以可以把整個模塊稱之為系統(tǒng)的插件。
創(chuàng)建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函數(shù)中進行調(diào)用,測試效果
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 {
  // 供中間編輯器渲染的數(shù)組
  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操作,就會發(fā)現(xiàn)復制出來的元素也粘貼出來的元素是一摸一樣的,最終就會導致在移動復制的元素的時候,被復制的元素也會被同樣移動。所以我們要對pasteCopiedComponent進行稍微的改造,拷貝一下數(shù)據(jù):

// 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})
})
}

實現(xiàn)之后發(fā)現(xiàn)會有一個問題:如果滾動條在下面的話,滾動條會跟著一起移動。
滾動條跟隨元素一起移動,這個行為是瀏覽器默認的一個行為,所以我們可以使用e.preventDefault來阻止瀏覽器默認行為,在useKotKey回調(diào)函數(shù)里面,第一個參數(shù)就是事件對象,我們可以在這里進行添加,其他事件也是如此。但是如果要是都是寫同樣的邏輯,是比較繁瑣的,有什么辦法能夠完成無數(shù)個這樣的邏輯呢?我們可以給回調(diào)函數(shù)在來一套包裝,返回一個新的function,這就是高階函數(shù),高階函數(shù)在處理多次邏輯重復的回調(diào)中比較適用:文章來源地址http://www.zghlxwxcb.cn/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架構(gòu)師編輯器內(nèi)容-快捷鍵操作的實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包