Html 文本区域中的ReactJS句柄选项卡字符
如何处理ReactJS中按下tab键的事件,以便能够缩进文本区域中的文本Html 文本区域中的ReactJS句柄选项卡字符,html,reactjs,Html,Reactjs,如何处理ReactJS中按下tab键的事件,以便能够缩进文本区域中的文本 当按下文本区域上的tab时,onChange事件不会被触发,因此我想可能有一个更高级别的处理程序可以用来检测此事件。您可以尝试onKeyDown并获取tab的键代码 add: function(event){ console.log(event.keyCode); //press TAB and get the keyCode }, render: function(){ return( &
当按下文本区域上的tab时,onChange事件不会被触发,因此我想可能有一个更高级别的处理程序可以用来检测此事件。您可以尝试onKeyDown并获取tab的键代码
add: function(event){
console.log(event.keyCode); //press TAB and get the keyCode
},
render: function(){
return(
<div>
<input type="text" id="one" onKeyDown={this.add} />
</div>
);
}
添加:函数(事件){
console.log(event.keyCode);//按TAB键并获取keyCode
},
render:function(){
返回(
);
}
您可以尝试使用KeyDown并获取选项卡的keycode
add: function(event){
console.log(event.keyCode); //press TAB and get the keyCode
},
render: function(){
return(
<div>
<input type="text" id="one" onKeyDown={this.add} />
</div>
);
}
添加:函数(事件){
console.log(event.keyCode);//按TAB键并获取keyCode
},
render:function(){
返回(
);
}
onKeyDown={(e:React.KeyboardEvent)=>{
如果(e.key==='Tab'&&!e.shiftKey){
e、 预防默认值();
const value=this.textareaRef.current!.value;
const selectionStart=this.textrarearef.current!.selectionStart;
const selectionEnd=this.textareaRef.current!.selectionEnd;
此.textareaRef.current!.value=
value.substring(0,selectionStart)+''+value.substring(selectionEnd);
此.textareaRef.current!.selectionStart=selectionEnd+2-(selectionEnd-selectionStart);
此.text区域引用.current!.selectionEnd=selectionEnd+2-(selectionEnd-selectionStart);
}
如果(e.key==='Tab'&&e.shiftKey){
e、 预防默认值();
const value=this.textareaRef.current!.value;
const selectionStart=this.textrarearef.current!.selectionStart;
const selectionEnd=this.textareaRef.current!.selectionEnd;
const beforeStart=值
.子字符串(0,selectionStart)
.拆分(“”)
.reverse()
.加入(“”);
常量indexOfTab=beforeStart.indexOf(“”);
const indexOfNewline=beforeStart.indexOf('\n');
if(indexOfTab!=-1&&indexOfTab
onKeyDown={(e:React.KeyboardEvent)=>{
如果(e.key==='Tab'&&!e.shiftKey){
e、 预防默认值();
const value=this.textareaRef.current!.value;
const selectionStart=this.textrarearef.current!.selectionStart;
const selectionEnd=this.textareaRef.current!.selectionEnd;
此.textareaRef.current!.value=
value.substring(0,selectionStart)+''+value.substring(selectionEnd);
此.textareaRef.current!.selectionStart=selectionEnd+2-(selectionEnd-selectionStart);
此.text区域引用.current!.selectionEnd=selectionEnd+2-(selectionEnd-selectionStart);
}
如果(e.key==='Tab'&&e.shiftKey){
e、 预防默认值();
const value=this.textareaRef.current!.value;
const selectionStart=this.textrarearef.current!.selectionStart;
const selectionEnd=this.textareaRef.current!.selectionEnd;
const beforeStart=值
.子字符串(0,selectionStart)
.拆分(“”)
.reverse()
.加入(“”);
常量indexOfTab=beforeStart.indexOf(“”);
const indexOfNewline=beforeStart.indexOf('\n');
if(indexOfTab!=-1&&indexOfTab
以防有人想在TypeScript中稍微更新(我认为是增强版)vipe解决方案:
实现使用示例:
<EnhancedTextArea
ref={txtCodeInput} {/* reference used whenever required as seen below */}
className='code-input'
tabSize={2}
onTextChange={handleCodeChange} {/* Function accepting callback of type (string) -> void, called every time code is changed */}
/>
void,每次更改代码时调用*/}
/>
获取文本:
const txtCodeInput = useRef<EnhancedTextAreaRefs>(null);
...
const codeContent = txtCodeInput.current?.getCodeContent();
const txtCodeInput=useRef(null);
...
const codeContent=txtCodeInput.current?.getCodeContent();
EnhancedTextArea.tsx:
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
type EnhancedTextAreaProps = {
onTextChange?: (text: string) => void,
className?: string,
spellCheck?: boolean,
tabSize?: number,
};
export type EnhancedTextAreaRefs = {
getCodeContent: () => string;
}
const EnhancedTextArea = forwardRef<EnhancedTextAreaRefs, EnhancedTextAreaProps>(({
onTextChange = undefined,
className = undefined,
tabSize = 4,
spellCheck = false,
}: EnhancedTextAreaProps, ref) => {
const [text, setText] = useState('');
const [stateSelectionStart, setStateSelectionStart] = useState(0);
const [stateSelectionEnd, setStateSelectionEnd] = useState(0);
const txtInput = useRef<HTMLTextAreaElement>(null);
useImperativeHandle(ref, () => ({
getCodeContent: () => text,
}));
useEffect(() => {
const textArea = txtInput.current;
if (!textArea) {
return;
}
if (stateSelectionStart >= 0) {
textArea.selectionStart = stateSelectionStart;
}
if (stateSelectionEnd >= 0) {
textArea.selectionEnd = stateSelectionEnd;
}
}, [text, stateSelectionStart, stateSelectionEnd]);
async function handleCodeChange(e: React.ChangeEvent<HTMLTextAreaElement>): Promise<void> {
const text = e.target.value;
setText(text);
if (onTextChange) {
onTextChange(text);
}
}
async function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>): Promise<void> {
const textArea = e.target as HTMLTextAreaElement;
const tabString = ' '.repeat(tabSize);
const value = textArea.value;
const selectionStart = textArea.selectionStart;
const selectionEnd = textArea.selectionEnd;
if (e.key === 'Tab' && !e.shiftKey) {
e.preventDefault();
if (selectionStart !== selectionEnd) {
const slices1 = getNewLineSlices(value, selectionStart, selectionEnd);
const newValue1 = addTabs(value, slices1, tabString);
setText(newValue1);
setStateSelectionStart(selectionStart + tabSize);
setStateSelectionEnd(selectionEnd + (newValue1.length - value.length));
} else {
const newValue2 = value.substring(0, selectionStart) + tabString + value.substring(selectionEnd);
setText(newValue2);
setStateSelectionStart(selectionEnd + tabSize - (selectionEnd - selectionStart));
setStateSelectionEnd(selectionEnd + tabSize - (selectionEnd - selectionStart));
}
} else if (e.key === 'Tab' && e.shiftKey) {
e.preventDefault();
const slices2 = getNewLineSlices(value, selectionStart, selectionEnd);
const newValue3 = removeTabs(value, slices2, tabSize);
const diff = value.length - newValue3.length;
setText(newValue3);
setStateSelectionStart(Math.max(0, selectionStart - (diff ? tabSize : 0)));
setStateSelectionEnd(Math.max(0, selectionEnd - diff));
} else {
setStateSelectionStart(-1);
setStateSelectionEnd(-1);
}
}
function getNewLineSlices(value: string, selectionStart: number, selectionEnd: number): Array<string | null> {
const newLineLocations = getAllIndices(value, '\n');
const left = findRange(newLineLocations, selectionStart);
const split = value.split('\n');
const arr = [];
let count = 0;
for (let i = 0; i < split.length; i++) {
const line = split[i];
if (count > left && count <= selectionEnd) {
arr.push(line);
} else {
arr.push(null);
}
count += line.length + 1;
}
return arr;
}
function addTabs(value: string, arr: Array<string | null>, joiner: string): string {
const split = value.split('\n');
let ret = '';
for (let i = 0; i < split.length; i++) {
const val = split[i];
const newLineVal = arr[i];
if (newLineVal === val) {
ret += joiner;
}
ret += val;
if (i !== split.length - 1) {
ret += '\n';
}
}
return ret;
}
function removeTabs(value: string, arr: Array<string | null>, tabSize: number): string {
const split = value.split('\n');
let ret = '';
for (let i = 0; i < split.length; i++) {
const val = split[i];
const newLineVal = arr[i];
if (!val.startsWith(' ') || newLineVal !== val) {
ret += val;
if (i !== split.length - 1) {
ret += '\n';
}
continue;
}
let count = 1;
while (val[count] === ' ' && count < tabSize) {
count++;
}
ret += val.substring(count);
if (i !== split.length - 1) {
ret += '\n';
}
}
return ret;
}
function getAllIndices(arr: string, val: string): Array<number> {
const indices = [];
let i = -1;
while ((i = arr.indexOf(val, i + 1)) !== -1){
indices.push(i);
}
return indices;
}
function findRange(arr: Array<number>, min: number): number {
for (let i = 0; i < arr.length; i++) {
if (arr[i] >= min) {
return i === 0 ? -1 : arr[i - 1];
}
}
return arr[arr.length - 1];
}
return(
<textarea
ref={txtInput}
value={text}
onKeyDown={handleKeyDown}
onChange={handleCodeChange}
className={className}
spellCheck={spellCheck} />
);
});
EnhancedTextArea.displayName = 'EnhancedTextArea';
export default EnhancedTextArea;
从'react'导入{forwardRef,useffect,useImportiveHandle,useRef,useState};
类型EnhancedTextAreaProps={
ContextChange?:(文本:字符串)=>void,
类名?:字符串,
拼写检查?:布尔,
tabSize?:数字,
};
导出类型EnhancedTextAreaRefs={
getCodeContent:()=>字符串;
}
常量EnhancedTextArea=forwardRef(({
onTextChange=未定义,
className=未定义,
tabSize=4,
拼写检查=false,
}:EnhancedTextAreaProps,ref)=>{
const[text,setText]=useState(“”);
常量[stateSelectionStart,setStateSelectionStart]=useState(0);
常量[stateSelectionEnd,setStateSelectionEnd]=useState(0);
const txtInput=useRef(null);
使用命令式句柄(参考,()=>({
getCodeContent:()=>文本,
}));
useffect(()=>{
const textArea=txtInput.current;
如果(!textArea){
返回;
}
如果(状态选择开始>=0){
textArea.selectionStart=状态selectionStart;
}
如果(状态选择结束>=0){
textArea.selectionEnd=状态selectionEnd;
}
},[文本,状态选择开始,状态选择结束];
异步函数handleCodeChange(e:React.ChangeEvent):承诺{
常量文本=e.target.value;
setText(文本);
if(onTextChange){
onTextChange(文本);
}
}
异步函数handleKeyDown(e:React.KeyboardEvent):承诺{
const textArea=e.target作为HtmlTextArea元素;
const tabString=''。重复(tabSize);
常量值=textArea.value;
const selectionStart=textArea.selectionStart;
const selectionEnd=textArea.selectionEnd;
如果(e.key