Thinking _javascript technique based on react.js to realize the effect of native JS dragging and dragging

Source: Internet
Author: User
Tags button type

First, cause & thinking

Always want to write a native JS drag-and-drop effect, coupled with the recent study react to learn more hi. So we use react to achieve this drag-and-drop effect.

First of all, in fact, the idea of drag-and-drop effect is very simple. There are three main steps:

1.onmousedown, start the drag-and-drop event, recording the original coordinate parameters of the dragged element.

2.onmousemove, real-time record the distance of the mouse movement, combined with the first phase of the drag element coordinate parameters, calculate and set a new coordinate value.

3.onmouseup, turn off drag-and-drop events and record new coordinate values.

Note: This is mainly through the absolute positioning of the top and left to determine the location of the elements, so the dragged elements of the CSS must set absolute positioning.

Second, auxiliary tools

The main thing about assistive tools is that the development process becomes efficient and cool. In this demo, to recommend a Gulp+browser-sync development tool, Gulp has a lot of functions, in this demo gulp role is to set up real-time compilation react JSX files, of course, if you write CSS with sass, You can also set up Just-in-time compilation sass. With Browser-sync This, the main is to automatically refresh the page in real time, we usually do the page, see the effect of the time, usually through the F5 to refresh the browser, and then see the page. But with this plug-in, you write the code, as long as the press, Ctrl+s save, the new effect will automatically refresh in the browser, and then see.

Usage Detailed:

Installation:

1. In node environment, the installation of Gulp, here is not known, the specific process can refer to my blog "React.js Getting started must know those things"

2. Install Gulp-livereload, at the command line or git bash, enter npm install--save-dev gulp-livereload

3. Install Gulp-watch, at the command line or git bash, enter npm install--save-dev Gulp-watch

4. Install Browser-sync, at the command line or git bash, enter npm install--save-dev Browser-sync

Configuration and interpretation as shown:

Iii. Defining component Build Pages

Note: Here the code description is in the React related modules installed in the case, the installation process to see my blog "React.js Getting started must know those things."

Effect Chart:

Component Split idea:

I thought the component was split a little bit better, so I made a component of input and button, respectively:

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;

Because the input has a lot of need to specify, in this case, if like me to define the need to pass too many parameters, and in fact, the landing of the input is mostly fixed and no need to reuse, so this is not really good. Here the input directly write better.

Parent component after writing:

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={"username"} type={"text"} placeholder={ Please enter the username "} value={this.state.username} onchange={this.handlechange}/> <myinput name=" password "labelId={" PW "} labeltip={"Password"} type={"password"} placeholder={"Please enter password"} Value={this.state.password > <div classname= "Form-group" > <div classname= "col-sm-offset-2 col-sm-10" > <div className= "Checkbo X "> <label> <input name=" checked "type=" checkbox "checked={this.state.checked} onchange={  This.handlechange}/> Remember me </label> </div> </div> </div> <mybutton type={"Submit"}
 buttontip={"Landing"}/> </div> </form>);

Note: REF is defined because the demo needs to get a real DOM node.

Plus CSS style, the page is complete! Finally, the emphasis is coming!!!

Iv. communication implementation between parent-child components drag-and-drop

Description: Because I want to achieve the effect is that the mouse hold the subassembly dragarea, drag the entire form, so start dragging is dragarea, and response is form. So, at first you have to pass some state attributes of the parent component to the subassembly, and then when the mouse presses the Dragarea, you must find the parent component's original coordinate parameter through the subassembly Dragarea, then update the state attribute inside the parent component and tell the parent component to drag. The parent component is passed directly by passing the parameter to the subassembly. The child component passes the event to the parent component. So define a function in the parent component:

Onchildchanged:function (newstate) {//Because there are too many arguments, put the arguments inside the object, passing the object to the
  this.setstate (newstate);
},

And the subassembly needs to bind this function, like the code above: callbackparent={this.onchildchanged}

In a subassembly, the function of the response is:

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>
}

In this way, the drag-and-drop switch is started in the subassembly, and the associated parameters of from are updated, with two events from the two outside, move and EndDrag respectively:

Move:function (event) {
  var e = event? event:window.event;//compatible with IE
  if (this.state.flag) {
    var nowx = E.clie NtX, 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
  });

So far, drag and drop implementation!

V. Review of Reflection

1. Theoretically, drag-and-drop effects can be implemented in any element, the idea of drag and drop are consistent, so theoretically, the function of dragging and dropping each process can be drawn out, made a mixin, and can be called repeatedly. That's the way I started, but there's always an error in the arguments, responses, and binding elements. Look up the information, did not find react and drag the simple writing data, only some react special plug-ins, but also with the ES6, because the level has not been able to understand. So I gave up the wording for the time being. I hope the great gods who have related ideas will communicate with me.

2. When the neutron component acquires the parameter from, the Var Dragbox=document.getelementbyid (' form ') is used; To find DOM, it seems to violate some of react's ideas. But I'm not quite familiar with how to get the DOM of a parent component from a subassembly. I have tried to define Refs=this.refs.dragbox in the parent component. It is then passed to the subassembly, but I don't know why the browser keeps the error saying this is not a DOM node. Ask the great God for advice.

3. The general wording of the drag-and-drop event is to define the MouseMove and MouseUp events on the document, but both events are associated with the from parameter, so that if I define the document in react, I cannot trace the relevant parameter. So I'm going to define it from the top. Is there a better way to do it? Please share!

4. The revolution has not yet succeeded, comrades still need to work hard!

This demo has been uploaded to: Https://github.com/LuckyWinty/dragDemo

The above is the entire content of this article, I hope to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.