1. 원인 및 아이디어
저는 항상 네이티브 JS 드래그 앤 드롭 효과를 작성하고 싶었고 최근에는 React를 재미있게 배우고 있습니다. 그래서 나는 이 드래그 앤 드롭 효과를 얻기 위해 반응을 사용했습니다.
우선 드래그 효과의 아이디어는 사실 매우 간단합니다. 주로 세 가지 단계가 있습니다:
1. onmousedown일 때 드래그 가능한 이벤트를 시작하고 드래그된 요소의 원래 좌표 매개변수를 기록합니다.
2. onmousemove 시 마우스가 이동한 거리를 실시간으로 기록하고 드래그된 요소의 첫 번째 단계의 좌표 매개변수를 기반으로 새로운 좌표값을 계산하고 설정합니다.
3. onmouseup 시 드래그 가능한 이벤트를 닫고 새 좌표값을 기록합니다.
참고: 요소의 위치는 주로 상단과 왼쪽의 절대 위치에 의해 결정되므로 드래그된 요소의 CSS를 절대 위치로 설정해야 합니다.
2. 보조 도구
보조 도구는 주로 개발 프로세스를 효율적이고 멋지게 만듭니다. 이 데모에서는 Gulp에 많은 기능이 있는 gulp+browser-sync 개발 도구를 추천하고 싶습니다. 이 데모에서 gulp의 주요 기능은 물론 jsx 파일의 실시간 컴파일을 설정하는 것입니다. , css를 작성하면 sass이고, sass의 실시간 컴파일도 설정할 수 있습니다. browser-sync를 사용하면 실시간으로 자동으로 페이지를 새로고침하는 것이 가장 중요합니다. 우리는 평소에 페이지를 만들고 효과를 볼 때 보통 F5를 통해 브라우저를 새로고침한 후 페이지를 봅니다. 하지만 이 플러그인을 사용하면 코드 작성을 마친 후 Ctrl+S를 눌러 저장하면 새 효과가 브라우저에서 자동으로 새로 고쳐져 볼 수 있습니다.
자세한 사용법 설명:
설치:
1. 노드 환경에 gulp를 설치합니다. 구체적인 프로세스는 제 블로그 게시물 "React.js를 시작하기 위해 알아야 할 사항"을 참조하세요.
2. gulp-livereload를 설치하려면 명령줄이나 git bash에서 npm install --save-dev gulp-livereload를 입력하세요
3. 명령줄이나 git bash에서 gulp-watch를 설치하고 npm install --save-dev gulp-watch를 입력하세요
4. browser-sync를 설치하려면 명령줄이나 git bash에서 npm install --save-dev browser-sync를 입력하세요
구성 및 설명은 그림과 같습니다.
3. 컴포넌트 구성 페이지 정의
참고: 여기에 나와 있는 코드 지침은 모두 React 관련 모듈을 설치한 후의 내용입니다. 설치 과정은 제 블로그 게시물 "react.js를 시작하기 위해 알아야 할 사항"을 참조하세요.
렌더링:
구성요소 분할 아이디어:
컴포넌트를 더 작은 부분으로 나누는 것이 더 낫다고 생각하여 입력과 버튼을 각각 하나의 컴포넌트로 만들었습니다.
var React=require('react'); var MyInput=React.createClass({ render:function(){ return ( <div className="form-group"> <label htmlFor={this.props.labelId} className="col-sm-2 control-label{this.props.labelTip</label> <div className="col-sm-10"> <input name={this.props.name} type={this.props.type} onChange={this.props.onChange} className="form-control" id={this.props.labelId} placeholder={this.props.placeholder}/> </div> </div> ); } }); module.exports=MyInput;
var React=require('react'); var Button=React.createClass({ render:function(){ return ( <button type={this.props.type} className="loginButton">{this.props.ButtonTip}</button> ); } }) module.exports=Button;
지정해야 할 입력이 많기 때문에 이 경우 저처럼 정의하면 너무 많은 매개변수를 전달해야 하고, 실제로 로그인한 입력은 대부분 고정되어 있어서 그럴 필요가 없습니다. 재사용하는 것은 실제로 좋은 생각이 아닙니다. 여기에 직접 입력을 작성하는 것이 좋습니다.
작성 후 상위 구성요소:
render:function(){ return ( <form className="form-horizontal" id="form" ref="dragBox" onSubmit={this.submitHandler} onMouseMove={this.move} onMouseUp={this.endDrag}> <DragArea callbackParent={this.onChildChanged} /> <div id="form-wrap"> <MyInput name="username" labelId={"userId"} labelTip={"用户名"} type={"text"} placeholder={"请输入用户名"} value={this.state.username} onChange={this.handleChange}/> <MyInput name="password" labelId={"pw"} labelTip={"密码"} type={"password"} placeholder={"请输入密码"} value={this.state.password} onChange={this.handleChange}/> <div className="form-group"> <div className="col-sm-offset-2 col-sm-10"> <div className="checkbox"> <label> <input name="checked" type="checkbox" checked={this.state.checked} onChange={this.handleChange} /> 记住我 </label> </div> </div> </div> <MyButton type={"submit"} ButtonTip={"登陆"}/> </div> </form> );
참고: 데모에서는 실제 DOM 노드를 얻어야 하므로 ref가 정의됩니다.
CSS 스타일을 추가하면 페이지가 완성됩니다! 마지막으로 여기서 요점이 나옵니다! ! !
4. 드래그 앤 드롭을 구현하기 위한 상위 구성요소와 하위 구성요소 간의 통신
참고: 제가 달성하려는 효과는 하위 구성 요소 DragArea에서 마우스를 누르면 전체 양식이 드래그되므로 DragArea가 드래그를 시작하고 양식이 응답하는 것입니다. 따라서 처음에는 상위 구성 요소의 일부 상태 속성을 하위 구성 요소에 전달해야 합니다. 그런 다음 DragArea에서 마우스를 눌렀을 때 하위 구성 요소 DragArea를 통해 상위 구성 요소의 원래 좌표 매개 변수를 찾아야 합니다. 상위 구성 요소의 상태 속성을 업데이트해야 하며 상위 구성 요소에 드래그가 가능함을 알려줍니다. 상위 구성 요소에서 하위 구성 요소로 전달된 매개 변수는 직접 전달됩니다. 하위 구성 요소는 매개 변수를 상위 구성 요소에 전달하기 위해 이벤트를 전달해야 합니다. 따라서 상위 구성 요소에 이러한 기능을 정의하십시오.
onChildChanged:function(newState){ //因为参数过多,所以把参数放到对象里面,通过对象来传 this.setState(newState); },
하위 구성 요소는 위 코드와 같이 이 함수를 바인딩해야 합니다. callbackParent={this.onChildChanged}
하위 구성 요소의 응답 기능은 다음과 같습니다.
startDrag:function(e){ var dragBox=document.getElementById('form'); var newState={}; var event=e||window.event; event.preventDefault(); var computedStyle=document.defaultView.getComputedStyle(dragBox,null); newState.left=computedStyle.left; newState.top=computedStyle.top; newState.currentX=event.clientX; newState.currentY=event.clientY; newState.flag=true; <span style="color: #0000ff;"> this.props.callbackParent(newState);</span> }
이러한 방식으로 하위 구성 요소에서 드래그 스위치가 활성화되고 from의 관련 매개 변수 from, move 및 endDrag가 업데이트되었습니다.
move:function(event){ var e = event ? event : window.event; //兼容IE的写法 if (this.state.flag) { var nowX = e.clientX, nowY = e.clientY; var disX = nowX - this.state.currentX, disY = nowY - this.state.currentY; ReactDOM.findDOMNode(this.refs.dragBox).style.left = parseInt(this.state.left) + disX + "px"; ReactDOM.findDOMNode(this.refs.dragBox).style.top = parseInt(this.state.top) + disY + "px"; } }, endDrag:function(){ var computedStyle=document.defaultView.getComputedStyle(ReactDOM.findDOMNode(this.refs.dragBox),null); this.setState({ left:computedStyle.left, top:computedStyle.top, flag:false }); }
Pada ketika ini, seret dan lepas dilaksanakan!
5. Refleksi
1. Secara teorinya, kesan seretan boleh direalisasikan dalam mana-mana elemen, dan idea seret adalah sama, jadi secara teorinya, fungsi setiap proses seretan boleh diekstrak dan dijadikan Mixin, dan kemudian Boleh dipanggil berulang kali. Ini adalah idea awal saya, tetapi saya sentiasa membuat kesilapan apabila menghantar parameter, bertindak balas dan elemen mengikat. Selepas mencari maklumat, saya tidak dapat mencari maklumat tentang kaedah penulisan mudah bertindak balas dan seret dan lepas Hanya terdapat beberapa pemalam khas untuk bertindak balas, dan ia ditulis dalam ES6 saya tidak dapat memahaminya tahap. Jadi saya tinggalkan cara penulisan ini buat sementara waktu. Saya harap pakar yang mempunyai idea yang berkaitan boleh berkongsi dengan saya.
2. Apabila subkomponen dalam artikel memperoleh parameter daripada, ia menggunakan var dragBox=document.getElementById('form'); Tetapi saya tidak begitu biasa dengan cara mendapatkan dom komponen induk daripada komponen anak. Saya telah cuba mentakrifkan refs=this.refs.dragBox dalam komponen induk. Kemudian ia dihantar kepada sub-komponen, tetapi saya tidak tahu mengapa penyemak imbas terus melaporkan ralat yang mengatakan bahawa ini bukan nod dom. Minta petunjuk kepada Allah.
3. Cara umum untuk menulis peristiwa seret dan lepas adalah dengan mentakrifkan peristiwa pergerakan tetikus dan naik tetikus pada dokumen, tetapi kedua-dua peristiwa ini dikaitkan dengan parameter daripada dari , saya tidak dapat menjejaki parameter yang berkaitan. Jadi saya mentakrifkannya dari. Adakah terdapat cara yang lebih baik? Sila kongsi!
4. Revolusi masih belum berjaya, rakan-rakan masih perlu bekerja keras!
Demo ini telah dimuat naik ke: https://github.com/LuckyWinty/dragDemo
Di atas adalah keseluruhan kandungan artikel ini, saya harap ia akan membantu kajian semua orang.