প্রতিক্রিয়া জেএসে অনভিজ্ঞ ইভেন্টটি ট্রিগার করার সর্বোত্তম উপায় কী


112

আমরা ক্লায়েন্ট-সাইড অ্যাপ্লিকেশন তৈরি করতে ব্যাকবোন + রিঅ্যাক্টজেএস বান্ডিল ব্যবহার করি। অত্যন্ত কুখ্যাত উপর নির্ভর করে valueLinkআমরা মডেলটিতে সরাসরি নিজের মোড়কের মাধ্যমে প্রচার করি যা দ্বিপথের বাইন্ডিংয়ের জন্য রিঅ্যাক্টজেএস ইন্টারফেসকে সমর্থন করে।

এখন আমরা সমস্যার মুখোমুখি হয়েছি:

আমাদের jquery.mask.jsপ্লাগইন রয়েছে যা ইনপুট মানটিকে প্রোগ্রাম্যাটিকভাবে ফর্ম্যাট করে তাই এটি ইভেন্টের প্রতিক্রিয়া প্রকাশ করে না। মডেল ব্যবহারকারী ইনপুট থেকে অরক্ষিত মানগুলি গ্রহণ করে এবং প্লাগইন থেকে ফর্ম্যাট করা মানগুলি মিস করলে এগুলি সমস্ত পরিস্থিতিতে পরে to

দেখে মনে হয় যে প্রতিক্রিয়াটির ব্রাউজারের উপর নির্ভর করে ইভেন্ট হ্যান্ডলিংয়ের প্রচুর কৌশল রয়েছে। কোনও বিশেষ DOM উপাদানটির জন্য ইভেন্টটি পরিবর্তন করার কোনও সাধারণ উপায় আছে যাতে প্রতিক্রিয়াটি তা শুনতে পায়?


উত্তর:


174

প্রতিক্রিয়া 16 এবং প্রতিক্রিয়া> = 15.6 এর জন্য

সেটারটি .value=আমরা যেমন চাইছিলাম তেমন কাজ করছে না কারণ প্রতিক্রিয়া পাঠাগারটি ইনপুট মান সেটারকে ওভাররাইড করে তবে আমরা inputপ্রসঙ্গ হিসাবে সরাসরি ফাংশনটিতে কল করতে পারি ।

var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
nativeInputValueSetter.call(input, 'react 16 value');

var ev2 = new Event('input', { bubbles: true});
input.dispatchEvent(ev2);

পাঠ্য এলাকা উপাদান জন্য আপনি ব্যবহার করা উচিত prototypeএর HTMLTextAreaElementবর্গ।

নতুন কোডেন উদাহরণ

এই অবদানকারী এবং তার সমাধানের সমস্ত ক্রেডিট

কেবলমাত্র প্রতিক্রিয়া <= 15.5 এর জন্য পুরানো উত্তর

সঙ্গে react-dom ^15.6.0 আপনি ব্যবহার করতে পারেন simulatedঘটনা বস্তুর উপর পতাকা ঘটনা মধ্য দিয়ে পাস করার জন্য

var ev = new Event('input', { bubbles: true});
ev.simulated = true;
element.value = 'Something new';
element.dispatchEvent(ev);

আমি একটি উদাহরণ সহ একটি কোডেন তৈরি করেছি

নতুন পতাকা কেন প্রয়োজন তা বুঝতে আমি খুঁজে পেয়েছি এই মন্তব্যটি খুব সহায়ক বলে মনে করেছি:

প্রতিক্রিয়াতে ইনপুট যুক্তি এখন ডিপাপের পরিবর্তিত ইভেন্টগুলি যাতে তারা মূল্য অনুযায়ী একাধিকবার গুলি চালায় না। এটি উভয় ব্রাউজারের চেঞ্জ / অন ইনপুট ইভেন্টের পাশাপাশি ডিওএম নোড মান প্রাপের (যখন আপনি জাভাস্ক্রিপ্টের মাধ্যমে মান আপডেট করবেন) সেট করে। এর অর্থের পার্শ্ব প্রতিক্রিয়া রয়েছে যে আপনি যদি ইনপুটটির মানটি ম্যানুয়ালি ইনপুট করে থাকেন = ', এটি একটি সদৃশ ইভেন্ট হিসাবে বিবেচনা করুন এবং এটি গ্রাস করুন।

এটি সাধারণ ক্ষেত্রে সূক্ষ্মভাবে কাজ করে কারণ একটি "আসল" ব্রাউজার সূচিত ইভেন্টটি উপাদানটির মূল্য সেট করে না। আপনি এই যুক্তি থেকে গোপনে জামিন দিতে পারেন ঘটনাটি আপনি যেভাবে সিমুলেটেড পতাকা দিয়ে ট্রিগার করেন তা ট্যাগ করে এবং প্রতিক্রিয়া জানায় ইভেন্টটি সর্বদা আগুন ধরিয়ে দেবে। https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128


1
ধন্যবাদ এটি প্রতিক্রিয়া-ডোম ^ 15.6.0 থেকে কাজ করেছে। তবে এটি 16.0 এর পরে প্রতিক্রিয়া দেখায় এটি কাজ বন্ধ করে দিয়েছে। পরিবর্তন ইভেন্টগুলি ট্রিগার করতে সিমুলেটেড পতাকা ব্যবহারের বিকল্প সম্পর্কে কোনও ধারণা?
কিওয়ার্টি

বিশ্বাস করুন যে এখানে এমন একটি পয়েন্ট রয়েছে যা ইঙ্গিতটি দেবে: reactjs.org/blog/2017/09/26/react-v16.0.html# ब्रेकिंग- পরিবর্তনগুলি কী হতে পারে কোনও ধারণা?
কিওয়ারটি

@ কিওয়ার্টি আমি আমার উত্তর আপডেট করেছি, এটি আপনার পক্ষে কাজ করতে পারে
গ্রিন

এবং ক্লিক আবু বোতাম? এই ধরনের ইভেন্টটি ট্রিগার করার জন্য কী করা হবে?
বেন্ডার

@ বেন্ডার আপনি কেবলমাত্র উপাদানটি নেটিভ ক্লিক পদ্ধতিটি কল করুন
গ্রিন

63

অন্তত পাঠ্য ইনপুটগুলিতে, এটি প্রদর্শিত হয় যা onChangeইনপুট ইভেন্টগুলির জন্য শুনছে:

var event = new Event('input', { bubbles: true });
element.dispatchEvent(event);

ব্রাউজার সংস্করণে নির্ভর করে। আইই 8 ইনপুট ইভেন্টটিকে সমর্থন করে না। আপনি যখন পাঠ্যবক্স থেকে অক্ষরগুলি সরিয়ে ফেলেন এবং ie9 ইনপুট ইভেন্টটি চালায় না। বিকাশকারী.মোজিলা.আর.ইন-
ইউএস


1
আইই 8 আর প্রতিক্রিয়া দ্বারা সমর্থিত নয় । আইই 9 এর জন্য, আপনি এর মতো কিছু ব্যবহার করতে সক্ষম হতে পারেন var event = document.createEvent('CustomEvent'); event.initCustomEvent('input', true, false, { });তবে আমার কাছে কোনও আইআই 9 ভিএম নেই।
মাইকেল

@ মিশেল আমি আইইডিতে আপনার কোডটি চেষ্টা করে দেখছি এবং এটি রিঅ্যাক্টজ ইনপুট ক্ষেত্রে কাজ করছে না। এটি সাধারণ এইচটিএমএল ইনপুটগুলিতে কাজ করে। এটি এজেও কাজ করে। var evt = document.createEvent('CustomEvent'); evt.initCustomEvent('input', true, false, { }); document.getElementById('description').value = 'I changed description'; document.getElementById('description').dispatchEvent(evt);
বোডোস্কো

19

আমি জানি এই উত্তরটি একটু দেরিতে আসে তবে আমি সম্প্রতি একই ধরণের সমস্যার মুখোমুখি হয়েছি। আমি নেস্টেড উপাদানগুলিতে একটি ইভেন্ট ট্রিগার করতে চেয়েছিলাম। আমার রেডিও এবং চেক বাক্স টাইপ উইজেটগুলির সাথে একটি তালিকা ছিল (সেগুলি ডিভ ছিল যা চেকবক্স এবং / বা রেডিও বোতামগুলির মতো আচরণ করেছিল) এবং অ্যাপ্লিকেশনের অন্য কোনও জায়গায়, যদি কেউ কোনও সরঞ্জামবক্স বন্ধ করে রাখে, তবে আমার একটিটি অন্বেষণ করা দরকার।

আমি একটি খুব সহজ সমাধান পেয়েছি, এটি সর্বোত্তম অনুশীলন কিনা তা নিশ্চিত নই তবে এটি কার্যকর works

var event = new MouseEvent('click', {
 'view': window, 
 'bubbles': true, 
 'cancelable': false
});
var node = document.getElementById('nodeMyComponentsEventIsConnectedTo');
node.dispatchEvent(event);

এটি ডোমনোডের ক্লিক ইভেন্টটিকে ট্রিগার করেছিল এবং প্রতিক্রিয়াটির মাধ্যমে সংযুক্ত আমার হ্যান্ডলারটি সত্যই ডাকা হয়েছিল কারণ এটি এমন আচরণ করে যে কেউ যদি উপাদানটিতে ক্লিক করে তবে আমি আশা করি। আমি onChange পরীক্ষা করেছি না তবে এটি কাজ করা উচিত, এবং নিশ্চিত নয় যে এটি IE এর সত্যিকারের পুরানো সংস্করণগুলিতে কীভাবে সুষ্ঠু হবে তবে আমি বিশ্বাস করি যে মাউসএভেন্ট কমপক্ষে IE9 এবং তারপরে সমর্থিত।

অবশেষে আমি আমার বিশেষ ব্যবহারের ক্ষেত্রে এটি থেকে সরে এসেছি কারণ আমার উপাদানটি খুব ছোট ছিল (আমার প্রয়োগের কেবলমাত্র একটি অংশ এখনও এটি শিখছি বলে প্রতিক্রিয়া দেখায়) এবং ডম নোডের উল্লেখ না পেয়েও আমি একই জিনিসটি অর্জন করতে পারি।

হালনাগাদ:

অন্যরা মতামতে যেমন বলেছে, this.refs.refnameডোম নোডের একটি রেফারেন্স পাওয়ার জন্য এটি ব্যবহার করা ভাল । এই ক্ষেত্রে, পুনর্নবীকরণ হল আপনার রেফারেন্সটি আপনার উপাদানগুলির মাধ্যমে সংযুক্ত <MyComponent ref='refname' />


1
আইডি পরিবর্তে, আপনি React.findDOMNodeফাংশনটি ব্যবহার করতে পারেন । goo.gl/RqccrA
m93a

2
> আইডি পরিবর্তে, আপনি React.findDOMNode ফাংশনটি ব্যবহার করতে পারেন। বা refআপনার উপাদানটিতে একটি যুক্ত করুন তারপরে ব্যবহার করুনthis.ref.refName.dispatchEvent
সিল্কএডমিন

ফ্রেমওয়ার্ক সম্ভবত এর পরে পরিবর্তিত হয়েছে, এর.রিফ এর .refname
nclord

1
স্ট্রিং রেফগুলি এখন উত্তরাধিকার হিসাবে বিবেচনা করা হয় এবং ভবিষ্যতে হ্রাস করা হবে। কলব্যাক রেফগুলি ডিওএম নোডের ট্র্যাক রাখতে পছন্দের পদ্ধতি।
dzv3

9

আপনি ReactTestUtils ব্যবহার করে ইভেন্টগুলি অনুকরণ করতে পারেন তবে এটি ইউনিট পরীক্ষার জন্য ডিজাইন করা হয়েছে।

আমি এই ক্ষেত্রে মান লিংক না ব্যবহার এবং প্লাগইন দ্বারা চালিত ইভেন্টগুলি পরিবর্তন করতে এবং প্রতিক্রিয়া হিসাবে ইনপুটটির স্থিতি আপডেট করার পরামর্শ দিচ্ছি listening দ্বিমুখী বাইন্ডিং অন্য যে কোনও কিছুর চেয়ে ডেমো হিসাবে বেশি ব্যবহার করে; খাঁটি দ্বিমুখী বাঁধাই বেশিরভাগ অ্যাপ্লিকেশনের জন্য উপযুক্ত নয় এবং আপনার অ্যাপ্লিকেশনটির ইন্টারঅ্যাকশনগুলি বর্ণনা করার জন্য সাধারণত আপনার আরও অ্যাপ্লিকেশন যুক্তির প্রয়োজন হয় তা এই বিষয়টির উপর জোর দেওয়ার জন্য এগুলি অ্যাডনগুলিতে অন্তর্ভুক্ত রয়েছে।


আমি ভয় পেয়েছিলাম যে উত্তরটি এর মতো কিছু হবে (সমস্যাটি হ'ল কার্যপ্রবাহ প্রেরণ / গ্রহণের ক্ষেত্রে প্রতিক্রিয়াটি অত্যন্ত কঠোর। । me.In আমার ক্ষেত্রে ওভার boilerplate, আমি এই হ্যান্ডলার ঘোষণা করা উচিত শুধুমাত্র নিয়ম অনুসরণ করতে, যখন প্রাসঙ্গিক ইনপুট onchange ঘটনা jQuery দ্বারা আলোড়ন সৃষ্টি থেকে আসবে প্রতিক্রিয়া সত্যিই পাঠান ব্যাপ্ত ধারণা অভাব আছে / গ্রহণ ব্যবহারকারীর সাথে এন্ড পয়েন্ট ঘোষিত কোড
wallice

1
এবং ... আপনি যদি ReactTestUtils ব্যবহার করতে চান ...ReactTestUtils.Simulate.change(ReactDOM.findDOMNode(this.fieldRef))
কল্লিন

8

গ্রিন / ড্যান আব্রামভের উত্তরটি প্রসারিত করে, এটি একাধিক ইনপুট ধরণের কাজ করে। প্রতিক্রিয়া> = 15.5 এ পরীক্ষিত

const inputTypes = [
    window.HTMLInputElement,
    window.HTMLSelectElement,
    window.HTMLTextAreaElement,
];

export const triggerInputChange = (node, value = '') => {

    // only process the change on elements we know have a value setter in their constructor
    if ( inputTypes.indexOf(node.__proto__.constructor) >-1 ) {

        const setValue = Object.getOwnPropertyDescriptor(node.__proto__, 'value').set;
        const event = new Event('input', { bubbles: true });

        setValue.call(node, value);
        node.dispatchEvent(event);

    }

};

5
নির্বাচিত উপাদানগুলির জন্য কাজ করে না। ইভেন্টটির জন্য আপনার 'ইনপুট' পরিবর্তে 'পরিবর্তন' দরকার need
শৈলী

3

স্বেচ্ছাসেবী উপাদানগুলিতে পরিবর্তন ইভেন্টগুলি ট্রিগার করা উপাদানগুলির মধ্যে নির্ভরতা তৈরি করে যার বিষয়ে तर्क করা শক্ত। প্রতিক্রিয়াটির একমুখী ডেটা প্রবাহের সাথে থাকা আরও ভাল।

প্রতিক্রিয়া পরিবর্তনের ইভেন্টটি ট্রিগার করার জন্য কোনও সরল স্নিপেট নেই। লজিকটি চেঞ্জইভেন্টপ্লাগিন.জেজে প্রয়োগ করা হয়েছে এবং বিভিন্ন ইনপুট ধরণের এবং ব্রাউজারগুলির জন্য বিভিন্ন কোড শাখা রয়েছে। তদুপরি, বাস্তবায়নের বিবরণগুলি প্রতিক্রিয়াটির বিভিন্ন সংস্করণে পৃথক হয়।

আমি প্রতিক্রিয়া-ট্রিগার-পরিবর্তন তৈরি করেছি যা কাজটি করে তবে এটি পরীক্ষার জন্য ব্যবহারের উদ্দেশ্যে, কোনও উত্পাদন নির্ভরতা হিসাবে নয়:

let node;
ReactDOM.render(
  <input
    onChange={() => console.log('changed')}
    ref={(input) => { node = input; }}
  />,
  mountNode
);

reactTriggerChange(node); // 'changed' is logged

CodePen


1

ভাল যেহেতু আমরা কোনও অন্বেষণ ইভেন্ট হ্যান্ডেল করতে ফাংশনগুলি ব্যবহার করি, আমরা এটি এটির মতো করতে পারি:

class Form extends Component {
 constructor(props) {
  super(props);
  this.handlePasswordChange = this.handlePasswordChange.bind(this);
  this.state = { password: '' }
 }

 aForceChange() {
  // something happened and a passwordChange
  // needs to be triggered!!

  // simple, just call the onChange handler
  this.handlePasswordChange('my password');
 }

 handlePasswordChange(value) {
 // do something
 }

 render() {
  return (
   <input type="text" value={this.state.password} onChange={changeEvent => this.handlePasswordChange(changeEvent.target.value)} />
  );
 }
}

1

আমি এটি রিএ্যাক্টের গিথুব ইস্যুতে পেয়েছি: কবজির মতো কাজ করে (v15.6.2)

আমি এখানে কোনও পাঠ্য ইনপুটটিতে কীভাবে প্রয়োগ করেছি:

changeInputValue = newValue => {

    const e = new Event('input', { bubbles: true })
    const input = document.querySelector('input[name=' + this.props.name + ']')
    console.log('input', input)
    this.setNativeValue(input, newValue)
    input.dispatchEvent(e)
  }

  setNativeValue (element, value) {
    const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set
    const prototype = Object.getPrototypeOf(element)
    const prototypeValueSetter = Object.getOwnPropertyDescriptor(
      prototype,
      'value'
    ).set

    if (valueSetter && valueSetter !== prototypeValueSetter) {
      prototypeValueSetter.call(element, value)
    } else {
      valueSetter.call(element, value)
    }
  }

পাঠ্যবাক্সের মানটি আপনি যে মূল্য সেট করে নেটিভালিয়ে যাচ্ছেন তার সমান হলে এটি কাজ করবে না
অরুণ

0

জন্য HTMLSelectElement, যেমন<select>

var element = document.getElementById("element-id");
var trigger = Object.getOwnPropertyDescriptor(
  window.HTMLSelectElement.prototype,
  "value"
).set;
trigger.call(element, 4); // 4 is the select option's value we want to set
var event = new Event("change", { bubbles: true });
element.dispatchEvent(event);

-1

আপনি যদি ব্যাকবোন এবং প্রতিক্রিয়া ব্যবহার করে থাকেন তবে আমি নিম্নলিখিতগুলির মধ্যে একটির প্রস্তাব দেব,

তারা উভয়ই প্রতিক্রিয়া দর্শনের সাথে ব্যাকবোন মডেল এবং সংগ্রহকে সংহত করতে সহায়তা করে। ব্যাকবোন দর্শনগুলির সাথে আপনি যেমন করেন তেমনই আপনি ব্যাকবোন ইভেন্টগুলি ব্যবহার করতে পারেন। আমি উভয় dabbled করেছি এবং ছাড়া এক একটি mixin এবং অন্যান্য পরিবর্তন হয় অনেক একটি পার্থক্য দেখতে পাইনি React.createClassকরতে React.createBackboneClass


দয়া করে প্রতিক্রিয়া এবং ব্যাকবোনগুলির মধ্যে সেই "ইভেন্ট-চালিত" ব্রিজগুলির সাথে সতর্ক থাকুন প্রথম প্লাগইনটি উপাদান মাউন্ট স্তরের উপেক্ষা করে সেটপ্রপস ব্যবহার করে। এটা একটা ভুল. দ্বিতীয় প্রচন্ডভাবে ফোর্সআপ্টেট এবং মনের উপর নির্ভর করে যে কোনও উপাদানগুলির জন্য কেবল একটি মডেল নির্ধারিত হতে পারে, যা সাধারণ পরিস্থিতি নয়। আরও বেশি, যদি আপনি জটিল UI জুড়ে মডেলটি প্রতিক্রিয়াযুক্ত উপাদানগুলির সাথে ভাগ করে নেন এবং জোর-আপডেটের কারণী অকেজো আপডেট ইভেন্টগুলি থেকে সদস্যতা নিতে ভুলে গিয়ে থাকেন তবে আপনি পুনরাবৃত্ত রেন্ডারিংয়ে পড়তে পারেন, সে সম্পর্কে সচেতন হন।
প্রাচীর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.