如何阻止 [contenteditable] 在 Angular 9 类型上模糊

问题描述

所以我正在尝试用 angular 制作一个编辑器,但是当我输入 contenteditable 模糊时。这是预期的吗?我尝试了一些解决方法,但没有任何真正奏效。

我正在做的是捕获文档中的所有 keydown 事件以进行处理,并手动更新 contenteditable。但是,正如您可以想象的那样,这有其自身的一系列问题。我真的不想像这样手动更新它,因为如果我这样做,那么首先使用 contenteditable 就没有任何意义。

这是我的代码:

// editor.component.html
<div class="editor">
    <p
        (click)="setFocusOnLine($event)"
        id="paragraph_{{ index }}"
        *ngFor="let line of writtenText; let index = index"
        >{{ line }}</p
    >
</div>
// editor.component.ts
export class EditorComponent implements OnInit {
    public readonly keyCodes: { [key: string]: number } = constants.KEY_CODES;

    public showContextMenu = false;
    public writtenText: string[] = ["Start typing here"];
    public index = 0;

    private clickCounter = 0;
    private elementToFocus: HTMLElement;

    constructor() {}

    ngOnInit(): void {
        this.forceFocus();
    }

    private writeOnLine(key: string): void {
        let capturedString: string = this.writtenText[this.index]
            ? this.writtenText[this.index]
            : "\n";

        capturedString = `${capturedString}${key}`;

        this.writtenText[this.index] = capturedString;
    }

    private createNewLine(): void {
        this.index = this.index + 1;
        this.writtenText.splice(this.index,0);
    }

    public setFocusOnLine(event,isOnClick: boolean = true): void {
        const elementId: string = event.target.id;
        const substring: number = Number(
            elementId.substring(elementId.indexOf("_") + 1)
        );

        this.index = substring ? substring : this.writtenText.length - 1;

        this.removeContentEditable();

        if (isOnClick) {
            this.elementToFocus = event.target;
        } else {
            setTimeout(() => {
                this.elementToFocus = document.getElementById(elementId);
                console.log("this.elementToFocus:",this.elementToFocus);
            });
        }

        setTimeout(() => {
            this.elementToFocus.setAttribute("contenteditable","true");
            this.elementToFocus.focus();
        });

        this.getSelection();
    }

    public getSelection(): void {
        this.clickCounter = this.clickCounter + 1;

        if (this.clickCounter % 2 !== 0) {
            return;
        }

        this.clickCounter = 0;
        const selection: any = window.getSelection();
        const selectionText: string = selection.toString();

        if (selectionText !== constants.IS_EMPTY_STRING) {
            this.showContextMenu = true;
        }
    }

    public removeContentEditable(): void {
        const elementToClearAttribute: NodeListOf<Element> = document.querySelectorAll(
            "[contenteditable=true]"
        );
        const elementIndex: number =
            elementToClearAttribute.length > 0
                ? elementToClearAttribute.length - 1
                : 0;

        if (elementIndex > 0) {
            setTimeout(() => {
                document
                    .getElementById(elementToClearAttribute[elementIndex].id)
                    .removeAttribute("contenteditable");
            });
        }
    }

    @HostListener("window:keydown",["$event"])
    public captureInput(event): void {
        console.log("event.which:",event.which);
        const isControlCharacter: boolean =
            event.which <= this.keyCodes.ControlCharacterMax;
        const isDelete: boolean = event.which === this.keyCodes.Delete;
        const isFunctionKey: boolean =
            event.which >= this.keyCodes.FunctionKeyStart &&
            event.which <= this.keyCodes.FunctionKeyEnd;
        const isArrowKey: boolean =
            event.which >= this.keyCodes.ArrowKeyLeft &&
            event.which <= this.keyCodes.ArrowKeyDown;
        const isNumLock: boolean = event.which === this.keyCodes.NumLock;
        const isContextMenu: boolean =
            event.which === this.keyCodes.ContextMenu;
        const isPageUp: boolean = event.which === this.keyCodes.PageUp;
        const isPageDown: boolean = event.which === this.keyCodes.PageDown;
        const isHome: boolean = event.which === this.keyCodes.Home;
        const isEnd: boolean = event.which === this.keyCodes.End;
        const isInsert: boolean = event.which === this.keyCodes.Insert;
        const isEnter: boolean = event.which === this.keyCodes.Enter;

        const shouldIgnore: boolean =
            (isControlCharacter && isEnter) ||
            isDelete ||
            isFunctionKey ||
            isNumLock ||
            isContextMenu ||
            isPageUp ||
            isPageDown ||
            isHome ||
            isEnd ||
            isInsert;

        const shouldPreventDefault: boolean = isArrowKey || isEnter;


        if (!shouldPreventDefault && !shouldIgnore) {
            this.writeOnLine(event.key);
            return;
        }


        if (event.which === this.keyCodes.Enter) {
            this.setEnterFunction();
        }

        return;
    }

    private setEnterFunction(): void {
        this.createNewLine();
        this.forceFocus();
        this.writeOnLine("");
    }

    private forceFocus(): void {
        const simulatedEventObject = {
            target: { id: `paragraph_${this.index}` },};
        this.setFocusOnLine(simulatedEventObject,false);
    }
// editor.component.scss
@import "../../assets/variables/colors";

.editor {
    p {
        padding: 0.75em 0.2em;
        margin: 0;
        cursor: text;

        &.has-focus {
            background-color: rebeccapurple;
        }
    }
    [contenteditable] {
        &:after {
            content: "|";
            color: powderblue;
            animation-name: blink;
            animation-duration: 0.9s;
            animation-iteration-count: infinite;
            animation-timing-function: ease;
        }

        &:focus,&:active,&:focus-within,&:focus-visible {
            outline: none;
            background-color: $focus-background-color;
        }
    }
}

@keyframes blink {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

我发现问题在于将写入的内容插入到 writeText 变量中,但我不确定如何更改捕获它的方式

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)