深圳 网站 设计,学设计师学费要多少钱,木马设计公司,wordpress手机端编辑有类似于这样的表格#xff0c;用的table标签。原本要在单元格的文本框里面输入内容#xff0c;需要用鼠标一个一个去点以获取焦点#xff0c;现在需要不用鼠标选中#xff0c;直接用键盘的上下左右来移动当前正在输入的单元格文本框。 const currentCell React.u…
有类似于这样的表格用的table标签。原本要在单元格的文本框里面输入内容需要用鼠标一个一个去点以获取焦点现在需要不用鼠标选中直接用键盘的上下左右来移动当前正在输入的单元格文本框。 const currentCell React.useRefHTMLElement | null() // 储存当前选中的单元格const handleArrowKeys (event) { // 当按下键盘方向键做的事情if (!currentCell || !currentCell.current) return;const cellIndex currentCell?.current?.cellIndex;let newCell;switch (event.key) {case ArrowUp:newCell currentCell.current?.parentElement?.previousElementSibling?.cells[cellIndex];break;case ArrowDown:newCell currentCell.current?.parentElement?.nextElementSibling?.cells[cellIndex];break;case ArrowLeft:newCell currentCell?.current?.previousElementSibling;break;case ArrowRight:newCell currentCell?.current?.nextElementSibling;break;default:break;}if (newCell) {if(currentCell?.current){currentCell.current.style.border solid 2px black// currentCell.current.style.boxShadow none}currentCell.current newCellnewCell.style.border 3px solid #1890ff// newCell.style.borderColor #1890ff// newCell.style.boxShadow 0 0 10px 5px #1890ff}}useEffect((){// 鼠标点击事件因为第一次选中单元格肯定是要点击document.addEventListener(click, (e: MouseEvent) {const target e.target as HTMLElement// console.log(target.tagName, target)// 这里要判断被点击的对象是不是你需要监听的表格的单元格const isActive (target.tagName TD || target.tagName TH) ...if (isActive) {if(currentCell?.current){ // 将原本被选中的单元格样式改为正常样式currentCell.current.style.border solid 2px black}// 新的单元格存起来并高亮显示currentCell.current targettarget.style.border 3px solid #1890ff} else {// 如果被点击的不是需要监听的地方则整个表格“失去焦点”if(currentCell?.current){currentCell.current.style.border solid 2px blackcurrentCell.current null}}})document.addEventListener(keydown, function(e) {// console.log(e, e)if (e.ctrlKey || e.altKey){// 这是按ctrl alt的情况很多快捷键方式不知道怎么模仿。} else if (e.key ArrowUp || e.key ArrowDown || e.key ArrowLeft || e.key ArrowRight) {handleArrowKeys(e);} else if (e.key Insert || // 按下的是插入键e.key Home || // 按下的是Home键e.key End // 按下的是End键// 其他需要处理的按键) {return} else{if(!currentCell || !currentCell.current) returnlet childNodes currentCell.current.childNodeslet inputIndex: any null, textAreaIndex: any nullchildNodes.forEach((node, index) {if(node.tagName INPUT) inputIndex indexif(node.tagName TEXTAREA) textAreaIndex index})if(inputIndex ! null){if (e.key Backspace || // 按下的是退格键e.key Delete// 其他需要处理的按键) {childNodes[inputIndex].value } else if(e.key.length 1) {childNodes[inputIndex].value childNodes[inputIndex].value e.key}}else if(textAreaIndex ! null){if (e.key Backspace || // 按下的是退格键e.key Delete// 其他需要处理的按键) {childNodes[textAreaIndex].value } else if(e.key.length 1) {childNodes[textAreaIndex].value childNodes[inputIndex].value e.key}}}});},[])这种方式实现的功能就是点击单元格注意不能点击到格里的文本框因为我觉得文本框都是单击它就获取了焦点键盘方向键也是用来控制光标位置的这里没有过多的去纠结去探究也许可以做到然后键盘的上下左右就能控制当前选中的单元格输入就能改变单元格的文本框的值。其实这样我觉得就和excel单击单元格选中输入就是覆盖整个内容方向键控制选中单元格双击单元格才是继续编辑单元格内容方向键控制光标差不多不过我这个变成了单击单元格是选中然后输入覆盖单击文本框是继续输入。
但是这样是有弊端的代码中也能看出来对于ctrlalt这些快捷键的功能我没有模仿出来可能跟个人能力有关而且就算有办法我觉得可能也太复杂了不想折腾还有就是很重要的一点他没办法输入中文因为我是监听键盘按下的事件然后获得它的key那用户想输入中文我也只能获取到一个一个的英文字母本人也想过偷懒因为这个系统这里的表格大多数是不用输入中文少数有中文后面闲着没事就问了chat gpt得到一些灵感。 const currentCell React.useRefHTMLElement | null() // 储存当前选中的单元格const handleArrowKeys (event) { // 当按下键盘方向键做的事情if (!currentCell || !currentCell.current) return;const cellIndex currentCell?.current?.cellIndex;let newCell;switch (event.key) {case ArrowUp:newCell currentCell.current?.parentElement?.previousElementSibling?.cells[cellIndex];break;case ArrowDown:newCell currentCell.current?.parentElement?.nextElementSibling?.cells[cellIndex];break;case ArrowLeft:newCell currentCell?.current?.previousElementSibling;break;case ArrowRight:newCell currentCell?.current?.nextElementSibling;break;default:break;}if (newCell) {if(currentCell?.current){currentCell.current.style.border solid 2px blacklet input document.getElementById(dynamicInput);if (input) {input.remove();}}currentCell.current newCellnewCell.style.border 3px solid #1890fflet input document.createElement(input);input.type text;input.style.position absolute;input.style.left -9999px;input.id dynamicInput;newCell.appendChild(input);input.addEventListener(input, handleInput);input.focus();}}const handleInput (e) {if(!currentCell || !currentCell.current) returnlet childNodes currentCell.current.childNodeslet inputIndex: any null, textAreaIndex: any nullchildNodes.forEach((node, index) {console.log(node, node)if(node.tagName INPUT !node.id) inputIndex indexif(node.tagName TEXTAREA) textAreaIndex index})console.log(e, e)if(inputIndex ! null){childNodes[inputIndex].value e.target.value}else if(textAreaIndex ! null){childNodes[textAreaIndex].value e.target.value}}useEffect((){// 鼠标点击事件因为第一次选中单元格肯定是要点击document.addEventListener(click, (e: MouseEvent) {const target e.target as HTMLElement// console.log(target.tagName, target)// 这里要判断被点击的对象是不是你需要监听的表格的单元格const isActive (target.tagName TD || target.tagName TH) ...if (isActive) {if(currentCell?.current){ // 将原本被选中的单元格样式改为正常样式currentCell.current.style.border solid 2px blacklet input document.getElementById(dynamicInput);if (input) {input.remove();}}// 新的单元格存起来并高亮显示currentCell.current targettarget.style.border 3px solid #1890fflet input document.createElement(input);input.type text;input.id dynamicInput;input.style.position absolute;input.style.left -9999px;target.appendChild(input);input.addEventListener(input, handleInput);input.focus();} else {// 如果被点击的不是需要监听的地方则整个表格“失去焦点”if(currentCell?.current){currentCell.current.style.border solid 2px blackcurrentCell.current nulllet input document.getElementById(dynamicInput);if (input) {input.remove();}}}})document.addEventListener(keydown, function(e) {// console.log(e, e)if (e.key ArrowUp || e.key ArrowDown || e.key ArrowLeft || e.key ArrowRight) {handleArrowKeys(e);}});},[])
后面这种方法就改成了给当前选中的单元格插入一个用户看不到的自动获取焦点的input然后监听这个文本框的input事件并实时将这个文本框的内容更新到对应的文本框。才刚实现这个没有经过大量操作的测试不知道会不会有什么bug目前没有什么大问题。