programing

jQuery 또는 플레인 JavaScript의 react js에서 변경 또는 입력 이벤트를 트리거하는 가장 좋은 방법은 무엇입니까?

closeapi 2023. 3. 7. 21:30
반응형

jQuery 또는 플레인 JavaScript의 react js에서 변경 또는 입력 이벤트를 트리거하는 가장 좋은 방법은 무엇입니까?

Backbone + React JS 。악명높은 것에 크게 의존하고 있다valueLink를 지원하는합니다.JS는 JS를 사용하고 있습니다.

이제 우리는 다음과 같은 문제에 직면했습니다.

우리는 가지고 있다.jquery.mask.js플러그인은 입력값을 프로그래밍 방식으로 포맷하기 때문에 React 이벤트를 발생시키지 않습니다.이 때문에 모델이 사용자 입력에서 포맷되지 않은 값을 수신하고 플러그인에서 포맷된 값을 놓치는 상황이 발생합니다.

리액트는 브라우저에 따라 이벤트 처리 전략이 풍부한 것 같습니다.특정 DOM 요소에 대해 변경 이벤트를 트리거하여 React가 이를 수신할 수 있도록 하는 일반적인 방법이 있습니까?

React 16 및 React > = 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);

에는 이렇게 하다를 해야 합니다.prototypeHTMLTextAreaElement를 누릅니다

새로운 코드펜 예시

모든 크레딧이 이 기고자와 솔루션에 대한 입니다.

React <=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);

나는 예를 들어 코드펜을 만들었다.

새로운 플래그가 필요한 이유를 이해하기 위해 코멘트가 매우 도움이 되었습니다.

React의 입력 논리는 중복 제거 변경 이벤트를 통해 변경 이벤트가 값당 두 번 이상 실행되지 않도록 합니다.브라우저 onChange/onInput 이벤트와 DOM 노드 값 프로펠러 설정(javascript를 통해 값을 갱신하는 경우)을 모두 수신합니다.이는 입력 값을 수동으로 input.value = 'foo'로 업데이트한 다음 {target: input}을(를) 사용하여 ChangeEvent를 디스패치하면 Respect가 세트와 이벤트를 모두 등록하고 값이 여전히 'foo'임을 확인하고 중복 이벤트를 삼킨다는 의미에 대한 부작용을 가지고 있습니다.

이는 "실제" 브라우저 시작 이벤트는 element.value에 대한 세트를 트리거하지 않기 때문에 일반적인 경우 정상적으로 작동합니다.시뮬레이션 플래그로 트리거한 이벤트에 태그를 지정하면 이 논리에서 몰래 벗어날 수 있으며 항상 이벤트가 발생합니다.https://github.com/jquense/react/blob/9a93af4411a8e880bbc05392ccf2b195c97502d1/src/renderers/dom/client/eventPlugins/ChangeEventPlugin.js#L128

에서는 어어음음음음음음음음음음음음음음음음 at at at at at at at at at at at at at at .onChange를 리슨하고 있습니다.

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

Green/Dan Abramov의 답변을 확장하면 여러 입력 유형에서 작동합니다.React > = 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);

    }

};

이 답변이 조금 늦은 건 알지만 최근에 비슷한 문제에 직면했어요.중첩된 구성 요소에서 이벤트를 트리거하려고 했습니다.라디오 및 체크박스 유형의 위젯(체크박스 및/또는 라디오 버튼과 같은 기능을 하는 div) 목록이 있었고, 응용 프로그램의 다른 곳에서 누군가 도구 상자를 닫았을 때 하나를 선택 취소해야 했습니다.

저는 꽤 간단한 해결책을 찾았습니다. 이것이 베스트 프랙티스인지는 모르겠지만 효과가 있습니다.

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

이로 인해 domNode의 클릭 이벤트가 트리거되어 react를 통해 연결된 핸들러가 실제로 호출되었습니다.따라서 누군가 요소를 클릭하면 정상적으로 동작합니다.아직 OnChange를 테스트한 적은 없지만 동작할 수 있습니다.또한 오래된 버전의 IE에서는 이것이 어떻게 적용되는지 잘 모르겠습니다만, 적어도 IE9 이후에서는 MouseEvent가 서포트되고 있다고 생각합니다.

결국 컴포넌트가 매우 작고(아직 학습 중이기 때문에 애플리케이션의 일부만 반응을 사용) 돔 노드에 대한 참조 없이 다른 방법으로 동일한 작업을 수행할 수 있었기 때문에 특정 사용 사례를 위해 이 작업을 중단했습니다.

갱신:

'다음에 더 좋다'는 표현을 게 것 같아요.this.refs.refname돔 노드를 참조할 수 있습니다.은 component를 통해 입니다.<MyComponent ref='refname' />.

ReactTestUtils를 사용하여 이벤트를 시뮬레이트할 수 있지만 이는 유닛 테스트용으로 설계되었습니다.

이 경우 valueLink를 사용하지 않고 플러그인에 의해 실행되는 변경 이벤트를 듣고 응답하여 입력 상태를 업데이트하는 것을 권장합니다.양방향 바인딩은 다른 어떤 것보다도 데모에 많이 활용됩니다. 애드온에 포함된 것은 순수 양방향 바인딩이 대부분의 애플리케이션에 적합하지 않다는 사실과 앱에서 상호 작용을 설명하는 데 더 많은 애플리케이션 로직이 필요하다는 사실을 강조하기 위한 것입니다.

을 사용법에서는 'Default 지원'이 있습니다.'click', 'focus', 'blur' 후 , JavaScript 등의 ,'change', 'input'(아직) 구현되지 않았습니다.

저는 이 일반적인 해결책을 생각해 냈고, 인정된 답변을 바탕으로 코드를 수정했습니다.

export const triggerNativeEventFor = (elm, { event, ...valueObj }) => {
  if (!(elm instanceof Element)) {
    throw new Error(`Expected an Element but received ${elm} instead!`);
  }

  const [prop, value] = Object.entries(valueObj)[0] ?? [];
  const desc = Object.getOwnPropertyDescriptor(elm.__proto__, prop);

  desc?.set?.call(elm, value);
  elm.dispatchEvent(new Event(event, { bubbles: true }));
};

어떻게 작동합니까?

triggerNativeEventFor(inputRef.current, { event: 'input', value: '' });

다음 두 번째 숙박업소는'event'키와 값의 쌍이 고려되고 나머지는 무시/삭제됩니다.이는 도우미 함수의 인수 정의를 복잡하게 하지 않기 위해 의도적으로 이렇게 기술되어 있습니다.디폴트로 디스크립터를 취득하지 않는 이유'value'예를 들어 네이티브 체크박스가 있는 경우만 해당됩니다.<input type="checkbox" />가치가 없는 것 보다는 오히려'checked'소품/소품그런 다음 다음과 같이 원하는 체크 상태를 전달할 수 있습니다.

triggerNativeEventFor(checkBoxRef.current, { event: 'input', checked: false });

React의 Github 문제에서 이것을 발견했습니다.마법처럼 기능 (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)
    }
  }

위해서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);

임의의 요소에서 변경 이벤트를 트리거하면 컴포넌트 간에 의존성이 생기기 때문에 이해하기 어렵습니다.React의 단방향 데이터 흐름을 유지하는 것이 좋습니다.

React의 변경 이벤트를 트리거하는 간단한 스니펫은 없습니다.이 로직은 ChangeEventPlugin.js에 구현되어 있으며 입력 유형 및 브라우저에 따라 다른 코드브런치가 존재합니다.또한 구현 세부 사항은 React 버전에 따라 다릅니다.

react-trigger-change를 구축하여 이 기능을 수행했지만, 이는 테스트용으로 사용되는 것이지 프로덕션 종속성으로 사용되는 것은 아닙니다.

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

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

코드펜

변경 이벤트를 처리하기 위해 함수를 사용하기 때문에 다음과 같이 할 수 있습니다.

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)} />
  );
 }
}

이벤트 유형input에 효과가 없었습니다.<select>로 바꾸면change작동하다

useEffect(() => {
    var event = new Event('change', { bubbles: true });
    selectRef.current.dispatchEvent(event); // ref to the select control
}, [props.items]);

이 추악한 솔루션이 나에게 효과가 있었다.

let ev = new CustomEvent('change', { bubbles: true });
Object.defineProperty(ev, 'target', {writable: false, value: inpt });
Object.defineProperty(ev, 'currentTarget', {writable: false, value: inpt });
const rHandle = Object.keys(inpt).find(k => k.startsWith("__reactEventHandlers"))
inpt[rHandle].onChange(ev);

Backbone과 React를 사용하는 경우 다음 중 하나를 권장합니다.

둘 다 Backbone 모델과 컬렉션을 React 뷰와 통합하는 데 도움이 됩니다.Backbone 이벤트는 Backbone 뷰와 마찬가지로 사용할 수 있습니다.두 가지를 모두 사용해 보았지만, 하나는 믹스인이고 다른 하나는 변경되는 것 외에는 큰 차이를 느끼지 못했습니다.React.createClass로.React.createBackboneClass.

언급URL : https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-change-or-input-event-in-react-js-from-jquery-or

반응형