리액트 JS에서 jQuery UI를 사용하는 방법
react에서 jQuery UI를 사용하려면 어떻게 해야 합니까?구글링의 사례를 몇 번 봤지만 모두 시대에 뒤떨어진 것 같다.
꼭 그렇게 해야 한다면, 여기 제가 사용하는 방법이 있습니다.
계획: jQuery 플러그인을 관리할 컴포넌트를 만듭니다.이 구성 요소는 jQuery 구성 요소의 반응 중심 보기를 제공합니다.또한 다음과 같은 이점이 있습니다.
- 리액트 라이프 사이클 메서드를 사용하여 jQuery 플러그인을 초기화 및 해체합니다.
- 사용
props플러그인 구성 옵션 및 플러그인 메서드 이벤트에 접속합니다. - 구성 요소가 마운트 해제되면 플러그인을 삭제합니다.
jQuery UI Sortable 플러그인을 사용하여 이를 수행하는 실제 예를 살펴보겠습니다.
TLDR: 최종 버전
랩된 jQuery UI Sortable 예제의 최종 버전을 가져오려는 경우:
...또, 다음은 긴 코멘트 코드 스니펫의 줄임말입니다.
class Sortable extends React.Component {
componentDidMount() {
this.$node = $(this.refs.sortable);
this.$node.sortable({
opacity: this.props.opacity,
change: (event, ui) => this.props.onChange(event, ui)
});
}
shouldComponentUpdate() { return false; }
componentWillReceiveProps(nextProps) {
if (nextProps.enable !== this.props.enable)
this.$node.sortable(nextProps.enable ? 'enable' : 'disable');
}
renderItems() {
return this.props.data.map( (item, i) =>
<li key={i} className="ui-state-default">
<span className="ui-icon ui-icon-arrowthick-2-n-s"></span>
{ item }
</li>
);
}
render() {
return (
<ul ref="sortable">
{ this.renderItems() }
</ul>
);
}
componentWillUnmount() {
this.$node.sortable('destroy');
}
};
선택적으로 기본 소품(전송되지 않은 경우)과 소품 유형을 설정할 수 있습니다.
Sortable.defaultProps = {
opacity: 1,
enable: true
};
Sortable.propTypes = {
opacity: React.PropTypes.number,
enable: React.PropTypes.bool,
onChange: React.PropTypes.func.isRequired
};
...또한 다음 사용방법을 나타냅니다.<Sortable />★★★★★★★★★★★★★★★★★★:
class MyComponent extends React.Component {
constructor(props) {
super(props);
// Use this flag to disable/enable the <Sortable />
this.state = { isEnabled: true };
this.toggleEnableability = this.toggleEnableability.bind(this);
}
toggleEnableability() {
this.setState({ isEnabled: ! this.state.isEnabled });
}
handleOnChange(event, ui) {
console.log('DOM changed!', event, ui);
}
render() {
const list = ['ReactJS', 'JSX', 'JavaScript', 'jQuery', 'jQuery UI'];
return (
<div>
<button type="button"
onClick={this.toggleEnableability}>
Toggle enable/disable
</button>
<Sortable
opacity={0.8}
data={list}
enable={this.state.isEnabled}
onChange={this.handleOnChange} />
</div>
);
}
}
ReactDOM.render(<MyComponent />, document.getElementById('app'));
상세설명
그 이유와 방법을 알고 싶은 분들을 위해스텝 바이 스텝 가이드를 다음에 나타냅니다.
1단계: 컴포넌트를 만듭니다.
는 항목의 배열.data
class Sortable extends React.Component {
componentDidMount() {
// Every React component has a function that exposes the
// underlying DOM node that it is wrapping. We can use that
// DOM node, pass it to jQuery and initialize the plugin.
// You'll find that many jQuery plugins follow this same pattern
// and you'll be able to pass the component DOM node to jQuery
// and call the plugin function.
// Get the DOM node and store the jQuery element reference
this.$node = $(this.refs.sortable);
// Initialize the jQuery UI functionality you need
// in this case, the Sortable: https://jqueryui.com/sortable/
this.$node.sortable();
}
// jQuery UI sortable expects a <ul> list with <li>s.
renderItems() {
return this.props.data.map( (item, i) =>
<li key={i} className="ui-state-default">
<span className="ui-icon ui-icon-arrowthick-2-n-s"></span>
{ item }
</li>
);
}
render() {
return (
<ul ref="sortable">
{ this.renderItems() }
</ul>
);
}
};
순서 2: 구성 옵션을 소품 경유로 전달
예를 들어 정렬 중에 도우미의 불투명도를 설정합니다.를 사용합니다.opacity 인 이 옵션은, 「」의 값을 합니다.0.01로로 합니다.1.
class Sortable extends React.Component {
// ... omitted for brevity
componentDidMount() {
this.$node = $(this.refs.sortable);
this.$node.sortable({
// Get the incoming `opacity` prop and use it in the plugin configuration
opacity: this.props.opacity,
});
}
// ... omitted for brevity
};
// Optional: set the default props, in case none are passed
Sortable.defaultProps = {
opacity: 1
};
코드의 컴포넌트를 사용할 수 있는 방법은 다음과 같습니다.
<Sortable opacity={0.8} />
마찬가지로 jQUERY UI Sortable 옵션을 매핑할 수 있습니다.
스텝 3: 플러그인 이벤트에 대한 연결 기능.
예를 들어 상태를 조작하는 등의 React 로직을 수행하기 위해 플러그인 메서드 중 일부를 연결해야 할 경우가 많습니다.
그 방법은 다음과 같습니다.
class Sortable extends React.Component {
// ... omitted for brevity
componentDidMount() {
this.$node = $(this.refs.sortable);
this.$node.sortable({
opacity: this.props.opacity,
// Get the incoming onChange function
// and invoke it on the Sortable `change` event
change: (event, ui) => this.props.onChange(event, ui)
});
}
// ... omitted for brevity
};
// Optional: set the prop types
Sortable.propTypes = {
onChange: React.PropTypes.func.isRequired
};
사용 방법은 다음과 같습니다.
<Sortable
opacity={0.8}
onChange={ (event, ui) => console.log('DOM changed!', event, ui) } />
순서 4: 향후 업데이트 제어를 jQuery에 넘깁니다.
ReactJS가 실제 DOM에 요소를 추가한 직후에 향후 컨트롤을 jQuery에 넘겨야 합니다.그렇지 않으면 리액트JS는 우리의 컴포넌트를 재렌더하지 않지만 우리는 그것을 원하지 않는다.우리는 jQuery가 모든 업데이트를 담당하기를 원합니다.
리액션 라이프 사이클 방법이 구조에 도움이 됩니다!
component Update()를 사용하여 컴포넌트의 출력이 현재 상태 또는 프로포트의 변화에 영향을 받지 않는지 여부를 React에 알립니다.기본 동작은 모든 상태 변경 및 대부분의 상태 변경에 대해 다시 렌더링하는 것이지만, 이 동작은 원하지 않습니다.
shouldComponentUpdate()렌더링 전에 새 소품 또는 상태를 수신할 때 호출됩니다. ifshouldComponentUpdate()false , , , 「 」componentWillUpdate(),render() , , , , 입니다.componentDidUpdate()호출되지 않습니다.
'우리'를 사용합니다.componentWillReceiveProps()this.propsnextPropsjQuery UI 입니다.jQuery UI Sortable을 활성화/비활성화합니다.
class Sortable extends React.Component {
// Force a single-render of the component,
// by returning false from shouldComponentUpdate ReactJS lifecycle hook.
// Right after ReactJS adds the element in the actual DOM,
// we need to pass the future control to jQuery.
// This way, ReactJS will never re-render our component,
// and jQuery will be responsible for all updates.
shouldComponentUpdate() {
return false;
}
componentWillReceiveProps(nextProps) {
// Each time when component receives new props,
// we should trigger refresh or perform anything else we need.
// For this example, we'll update only the enable/disable option,
// as soon as we receive a different value for this.props.enable
if (nextProps.enable !== this.props.enable) {
this.$node.sortable(nextProps.enable ? 'enable' : 'disable');
}
}
// ... omitted for brevity
};
// Optional: set the default props, in case none are passed
Sortable.defaultProps = {
enable: true
};
// Optional: set the prop types
Sortable.propTypes = {
enable: React.PropTypes.bool
};
5단계: 어지럽힌 것을 정리합니다.
많은 jQuery 플러그인은 더 이상 필요하지 않을 때 스스로 정리하는 메커니즘을 제공합니다.jQuery UI Sortable은 DOM 이벤트를 바인드 해제하고 파기하도록 플러그인에 지시하기 위해 트리거할 수 있는 이벤트를 제공합니다.리액트 라이프 사이클 메서드는 다시 구조 작업을 수행하며 컴포넌트를 마운트 해제했을 때 연결하기 위한 메커니즘을 제공합니다.
class Sortable extends React.Component {
// ... omitted for brevity
componentWillUnmount() {
// Clean up the mess when the component unmounts
this.$node.sortable('destroy');
}
// ... omitted for brevity
};
결론
jQuery 플러그인을 React로 래핑하는 것이 항상 최선의 선택은 아닙니다.단, 이것이 옵션이라는 것과 솔루션을 구현하는 방법에 대해 알게 되어 기쁩니다.레거시 jQuery 응용 프로그램을 React로 마이그레이션하거나 사용자의 필요에 맞는 React 플러그인을 찾을 수 없는 경우에 사용할 수 있는 옵션입니다.
라이브러리가 DOM을 변경할 경우 React를 방해하지 않도록 합니다.리액션은 DOM을 완전히 제어할 때 가장 잘 작동합니다.이 경우 React 컴포넌트는 서드파티 라이브러리의 래퍼에 가깝습니다.주로 componentDidMount/componentWillUnmount를 사용하여 서드파티 라이브러리를 초기화/파괴합니다.또한 자녀가 랩하는 서드파티 라이브러리의 동작을 커스터마이즈하고 플러그인 이벤트에 접속하는 방법을 부모에게 제공하는 소품입니다.
이 방법을 사용하여 거의 모든 jQuery 플러그인을 통합할 수 있습니다.
리액션은 DOM 돌연변이를 직접 실행하는 라이브러리에서는 잘 작동하지 않습니다.React가 렌더링하려고 하는 DOM을 다른 것으로 변환하면 오류가 발생합니다.이 작업을 수행해야 하는 경우 페이지의 다른 부분을 관리하도록 하는 것이 가장 좋습니다. 예를 들어 jquery 컴포넌트를 저장하는 div와 React 컴포넌트를 포함하는 다른 div가 있습니다.이러한 서로 다른 (질문과 반응) 컴포넌트 간의 커뮤니케이션은 어렵지만, 솔직히 둘 중 하나를 선택하는 것이 더 나을 수 있습니다.
Kayolan의 답변에는 기술적으로 결함이 없지만 IMHO라는 치명적인 결함이 있습니다. 즉, 향후 UI 업데이트에 대한 책임을 React에서 jQuery로 전가할 때, Kayolan은 애초에 React가 있다는 점을 부정했습니다.React는 정렬 가능한 목록의 초기 렌더링을 제어하지만, 그 이후에는 사용자가 첫 번째 jQueryUI 드래그/소트 작업을 수행하는 즉시 React의 상태 데이터가 오래됩니다.React의 요점은 보기 수준에서 상태 데이터를 표시하는 것입니다.
그래서 이 문제에 접근했을 때는 반대로 접근했습니다.나는 리액트가 가능한 한 통제력을 갖출 수 있도록 노력했다.jQueryUI Sortable 컨트롤은 DOM을 변경하지 않습니다.
게게어 떻떻?에는 jQuery-ui의 sortable()이 .cancel이 호출은 UI를 드래그 앤 드롭을 시작하기 전의 상태로 되돌립니다.이 방법은 정렬 가능한 컨트롤의 상태를 읽은 후 다음 명령을 발행하는 것입니다.cancel그렇게 하면 사용자의 의도가 무엇이었는지 알 수 있습니다.cancel【DOM】【DOM】이러한 의도가 있으면 React에 다시 전달하여 사용자가 원하는 새로운 순서로 상태 데이터를 조작할 수 있습니다.마지막으로 해당 데이터의 setState()를 호출하여 React가 새 순서를 렌더링하도록 합니다.
방법은 다음과 같습니다.
- jquery-ui.sortable() 메서드를 줄 항목 목록에 첨부합니다(물론 React에 의해 생성됨).
- 사용자가 DOM 주위에 이러한 라인 항목을 드래그 앤 드롭할 수 있습니다.
- 사용자가 드래그하기 시작하면 사용자가 드래그한 라인 항목의 인덱스를 읽습니다.
- 사용자가 라인 항목을 드롭하면 다음과 같이 처리됩니다.
- jQuery-ui.sortable()에서 행 항목의 새 인덱스 위치를 읽습니다(목록에서 사용자가 드롭한 위치).
- 를 건네다
canceljQuery-ui.sortable()은 DOM을 사용합니다. - 드래그 라인 항목의 이전 인덱스와 새 인덱스를 매개 변수로 React 모듈의 JavaScript 함수에 전달합니다.
- 해당 함수는 목록의 백엔드 상태 데이터를 사용자가 끌어다 놓은 새 순서로 정렬합니다.
setState()discl.discl.discl을 클릭합니다.
UI의 목록은 상태 데이터의 새로운 순서를 반영합니다.이것은 표준 리액트 기능입니다.
따라서 dom을 변경하지 않고 jQueryUI Sortable의 드래그 앤 드롭 기능을 사용할 수 있습니다.리액션은 만족합니다.DOM(필요한 장소)을 제어할 수 있기 때문입니다.
https://github.com/brownieboy/react-dragdrop-test-simple에 있는 Github 저장소의 예.여기에는 라이브 데모 링크가 포함됩니다.
jquery-ui npm 패키지가 작동하지 않았습니다.지금까지 효과가 있었던 것은 jquery-ui-bundle을 사용한 것입니다.
import $ from 'jquery';
import 'jquery-ui-bundle';
import 'jquery-ui-bundle/jquery-ui.min.css';
Kaloyan Kosev의 장황한 답변입니다만, 사용하는 모든 jQueryUi 기능에 대해 컴포넌트를 작성해야 합니까?됐어!DOM을 변경할 때 단순히 상태를 업데이트하지 그래요?Followig는 나에게 효과가 있다:
export default class Editor extends React.Component {
// ... constructor etc.
componentDidMount() {
this.initializeSortable();
}
initializeSortable() {
const that = this;
$('ul.sortable').sortable({
stop: function (event, ui) {
const usedListItem = ui.item;
const list = usedListItem.parent().children();
const orderedIds = [];
$.each(list, function () {
orderedIds.push($(this).attr('id'));
})
that.orderSortableListsInState(orderedIds);
}
});
}
orderSortableListsInState(orderedIds) {
// ... here you can sort the state of any list in your state tree
const orderedDetachedAttributes = this.orderListByIds(orderedIds, this.state.detachedAttributes);
if (orderedDetachedAttributes.length) {
this.state.detachedAttributes = orderedDetachedAttributes;
}
this.setState(this.state);
}
orderListByIds(ids, list) {
let orderedList = [];
for (let i = 0; i < ids.length; i++) {
let item = this.getItemById(ids[i], list);
if (typeof item === 'undefined') {
continue;
}
orderedList.push(item);
}
return orderedList;
}
getItemById(id, items) {
return items.find(item => (item.id === id));
}
// ... render etc.
}
목록 요소에는 jQuery가 요소를 선택하도록 하기 위한 추가 속성만 필요합니다.
import React from 'react';
export default class Attributes extends React.Component {
render() {
const attributes = this.props.attributes.map((attribute, i) => {
return (<li key={attribute.id} id={attribute.id}>{attribute.name}</li>);
});
return (
<ul className="sortable">
{attributes}
</ul>
);
}
}
ID의 경우 UUID를 사용하기 때문에 일치 시 충돌이 발생하지 않습니다.orderSortableListsInState().
useRef 또는 컴포넌트 ID 또는 클래스를 평소처럼 사용할 수 있습니다.
import { useRef, useEffect } from 'react';
import $ from 'jquery';
import "jquery-ui-dist/jquery-ui"
export default function YourComponent() {
const ref = useRef()
useEffect(() => {
$(ref.current).sortable({
items: '>li',
});
}, []);
return (
<ul ref={ref}>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
)
}
언급URL : https://stackoverflow.com/questions/38836553/how-to-use-jquery-ui-with-react-js
'codememo' 카테고리의 다른 글
| 검출되지 않은 오류:불변 위반: find ComponentRoot(......$110):요소를 찾을 수 없습니다.이것은 아마도 DOM이 예기치 않게 변환되었음을 의미합니다. (0) | 2023.04.03 |
|---|---|
| POST를 angularj로 전송하려면 어떻게 해야 하나요? (0) | 2023.03.29 |
| Oracle에서 테이블을 생성하기 전에 테이블 존재 여부를 확인합니다. (0) | 2023.03.29 |
| 각도 JS의 이중과 단일 곱슬 가새의 차이? (0) | 2023.03.29 |
| 클래스 A가 복수의 JSON 필드를 선언합니다. (0) | 2023.03.29 |