React: وقع حدث التغيير مرات إضافية قبل انتهاء تكوين محرر أسلوب الإدخال (IME)

تم إنشاؤها على ٢١ مايو ٢٠١٥  ·  48تعليقات  ·  مصدر: facebook/react

تفاصيل اضافية


البند الاصلي

عندما كنت أحاول هذا المثال من https://facebook.github.io/react/blog/2013/11/05/thinking-in-react.html ، فإن أي أحرف صينية يتم إدخالها عن طريق أسلوب إدخال بينيين الصينية ستطلق العديد من العروض مثل :

screen shot 2015-05-21 at 14 04 36

في الواقع ، أتوقع ألا يطلقوا النار قبل تأكيد الشخصية الصينية.

ثم جربت نوعًا آخر من طرق الإدخال - طريقة إدخال wubi ، حصلت على هذا:

screen shot 2015-05-21 at 14 17 15

إنه أمر غريب أيضًا. لذلك أجريت اختبارًا في jQuery :

screen shot 2015-05-21 at 14 05 12

فقط بعد أن أضغط على شريط المسافة لتأكيد الشخصية ، سيتم إطلاق الحدث keyup .

أعلم أنه قد يكون مختلفًا بين تنفيذ jQuery keyup والتفاعل onChange ، لكنني أتوقع الطريقة التي يتعامل بها jQuery keyup مع الأحرف الصينية بدلاً من رد الفعل onChange .

DOM Bug

التعليق الأكثر فائدة

مرحبًا يا شباب Facebook ، في الواقع ، تسبب هذه المشكلة مشكلة خطيرة : لا يمكننا تحديث الإدخال بشكل غير متزامن مع المدخلات الصينية.
على سبيل المثال ، لا يمكننا استخدام مصادر البيانات التفاعلية النيزكية أو مخازن مثل redux ، لأنها جميع التعليقات يتم تحديثها بشكل غير متزامن.
فيما يلي أبسط مثال لإظهار هذه المشكلة ، فهو يستخدم setTimeout لإجراء تحديث غير متزامن:
https://jsfiddle.net/liyatang/bq6oss6z/1/

آمل حقًا أن تتمكن من إصلاح هذا بسرعة ، حتى لا نهدر جهودنا لحلها هنا وهناك مرارًا وتكرارًا.

شكر.

هنا هو الحل الخاص بي. إذا واجه أي شخص نفس المشكلة ، يمكنك إلقاء نظرة

ال 48 كومينتر

ccsalier :) - ماذا يجب أن نفعل هنا؟

أعتقد أنه لا يجب إطلاق onChange حتى يتم الالتزام بسلسلة IME.

تتمثل إحدى طرق معالجة هذا الأمر في ChangeEventPlugin في تجاهل جميع أحداث input بين compositionstart و compositionend ، ثم استخدام الحدث input فورًا بعد compositionend .

لقد أجريت بعض الاختبارات السريعة على OSX Chrome و Firefox باستخدام Simplified Pinyin و 2-Set Korean ، ويبدو أن ترتيب الأحداث والبيانات صحيحة بما فيه الكفاية. (أتوقع أننا سنواجه مشاكل مع IE Korean ، لكننا قد نكون محظوظين.)

أعتقد أننا قد نستمر في رؤية المشكلات المتعلقة بأساليب الإدخال البديلة مثل ملحق أدوات الإدخال من Google ، ولكن قد تكون هناك حلول لذلك.

يؤثر هذا أيضًا على كيفية كتابة الأحرف الجدلية للغات اللاتينية. حتى الضغط لفترة طويلة على e ثم استخدام المتغير يفشل هنا.

آسف يبدو أن هذا لا علاقة له. اعتذاري.

هل يوجد تحديث؟ يعاني من هذه القضية أيضا.

لا شيء حاليًا - هذه ليست أولوية عالية بالنسبة لنا في الوقت الحالي. سأكون سعيدًا للنظر في طلب سحب إذا غاص أي شخص في إصلاح هذا.

salier يبدو أن IE لا يطلق حدث input بعد compositionend . لقد اختبرت على IE11 و Edge على Windows 10. إنه يعمل بشكل صحيح في Chrome و Firefox.

في مثال 9 ، يتم تشغيل حدث التغيير مرات عديدة عند إدخال الأحرف الصينية مرة أخرى

مرحبًا يا شباب Facebook ، في الواقع ، تسبب هذه المشكلة مشكلة خطيرة : لا يمكننا تحديث الإدخال بشكل غير متزامن مع المدخلات الصينية.
على سبيل المثال ، لا يمكننا استخدام مصادر البيانات التفاعلية النيزكية أو مخازن مثل redux ، لأنها جميع التعليقات يتم تحديثها بشكل غير متزامن.
فيما يلي أبسط مثال لإظهار هذه المشكلة ، فهو يستخدم setTimeout لإجراء تحديث غير متزامن:
https://jsfiddle.net/liyatang/bq6oss6z/1/

آمل حقًا أن تتمكن من إصلاح هذا بسرعة ، حتى لا نهدر جهودنا لحلها هنا وهناك مرارًا وتكرارًا.

شكر.

هنا هو الحل الخاص بي. إذا واجه أي شخص نفس المشكلة ، يمكنك إلقاء نظرة

لقد قمت بعمل مثال بسيط لعرض كيفية استخدام أحداث compositionstart و compositionend لمنع إدخال محرر أسلوب الإدخال الصيني على مشكلة حدث onchange .
ها هو الرابط: https://jsfiddle.net/eyesofkids/dcxvas28/8/

eyesofkids عمل رائع ، يمكن أن يكون هذا التطبيق الافتراضي onChange للإدخال ، textarea ...

عمل جيد !

كنت أعاني من نفس المشكلة ويعمل حل eyesofkids بشكل مثالي (شكرًا لك!).

بعد تطبيق الحل ، كنت أغوص في الكود المصدري لـ React على الأقل لمحاولة إضافة اختبار فاشل لهذا - آملاً في إضافة السلوك المتوقع لاحقًا إلى المكتبة - على الرغم من أنه يبدو معقدًا بعض الشيء بالنسبة لشخص ليس على دراية بالأمور الداخلية.

في البداية كنت أتوقع أن اختبارًا مشابهًا لما هو متاح بالفعل لـ ChangeEventPlugin يجب أن يعمل ، أي محاكاة مواطن compositionStart / compositionUpdate والتحقق من عدم وجود رد اتصال onChange كان مطرود؛ التحقق أيضًا من onChange سيتم إطلاقه بمجرد محاكاة compositionEnd . لكن هذا لا يبدو أنه يعمل.

ومن ثم كنت أفكر في أن التحقق من ChangeEventPlugin.extractEvents() سيكون نهجًا ممكنًا ، على غرار ما تم إجراؤه في اختبارات SelectEventPlugin . هنا لسبب ما ، أحصل دائمًا على undefined عند استخراج الأحداث.
كمرجع ، هذا هو رمز الاختبار الذي جربته في _ChangeEventPlugin-test.js_:

  var EventConstants = require('EventConstants');
  var ReactDOMComponentTree = require('ReactDOMComponentTree');
  var topLevelTypes = EventConstants.topLevelTypes;

  function extract(node, topLevelEvent) {
    return ChangeEventPlugin.extractEvents(
      topLevelEvent,
      ReactDOMComponentTree.getInstanceFromNode(node),
      {target: node},
      node
    );
  }

  function cb(e) {
    expect(e.type).toBe('change');
  }
  var input = ReactTestUtils.renderIntoDocument(
    <input onChange={cb} value='foo' />
  );

  ReactTestUtils.SimulateNative.compositionStart(input);

  var change = extract(input, topLevelTypes.topChange);
  expect(change).toBe(null);

أخشى أنني لا أعرف بالضبط كيف يُفترض أن ينجح المرء في تصحيح هذه الاختبارات - وإلا فسيكون لدي صورة أوضح عما يحدث. أي إرشادات حول كيفية المتابعة أو أي مؤشرات أخرى ستكون محل تقدير كبير.

توقف الحل فجأة في Chrome 53+ ويبدو أنه لم يعد صالحًا بعد الآن لأنهم قاموا بتغيير الطلب compositionend تم إطلاقه : حدث ذلك سابقًا قبل textInput ، والآن بعد textInput . نتيجة لذلك ، لن يتم تشغيل change إذا تم إحباطه أثناء التكوين 😕.

https://github.com/suhaotian/react-input ربما يساعد شخصًا ما

يوجد حل صعب لـ Chrome v53. لاستدعاء Handlechange بعد إطلاق compositionend .

handleComposition  = (event) => {

    if(event.type === 'compositionend'){
      onComposition = false

      //fire change method to update for Chrome v53
      this.handleChange(event)

    } else{
      onComposition = true
    }
  }

تحقق من العرض التوضيحي هنا: https://jsfiddle.net/eyesofkids/dcxvas28/11/

chenxsan هل وجدت الحل؟
يمكنك اكتشاف التكوين ، ابدأ ودع متغيرًا يساوي true.
ثم لاستخدام المتغير ، الذي قمت بتعيينه ، عند onChange لمعرفة ما إذا كان يجب تشغيل الاستعلام

لقد أرسلت إصدارًا جديدًا للمكونات الخاضعة للرقابة في # 8683

يتم تحميل الحل المؤقت للمكونات غير الخاضعة للرقابة والمراقبة (الإدخال ، منطقة النسيج) إلى حدث تكوين التفاعل .

yesmeck سعيد للغاية لرؤية هذه الأخبار.

رأيت اختبار تركز فقط على بكت، ينبغي أن يكون منفصلا في كروم وسفاري لكروم تغيير في compositionend الحدث أجل تشغيلها بعد 53+.

أضاف eyesofkids حالة اختبار جديدة لمتصفح Chrome أقل من 53 عامًا.

فقط لإضافة الوقود إلى النار ، كنت أحاول حل هذه المشكلة واكتشفت أن الإصدار الحالي من iOS Safari لا يؤدي إلى حدث compositionend عند استخدام محرر أسلوب الإدخال الياباني Hiragana ، أعتقد أن هذا مقصود لأن لا يبدو أن قائمة التكوين مغلقة.
على سبيل المثالeyesofkids الحل يتم تحديث inputValue أبدا، على الرغم بالنسبة لي https://github.com/zhaoyao91/react-optimistic-input إصلاح المشكلة مع IME اليابانية.

لأي شخص يبحث عن حل لهذا ، إليك مكون جاهز للاستخدام. https://github.com/aprilandjan/react-starter/blob/test/search-input/src/components/SearchInput.js فقط استخدمه بدلاً من عنصر إدخال النص العادي وكل شيء على ما يرام.

@ zhaoyao91 الحل الخاص بك يعمل فقط! شكرا كثيرا.

يا رفاق بعض الأخبار في هذا الموضوع؟

لم تكن أولوية عالية لأن إطلاق النار عند التغيير كثيرًا نادرًا ما يسبب مشاكل. أين تسبب المشاكل في تطبيقك؟

sophiebits آسف نقرت بطريق الخطأ "X". يمكن أن يؤدي هذا إلى تدهور الأداء إذا كانت هناك عمليات تصفية أو عمليات استرجاع للخادم مستخدمة في معالجات أحداث التغيير. يُعد النهج الموضح في https://github.com/facebook/react/issues/3926#issuecomment -316049951 حلاً جيدًا للمدخلات غير المنضبطة أو الأصلية ولكنه لا يتناسب جيدًا مع المدخلات التي يتم التحكم فيها. يبدو أن البعض في هذا الموضوع قد حاولوا تطوير علاقات عامة ولكنهم وجدوا الأجزاء الداخلية معقدة بعض الشيء - ولكن ربما يمكن لمهندس في فريقك أن يقوم بعملها بشكل أسرع؟ https://github.com/facebook/react/issues/8683 هو وصف أفضل بكثير للقضية الحقيقية IMO.

هل يمكن لأي شخص مساعدتي في فهم: هل المشكلة في مكالمات إضافية onChange في المنتصف ؟ أم أنك تحصل على قيمة غير صحيحة في النهاية؟

يمر الاختبار من محاولة الإصلاح في https://github.com/facebook/react/pull/8438 إذا قمت بإزالة التأكيد حول عدد مرات استدعاء onChange . لذلك أفترض أن هذه المشكلة تتعلق فقط بالمكالمات الإضافية onChange .

لا توجد مكالمات onChange إضافية ، إنها مجرد الحصول على قيمة غير صحيحة في النهاية ، تبدو أشبه بمشكلة onComposition.

crochefluid هل يمكنك إنشاء اختبار فاشل لهذا؟ على غرار ما حاول القيام به # 8438. في هذا الاختبار ، لم تكن هناك قيمة غير صحيحة.

gaearon سأحاول ذلك. هل جربت هذا الاختبار على Safari (mac / IOS)؟

إنه اختبار Node ولكنه يشفر التسلسلات الملتقطة من متصفحات وأجهزة مختلفة. يرجى الاطلاع على مصدره. ستحتاج إلى إضافة تسلسلات فاشلة.

لذلك أفترض أن هذه المشكلة تتعلق فقط بمكالمات onChange الإضافية.

بالضبط.

ما زلت أتلقى هذه المشكلة. يبدو أن هذه المشكلة ظلت مفتوحة منذ 3 سنوات ، فهل تدعم React المدخلات الصينية في المكونات الخاضعة للرقابة في الوقت الحالي؟

أرى هذا أيضًا باللغة اليابانية بشخصيات معينة ...

هذا هو رمز الحماية الذي يعيد إنتاج مشكلتي. يبدو أنه مرتبط بالنماذج. استخدام المدخلات مباشرة أمر جيد.

https://codesandbox.io/s/0m1760xqnl

أضفت بعض الحالات:
استخدام حالة التفاعل والمدخلات العادية جيد
إن استخدام حالة التفاعل والنماذج العادية والمدخلات العادية أمر جيد
نحن نستخدم مكون نموذج قائم على السياق ولا يعمل. قد تكون مشكلة متعلقة بالسياق.

تم حل المشكلة: لقد عملت في codepen. لسبب ما ، تم تمرير "الإدخال" كمكون يعمل ، عند تمرير (props) => لم.

أي شخص لديه فكرة ما هو الفرق؟

في الواقع ، لقد حاولت أيضًا:

يعمل

<Field {...otherProps} component="input" />

لا يعمل

<Field {...otherProps} component={(props) => <input {...props} />} />

يعمل بغرابة

const WrappedInput = (props) => <input {...props} />
...
<Field {...otherProps} component={WrappedInput} />

من الواضح أن هناك بعض السحر يحدث هنا ولا أفهمه. 😕

أي تحديثات؟

يبدو أنه يتسبب في نتيجة غير صحيحة عند تمكين محرر أسلوب الإدخال

e84721f3ec71a5ce043ef8290

لقد واجهت نفس المشكلة مثلotakustay
يبدو من المستحيل دعم الإدخال المتحكم فيه باستخدام إدخال محرر أسلوب الإدخال. لقد تتبعت تسلسل الأحداث إلى ما يلي.

  1. يكتب المستخدم حرفًا ، على سبيل المثال w
  2. تم تشغيل عند التغيير
  3. يتم تحديث الحالة بقيمة جديدة
  4. يتم نشر القيمة الجديدة وصولاً إلى input عن طريق السمة value .
  5. تمت مقاطعة "تكوين" محرر أسلوب الإدخال (IME) في هذه المرحلة

    • هناك سلسلة w في عنصر الإدخال

    • هناك أيضًا سلسلة منفصلة من w مخزنة في المخزن المؤقت لمحرر أسلوب الإدخال

  6. يكتب المستخدم حرفًا آخر ، مثل a
  7. تتحد السلسلة الموجودة في الإدخال a مع السلسلة المخزنة IME لإنتاج wwa .
  8. كرر الخطوات من 1 إلى 7 للحصول على مجموعة من الأحرف المكررة.

لقد لاحظت أن الخطأ يحدث فقط إذا تمت إعادة عرض الإدخال > 15 مللي ثانية

الحل الوحيد الآن هو الابتعاد عن المدخلات الخاضعة للرقابة.

تحرير : هنا نسخة بسيطة: https://jsfiddle.net/kbhg3xna/
Edit2 : هذا هو الحل البديل الخاص بي: https://jsfiddle.net/m792qtys/ cc: otakustay

أي تحديثات على هذا؟

تحديث ؟؟

أي تحديث على هذا؟

مذهول ، لقد واجهت هذا السؤال

من المثير للاهتمام ، أن المشكلة لا تتعلق فقط بالتغيير المتعدد الأوقات. إذا لم نقم بتعيين الحالة بين onCompositionStart و onCompositionEnd ، فإن التفاعل "يتحكم" في القيمة كما هي. سيؤدي هذا الإجراء إلى مقاطعة التكوين. هذا يعني أننا لن نحصل على حدث onCompositionEnd ...... (إذا كنت مخطئًا أذكرني من فضلك.) ولكن لا يمكننا تغيير الحالة إلا على الفور (وإلا فسيتعين علينا مواجهة المشكلة @ يذكر https://gist.github.com/cpdyj/6567437d96c315e9162778c8efdfb6e8

لكنني مندهش جدًا من عدم وجود حل للمشكلة خلال خمس سنوات 😢

hellendag أعتقد أنه لا ينبغي إطلاق onChange حتى يتم الالتزام بسلسلة IME.

لا أعتقد أن هذا حل صالح لأن أحد المكونات قد يرغب في معرفة سلسلة محرر أسلوب الإدخال "غير الملتزم بها" على سبيل المثال خيارات التصفية في قائمة مثل أنواع المستخدمين.

لست متأكدًا مما إذا كان النهج الذي أستخدمه في هذا الموضوع الآخر قد يساعد أولئك الذين يواجهون هذه المشكلة ، ولكن هذا الرابط فقط في حالة: https://github.com/facebook/react/issues/13104#issuecomment -691393940

أي تحديثات؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات