Heim  >  Artikel  >  Web-Frontend  >  Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

不言
不言nach vorne
2018-10-22 17:42:274978Durchsuche

Der Inhalt dieses Artikels befasst sich mit dem Umgang mit dem Cursor der React-Eingabe (Details). Ich hoffe, dass er für Sie hilfreich ist.

Worüber wir heute sprechen werden, sind einige abnormale Verhaltensweisen des React-Eingabecursors und entsprechende Lösungen in Szenarien mit numerischer Formatierung. Die Geschichte beginnt mit einem Problem, das bei Verwendung der NumberField-Komponente zur Eingabe auf Android zu einer abnormalen Cursorposition führte, was dazu führte, dass die kontinuierliche Eingabe nicht die erwarteten Ergebnisse lieferte. Wie sieht die konkrete Leistung aus?

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

Abbildung 1 Unerwartetes Eingabeverhalten unter Android

Wie Sie sehen können, in Every Bei einer Zeitformatierung auf einem Android-Telefon hat der Cursor, der sich immer am Ende befinden sollte, das falsche Format, was zu Problemen bei der kontinuierlichen Eingabe führt. Dieses Problem tritt auf PC Chrome oder iOS nicht auf, daher kann davon ausgegangen werden, dass es sich um ein Kompatibilitätsproblem handelt. Aber wie kam es zu diesem Kompatibilitätsproblem?

Analysieren Sie den Formatierungsprozess, da bei der Eingabe von 18758 der ursprüngliche Wert aus der Zeichenfolgenlänge in „1875 8“ konvertiert werden muss Ab dem obigen Punkt Von 5 Ziffern bis 6 Ziffern: Wenn die Cursorposition bei einer Wertänderung nicht zur letzten Ziffer springt, sieht es so aus, als ob eine falsche Ziffer eingegeben wurde Probleme.

Nach dem Cursor-Änderungsverhalten des Eingabefelds zu urteilen, scheint dies keine abnormale Änderung zu sein, es reagiert einfach nicht auf die Wertänderung und springt zum Ende. Es stellt sich jedoch die Frage, warum es auf iOS und PC Chrome zum Ende springt.

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

Abbildung 2: Der gleiche Code verhält sich unter PC Chrome anders als unter Android.

Also habe ich online gesucht und ein solches Problem im Github von React gefunden: Der Cursor springt zum Ende der kontrollierten Eingabe. Hier gab @sophiebits(spicyj), eine der Hauptbetreuerinnen von React, eine genauere Antwort.

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

Abbildung 3 Sophiebits' Erklärung des Cursorverhaltens, wenn sich der durch React gesteuerte Eingabewert ändert

Es stellt sich heraus Das liegt daran, dass die Änderungen sehr unsicher sind, sodass React keine zuverlässige und universelle Logik verwenden kann, um die Cursorposition an einer geeigneten Position zu speichern. Daher bewegt React den Cursor beim erneuten Rendern im kontrollierten Modus an die letzte Position. Dies erklärt zumindest, warum der Cursor in PC Chrome und iOS ans Ende springt, aber ich habe keine vernünftige Erklärung dafür gefunden, warum Android nicht dasselbe Verhalten zeigt.

Gibt es eine Möglichkeit, die Leistung auf Android mit der von iOS in Einklang zu bringen? Nach einer Weile des Lesens und Ausprobierens habe ich schließlich herausgefunden, dass die Leistung der Eingabe in Android mit der Leistung auf anderen Plattformen übereinstimmen kann, wenn der Prozess des erneuten Renderns und der onChange der Eingabe in zwei Ticks davor und danach platziert werden Das heißt, der Cursor springt beim erneuten Rendern. Am Ende lautet der Code wie folgt.

import React from 'React';
class Demo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: 'xxx',
        };
    }
    
    handleChange(e) {
        const value = e.target.value;
        // 通过 setTimeout 异步
        // 使 re-render 和 onChange 处于两个 tick 中
        setTimeout(() => {
            this.setState({
                value,
            });
        });
    }
    
    render() {
        return (
            <input> { this.handleChange(e); }}  
            />
        );
    }
}

Dadurch ist das Verhalten auf Android und iOS endlich konsistent und die Leistung entspricht eher den Erwartungen unter normalen Eingabebedingungen. Aber Moment, ist das in Ordnung? Aus den Schlussfolgerungen der vorherigen React-Ausgabe können wir ersehen, dass unabhängig von der Änderung zum Ende der Eingabe gesprungen wird.

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

Abbildung 4: Ein weiteres Problem tritt bei der Zwischenbearbeitung auf

Wie aus dem obigen Bild ersichtlich ist, da React den Cursor ändert Unabhängig davon, welche Änderungen vorgenommen werden, entspricht die Leistung am Ende nicht den Erwartungen des Benutzers und es gibt keine Möglichkeit, eine kontinuierliche Eingabe zu erreichen. Diesmal ist das Verhalten beider Enden konsistent, was beides unerwartet ist. .

Aber es gibt Vorteile, nicht normal zu sein. Je nach Plattform ist es nicht erforderlich, etwas zu schreiben, und es kann einheitlich verarbeitet werden. Aus der obigen Diskussion können wir erkennen, dass React die Cursorposition nicht speichert, da es keinen allgemeinen und zuverlässigen Algorithmus gibt, der dieses Verhalten unterstützt. Dies liegt daran, dass sich die Eingabe durch das Hinzufügen von Leerzeichen zur Formatierung, das Filtern einiger Zeichen oder das Auslösen bestimmter Bedingungen und den direkten Wechsel zu anderen Zeichen usw. sowie durch andere unvorhersehbare Änderungen ändern kann. Wenn es jedoch um das einzelne Szenario der digitalen Formatierung geht, wird die Logik zum Speichern der Cursorposition viel einfacher und klarer.

在用户输入的过程中,只存在两种情况,在结尾中追加和在中间修改。在结尾追加的 case 中,例如 18758^ 时,由于一直是在向后追加的状态,我们只要一直保持光标在最后即可(即默认状态 1875 8^ ),在中间编辑的 case 下,光标并不处于结尾,如 187^5 8,此时如果在 7 后面追加了一个 8,那么理想的图标应该维持在 8 之后(即 1878^ 58),此时就应该保存光标的位置在上次 format 之前的状态。

逻辑清楚了,接下来就是如何实现的问题了。那么如何探测和修改光标位置呢?这就涉及了 input 中选区相关的属性,我们知道我们可以通过一些方式(如鼠标拖拽和长按屏幕等)在 input 中完成对一段话的选区,因此光标的位置其实是由选区的开始点(selectionStart)和结束点(selectionEnd)决定的。那么其实我们就可以通过读取,储存和设置这两个属性来达到我们想要实现的目的,实例代码如下。

class Demo extends React.Component {
    ...
    
    componentDidUpdate(prevProps) {
        const { value } = prevProps;
        const { inputSelection } = this;
        if (inputSelection) {
          // 在 didUpdate 时根据情况恢复光标的位置
          // 如果光标的位置小于值的长度,那么可以判定属于中间编辑的情况
          // 此时恢复光标的位置
          if (inputSelection.start  { this.input = c; }}
                value={this.state.value} 
                onChange={(e) => { this.handleChange(e); }}  
            />
        );
    }
}

至此,我们终于在追加和中间编辑的情况下都实现了我们想要的效果。这是一个比较小的技术点,但是由于里面涉及了一些 React 内部的处理逻辑及平台差异性问题,排查和解决起来并不是那么容易,希望可以给有类似问题的同学在处理时有所启发。

Umgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details)

文中涉及的各端及浏览器信息

Android

Mozilla/5.0 (Linux; U; Android 8.1.0; zh-CN; CLT-AL00 Build/HUAWEICLT-AL00) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.108 UCBrowser/11.9.4.974 UWS/2.13.1.48 Mobile Safari/537.36

iOS

Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15F79

PC Chrome

Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Mobile Safari/537.36

文中涉及的组件库

SaltUI: https://github.com/salt-ui/sa...

Das obige ist der detaillierte Inhalt vonUmgang mit dem Cursor der React-Eingabe in numerischer Formatierung (Details). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen