1. Some insights on technical development

What is the use of learning various design patterns?

“Development”

High development efficiency

Good for teamwork

“Maintenance”

Facilitate code upgrade changes

Clear logic, rigorous code, conducive to later maintenance

“General”

We rely on design pattern can realize componentization, modularization, plug-in, framework and some common class library method writing

Technical language development route

The way to update and iterate language syntax

Initial stabilization of syntax -> early people who study core syntax and usage -> encapsulating various libraries and plug-ins -> lots of developers who study core… -> Various design patterns appear -> frameworks (VUE, REACT)

2, class library, component, plug-in, framework four differences

Class library: provides some common methods in real project development (methods made perfect processing: compatibility processing, detail optimization), convenient for us to develop and maintain [jQuery, Zepto…]

Plug-in: Package a part of the project into a plug-in (it has specific business logic and is more targeted), and import the plug-in directly in the future if there is a similar demand. Jquery.drag.js, jquery.dialog.js, jquery.validate.min.js, datepicker calendar plugin, echarts statistics plugin, iscroll plugin…

Components: It is similar to plug-ins, but plug-ins generally only encapsulate THE JS part. Components not only encapsulate the JS part, but also the CSS part. When we use it in the future, we directly introduce CSS/JS according to the usage instructions of the document to build the corresponding structure. Swiper, bootstrap, swiper, swiper, bootstrap

Framework: Larger than the above three, not only does it provide a lot of common methods, but it also supports extension of some plug-ins (you can integrate some plug-ins into the framework to run), and more importantly, it provides excellent code management design ideas… REACT VUE ANGULAR REACT NATIVE

3. Design patterns commonly used in JS

Singleton design pattern, Construct prototype design pattern, publish and subscribe design pattern, Promise design pattern…

Singleton design pattern

// exampleRender=(); // exampleRender=();function(){// the idea of js inertia is to create an undestructible private scope through closures.let fn=function(){
5.        //...
6.    }
7.
8.    return {
9.        init:function(){10. //=> entry method: control the specific business logic sequence of the current module 11.fn (); 12.} 13.} 14.})(); 15.exampleRender.init();Copy the code

In real projects, if we want to achieve specific business logic requirements, we can rely on the singleton pattern construction; We divide the project into blocks or modules (modular development), and put the method of implementing the same block in a separate namespace to facilitate team collaboration.

Construct a prototype pattern: The closest thing to OOP object-oriented programming ideas

Future real projects, whether encapsulated libraries or plug-ins or UI components (with existing styles and structures), are basically based on the construction of prototype patterns

1. Class Tool{// Create a Tool class to store public method 2.constructor(){// Put all private things in the constructor where this is an instance of the current Tool method 3. this.iscompatible ='addEventListener' indocument; //=> If incompatible, return FALSE(IE6 to 8) // Verify IE6 to 8 compatibility: GetComputedStyle, GetelementByClassName, addEventListener, etc. 4. 5.} 6. //=> Methods that can be called by method instances mounted to the prototype 7.css() {8. / /... } 10. //=> Mount methods to common objects 11. Staticdistinct() {12. / /... } 15. 16. Class Banner extends Tool{//Banner extends Tool 17. arg){ //... Arg: all arguments received by the current Banner class 18.super (... arg); //es6 inheritance must write super... Arg: pass the parameters received by the current Banner to super 19.this. XXX = XXX; // Add private attribute 20.} 21. //=> method 22 mounted to the subclass prototype.bindData(){this.css() {this.css() {this.css() {this.css() {this.css(); This. Distinct ===undefined; //=> execute a method from a parent class. //=> An instance of a subclass can only call methods on the parent class's prototype, and private attribute methods provided by the parent class to the instance. However, a static method added by the parent class as an ordinary object cannot be called by an instance of a subclass. Tool.distinct()) 25. } 26.} // new Banner()Copy the code

There are usually many classes in a plug-in. For example, there are five classes, four of which are utility classes (providing some common methods), and only the last class is the implementation of the specific business logic, so the last class needs to inherit all the previous classes. How can a class inherit multiple classes? As follows:

I have three classes A/B/C, and I want C to inherit from A and B

1. Class A{2.... 3.} 4. Class B extends A{// Class B extends A{// Class B extends A{5.... 6. Extends {B} 7. Class C/B/C inheritance, you can use C B provides A private property and prototype method can C B, can use A, B C can B and A 8.... 9.}Copy the code

Publish subscribe design pattern: Observer pattern

Unlike singletons and constructs, publish-and-subscribe design patterns are small design patterns that apply to a specific requirement: we can rely on publish-and-subscribe design patterns to manage and plan our JS code whenever there are N methods that need to be executed after a certain condition is reached

We often nest publish/subscribe design patterns into other design patterns

Promise design pattern

Synchronization can be hierarchically nested (completion of A before completion of B), but asynchro cannot hierarchically nested (because A executes B before completion).

Solve AJAX asynchronous request hierarchy nesting

It is also a small design pattern designed to solve the problem of hierarchical nesting, and we will often run it nested within other design patterns

1.$.ajax({
2.    url:'/A',
3.    async:true,//=> asyncfunction(result){
5.        $.ajax({
6.            url:'/B',
7.            async:true,
8.            success:function(){9. //=> there will be a follow-up nesting after the nesting will be messy and difficult to manage 10. 13. 12.}});Copy the code

In the project, if you master the design pattern, you will discover the function or method to realize a certain module or a certain area, and eventually use n multiple design patterns to jointly develop the project (single column, publish and subscribe, and promise may be combined to complete a function).

The common design patterns are basically these four, and there are many more

4. Core ideas of publish and subscribe design pattern

It’s colloquially called the observer model.

Implementation ideas and principles:

1. Let’s create a schedule (container)

2. What do we need to do in the later stage

3. When a condition is met, we just need to notify the methods in the schedule to execute in sequence

1- Publish subscribe. HTML

<! DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <! -- <script src="js/animate.min.js"></script> -->
<script src="js/animate.js"></script>
<script>

    
    let fn1 = function () {
        console.log(1);
    };
    
    let fn2 = function () {
        console.log(2);
    };
    
    let fn3 = function() { console.log(3); }; Animate ({curEle: document.body, target: {opacity: 0.2}, duration: 1000, callBack:fn1}); animate({curEle: document.body, target: {opacity: 0.2}, duration: 1000, callBack:fn1}); / / -- -- -- -- -- -- -- -- the above animation execution can only perform the fn1, now want to executed after three methods can all animation -- -- -- -- -- -- -- / / -- -- -- -- -- -- -- -- executed after three methods can all animation -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --let fn1 = function () {
        console.log(1);
    };
    
    let fn2 = function () {
        console.log(2);
    };
    
    let fn3 = function() { console.log(3); }; Animate ({curEle: document. Body, target: {opacity: 0.2}, duration: 1000, callBack: animate({curEle: document. Body, target: {opacity: 0.2}, duration: 1000, callBack:function(){ fn1(); fn2(); fn3(); }}); Late / / but it's not convenient to maintenance, the callback function with a layer of more nested function, and if you don't need to perform the functions on the callback function / / only three, it is not convenient maintenance (it must end need to be performed after the completion of the current animation methods are written), / / so you need to use subscriptions to solve, // Publish and subscribe / / 1, we first create a schedule (containers) / / 2 late, need to do something, all of us in turn to deal with things added to the schedule / / 3, when the accord with a condition, we only need to inform the schedule of the method according to the order can be executed in sequence / / publish-subscribe compatible with dom2 events pool thoughts like: / / 1, to create a fake event pool, / / 2, all click time needs to be done through on one by one in the first event in the pool but no execution, when to click on to perform, but click / / how much you need to perform a method does not know when, but it doesn't matter, want to execute many methods through on to false events in the pool, / / 3, when click the run way let run method method is executed in sequence in a pool of events / / -- -- -- -- -- publish-subscribe ideas to achieve the above code -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --letplan = []; // Container schedulelet fn1 = function() { console.log(1); }; plan.push(fn1); // We don't know how many methods we need to execute. We need to execute one method to push it into the containerlet fn2 = function() { console.log(2); }; plan.push(fn2); Animate ({curEle: document. Body, target: {opacity: 0.2}, duration: 1000}); animate({curEle: document. Body, target: {opacity: 0.2}, duration: 1000}); / /... Lots and lots of code......let fn3 = function() { console.log(3); }; plan.push(fn3); </script> </body> </ HTML > </script> </body>Copy the code

5. Publish and subscribe in JQ

Publish and subscribe if you can, it’s very convenient for code management and design management throughout the project

For example, the previous animation, after the animation is done, what can be done by publishing subscriptions

Drag and drop, you want to do something extra when you press, you want to do something extra when you move, you want to do something extra when you release, you can also create a container schedule by publishing a subscription

And then there’s the TAB, and when you press it you not only switch, but you want to do something else, and you can manage that by publishing and subscribing

Publish and subscribe is a very common way to do this when you want to execute not just one method but many other methods under certain conditions

Publish subscriptions in JQ

JQ provides a way to implement the publish-subscribe design pattern

1.let $plan= $.Callbacks(); // create a list of Callbacks. Publish and subscribe is a collection of Callbacks (create a list of things to do when a condition // triggers successfully.) 2function(n,m){
4.    //=>n=100 m=200
5.}
6.$plan.add(fn); //=> Add method 7 to the schedule.$plan.remove(fn); //=> Remove method 8.9 from the schedule.$planThe fire (100200); //=> All methods in the notification schedule are executed in sequence; 100 and 200 are passed as arguments to each method that needs to be executed;Copy the code

As an example

<! DOCTYPE html> <html> <head> <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script src="Js/jquery - 1.11.3. Min. Js." "></script>
<script>
    let $plan = $.Callbacks();
    $plan.add(function () {
        console.log(1);
    });

    setTimeout($plan.fire, 1000); // Execute the fire method after one second$plan// The left and right methods are implemented in sequence. What other methods will be saved in the later stage$plan.add(function () {
        console.log(2);
    });
</script>
</body>
</html>
Copy the code

6. Encapsulate your own library of publish and subscribe patterns

Encapsulate a library of publish subscribe patterns similar to JQ

Constructor based encapsulation

2. Simulate the operation steps of JQ

3. Pay attention to array collapse

4, encapsulate EACH item in EACH traversal number group

WEEK6-DAY4-js-callbacks-3-CALLBACKS.html

<! DOCTYPE html> <html> <head> <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script src="js/callbacks-backup.js"></script>
</body>
</html>
Copy the code

WEEK6-DAY4-js-callbacks-backup.js

~function() {//=>EACH: iterate over the contents of EACH item in the group,forEach is not compatible, encapsulate each method (projects usually encapsulate their own each loop)let each = function (ary, callBack) {
        for (let i = 0; i < ary.length; i++) {
            letresult = callBack && callBack(ary[i], i); // Execute the callback and receive the result of the callback function // if FALSE is returned in the callback function, it terminates the operation that is currently being iterated over (modeled after the EACH syntax in JQ).if (result === false) break; If DEL is returned in the callback function, it means that the current item is removed from the callback function. In order to prevent the collapse of the array, we decrement the index.if (result === 'DEL') i--; }}; / / each ([12, 10],function(item,index){//item: current traversal object index: current traversal object index //return false; // return from the callback functionfalse
    // });

    class Plan {
        constructor() {//Plan constructor this.planList = []; // add(fn) {// add(fn) {let planList = this.planList,
                flag = true; //=> reprocess the method that has been added to it.function (item, index) {

                // if(item === fn){
                //     return false; // Write this like thisreturn false// it will just end the current each loop, and it will continue, executing the push of the add method, so flag it.if (item === fn) flag = false;
                return flag;
            });
            flag ? planList.push(fn) : null;
        }

        remove(fn) {
            let planList = this.planList;
            each(planList, function (item, index) {
                if(item === fn) { //planList.splice(index, 1); PlanList [index] = null; planList[index] = null; //=> The position is present, but the value is notreturn false; }}); } fire(... Arg) {// The argument passed in to fire is equivalent to each method in the container receiving the value of the argument. The rest of the operators get the value and write all the arguments passed to fire into arg, which is an arraylet planList = this.planList;
            each(planList, function (item, index) {
                if(item === null) {//=> The current item is planlist.splice (index, 1); // Delete in the callback function has no effect on eachforIn the loop I will continue ++, and fn2 will be skipped. // So we need to decrement the index in each to prevent array collapsereturn 'DEL'; // Special processing can only be done with the return value (an identifier is returned) (callbak in each receives this return identifier for special processing)} item(... arg); Pieces / / operator to the item and execute (item is required to perform method) is equivalent to the item. The apply (null, [100200300]) (item can't pass an array can only a a transfer)}); } //=> Static properties and methods mounted to the PLAN objectCallbacks() {
            returnnew Plan(); Callbacks() return the Plan instance before the add, remove, and fire methods on the prototype can be called. // New Plan(): execute the Plan method. Constructor (); new Plan() not only creates the paln instance, // Also execute the constructor method, which creates a container planList (but this container can be used in the other three methods), so this container needs to be placed on the paln instance. } } window.$ = window.Plan = Plan; } (); // $.Callbacks(); //$:plan is equivalent to plan.callbacks (): it is equivalent to setting Callbacks() on plan as an objectlet $plan= Plan.Callbacks(); // Executing Callbacks() in JQ creates a schedule // // console.log($plan);
// $plan.add();
// $plan.remove();
// $planThe fire (100200300); // Take a quizlet plan1 = $.Callbacks();

// console.dir(plan1);

let fn1 = function () {
    console.log(1,arguments);
}
plan1.add(fn1);

let fn2 = function () {
    console.log(2,arguments);
}
plan1.add(fn2);

let fn3 = function () {
    console.log(3);
    plan1.remove(fn1);
    plan1.remove(fn2);
}
plan1.add(fn3);

let fn4 = function() { console.log(4); } plan1.add(fn4); Plan1. The fire (100200);Copy the code

An array of collapse

A bug in the each method can also cause arrays to collapse

This can cause array collapse in many cases. Dom2 compatibility processing and encapsulating publish-subscribe libraries have been encountered.

A collapse is caused by looping in one method and dropping an array item in another, for example:

The same is true of the callback function, which loops through an array in the current each method and deletes an item from the array

When I write a for loop array, I delete one of the array items in another function without doing I –, the next loop will collapse

It is important to avoid array collapse when iterating through arrays

WEEK6-DAY4-js-callbacks.js

~function() {//=>EACH: iterate over the contents of EACH item in the number grouplet each = function (ary, callBack) {
        for (let i = 0; i < ary.length; i++) {
            let result = callBack && callBack(ary[i], i);
            if (result === false) break;
            if (result === 'DEL') i--; }}; class Plan {constructor() { this.planList = []; } //=> mount the PLAN prototype method add(fn) {let planList = this.planList,
                flag = true;
            each(planList, function (item, index) {
                if (item === fn) flag = false;
                return flag;
            });
            flag ? planList.push(fn) : null;
        }

        remove(fn) {
            let planList = this.planList;
            each(planList, function (item, index) {
                if (item === fn) {
                    planList[index] = null;
                    return false;
                }
            });
        }

        fire(...arg) {
            let planList = this.planList;
            each(planList, function (item, index) {
                if (item === null) {
                    planList.splice(index, 1);
                    return 'DEL'; } item(... arg); }); } //=> Static properties and methods mounted to the PLAN objectCallbacks() {
            returnnew Plan(); } } window.$ = window.Plan = Plan; } ();Copy the code

7. Build my first plug-in – drag and drop plug-in, which can support later expansion

The core of the drag theme is mousedown, Mousemove, mouseup, but at each stage there may be something else to do (many things to do, not to do, or just one thing to do), and a similar need (to do more than one thing is not certain) can be addressed through callbacks. However, the callback function can only pass one, and our publish-subscribe model fits this requirement perfectly. We throw things (methods) in the schedule that need to be done by firing the events in the schedule when each phase needs to be executed

Publish and subscribe can be fused into any case column, with strong scalability

Encapsulates a drag and drop library that uses publish subscriptions, event pooling, each, BIND compatibility handling, and so on

WEEK6-DAY4-4-DRAG.html

<! DOCTYPE html> <html> <head> <meta charset="UTF-8"</title> <link rel="stylesheet" href="css/reset.min.css">
    <style>
        html, body {
            height: 100%;
            overflow: hidden;
        }

        .container {
            position: relative;
            margin: 20px auto;
            width: 500px;
            height: 500px;
            border: 1px solid green;
        }

        .box {
            position: absolute;
            width: 100px;
            height: 100px;
            background: red;
            cursor: move;
        }
    </style>
</head>
<body>
<div class="container">
    <div class="box" id="box"></div>
</div>


<script src="js/drag.js"></script>
<script>
    lettemp = Drag.init(box); //<=> new Drag(box) // Press to change orange temp.plandown.add (function(dragExp) {/ / by adding dragExp approach is to add to the schedule by this passed instances of drag by dragExp. CurEle for current drag and drop the element dragExp. CurEle. The style.css. Background ='orange'; }); // Lift the red temp. Planup.add (function (dragExp) {
        dragExp.curEle.style.background = 'red'; }); // Mouse up to make the current drag element in free fall press down to clear timer temp.plandown.add (function (dragExp) {
        let curEle = dragExp.curEle;
        clearInterval(curEle.dropTimer);
    });
    temp.planUp.add(function (dragExp) {
        letcurEle = dragExp.curEle; //dragExp is the drag instance passed through this. The dragexp. curEle gets the element being draggedletSpeed = 10,// speed flag = 0; // Clear curele. dropTimer = when flag is greater than 1setInterval(function () {
            if (flag > 1) {
                clearInterval(curEle.dropTimer);
                return; } speed += 10; Speed * = 0.98; // Let the speed decreaselet curT = curEle.offsetTop + speed;
            if(curT >= dragexp. maxT) {// If maxT is mounted to the instance maxL attribute in drag.js, curT = dragexp. maxT; speed *= -1; // flag++; }else {
                flag = 0;
            }
            curEle.style.top = curT + 'px'; }, 17); }); </script> </body> </ HTML > </script> </body>Copy the code

WEEK6-DAY4-js-drag.js

//=>EACH: iterates over the contents of EACH item in the number grouplet each = function (ary, callBack) {
    if(! (ary instanceof Array))return; // Each is not executed if ary is not an arrayfor (let i = 0; i < ary.length; i++) {
        let result = callBack && callBack(ary[i], i);
        if (result === false) break;
        if (result === 'DEL') i--; }}; / / = > BIND: compatible processing, change the Function of THIS in advance. The prototype. MyBind =functionmyBind(context = window, ... outer) {if ('bind' in this) {
        returnthis.bind(... arguments); }return(... inner)=> this.apply(context, outer.concat(inner)); }; //=> Part 1: Encapsulate event pool ~ based on DOM2 event binding libraryfunction () {
    class EventLibrary {
        on(curEle, type, fn) {//=>this:exampleif (typeof curEle['pond' + type= = ='undefined') {
                curEle['pond' + type] = []; // Create an event poollet_run = this.run; AddEventListener: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent: attachEvent'addEventListener' in document ? curEle.addEventListener(type, _run, false) : curEle.attachEvent('on' + type.function(e) { _run.call(curEle, e); // curEle.attachEvent('on' + type// So curele.attachevent ()'on' + type.function(e) {_run.call(curEle, e); }); }let ary = curEle['pond' + type],
                flag = true; Each (ary, (item, index)=> {// Traverses the event pool to determine whether there is already a method that needs to be added to the event pool.if (item === fn) flag = false;
                return flag;
            });
            flag ? ary.push(fn) : null;
        }

        off(curEle, type, fn) {
            let ary = curEle['pond' + type]; Each (ary, (item, index)=> {// Iterate through the event pool to remove the current eventif(item === fn) { ary[index] = null; }}); } the run (e) {/ / = > this: curEle current element, binding in on already processed into the current element e = e | | window. The event;if(! E.target) {// Handle compatibility issues with event object e. e.pageX = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft); e.pageY = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop); e.which = e.keyCode; e.preventDefault =function () {
                    e.returnValue = false;
                };
                e.stopPropagation = function () {
                    e.cancelBubble = true;
                };
            }

            let ary = this['pond'+ e.type]; Each (ary, (item, index)=> {// Executes the function passed in through the event pool and makes this refer to the current elementif (item === null) {
                    ary.splice(index, 1);
                    return 'DEL'; } item.call(this, e); // make this refer to the current element}); } } window.EventLibrary = EventLibrary; } (); // Execute the methods in EventLibrary: //let ev = new EventLibrary();
// ev.on(document.body,'click',fn1); //=> Part 2: Publish the subscription library ~function () {
    class Plan {
        constructor() {
            this.planList = [];
        }

        add(fn) {
            let planList = this.planList,
                flag = true;
            each(planList, function (item, index) {
                if (item === fn) flag = false;
                return flag;
            });
            flag ? planList.push(fn) : null;
        }

        remove(fn) {
            let planList = this.planList;
            each(planList, function (item, index) {
                if (item === fn) {
                    planList[index] = null;
                    return false;
                }
            });
        }

        fire(...arg) {
            let planList = this.planList;
            each(planList, function (item, index) {
                if (item === null) {
                    planList.splice(index, 1);
                    return 'DEL'; } item(... arg); }); } staticCallbacks() {
            returnnew Plan(); } } window.Plan = Plan; } (); //=> Part 3: Drag library ~functionConstructor () {class Drag extends EventLibrary {constructor(curEle) {super(); // this:example this. CurEle = curEle; // Mount the current element to the instance private property, so that the public method can call the element // constructor mode, if you want each method to use a variable value, //=> Call-backs publish subscribe create schedule to this.planDown, this.planMove, this.planUp this.planDown = Plan.Callbacks(); this.planMove = Plan.Callbacks(); this.planUp = Plan.Callbacks(); // this. On (curEle,) {// this.'mousedown', this.down); // This in dowm(e) is a curEle (because on automatically points this in the current method to // //) => see item.call(this, e); // To make this in dowm(e) refer to an instance (make sure this in each prototype method is an instance of the current class) : this.on(curEle,'mousedown', this.down.myBind(this)); } down(e) {//=>this:examplelet{top:t, left:l}= this.curele,// Get the current element, get the starting position of the mouse and box and store it on the instance (because drag.init () requires a new one for each move) {top:t, left:l}= this.curele (true); // Get the box (current example) start value pass argumenttrueThis. MouseX = e.pagex; this.mouseY = e.pageY; this.strL = l; this.strT = t; //=> mouse-move/mouse-up to prevent loss of MOUSE focus, bind these two methods to document, and change this to // this.on(document,'mousemove', this); // This. On (document,'mouseup', this); This._move = this.move. MyBind (this); this._move = this.move. this._UP = this.up.myBind(this); this.on(document,'mousemove', this._MOVE);
            this.on(document, 'mouseup', this._UP); // this.plandown.fire. Call (this)// This will point this in FIRE to an example instance (Drag), but this in FIRE must be a Plan instance. // But when the scheduler is finished, the current example instance (Drag) needs to be manipulated, So pass this (current example instance (Drag)) when passing in (because you can't call to change this) this.planDown.fire(this); } move(e) {move(e) {move(e) {move(e) {move(e) {move(e) {move(e) {move(e) {move(e) {move(e) { // The parent reference is the big box in the picture //=>this:examplelet curEle = this.curEle;
            letCurL = e.pagex - this.mouseX + this.strL,// curL = e.pagex - this.mouseY + this.strT; //=> Boundary judgment: the boundary is no longer the width of the screen, but the width of the parent minus the width of the box itself is the maximum left and top values, but if the parent is body, the boundary is the width of the screen minus the width of the box itselflet{offsetParent: p} = curEle, / / get the parent of the current element reference W = document. The documentElement. ClientWidth | | Document. Body. ClientWidth, / / the default access to a wide screen high H = document. The documentElement. ClientHeight | | document. Body. ClientHeight;if(p.tagName ! = ='BODY') {// If the parent is not body, get the parent width of the current element W = p.clientWidth; H = p.clientHeight; } // Calculate the boundary (maximum moveable width and height)let maxL = W - curEle.offsetWidth,
                maxT = H - curEle.offsetHeight;
            curL = curL < 0 ? 0 : (curL > maxL ? maxL : curL);
            curT = curT < 0 ? 0 : (curT > maxT ? maxT : curT);

            curEle.style.left = curL + 'px'; // Set the left top value of curele.style. top = curT +'px'; this.maxL = maxL; // This. MaxT = maxT; // This. MaxT = maxT; //=>FIRE execute planMove schedule this.planmove. FIRE (this); } up(e) { //=>this:example this.off(document,'mousemove', this._MOVE);
            this.off(document, 'mouseup', this._UP); //=>FIRE execute planUp schedule this.planup. FIRE (this); } offset(flag) {// Get the offset of the current box // Get the parent reference, its own upper offset, left offset //=>this:example //let curEle = this.curEle;
            // let l = curEle.offsetLeft,
            //     t = curEle.offsetTop,
            //     p = curEle.offsetParent;

            let {offsetLeft:l, offsetTop:t, offsetParent:p}=this.curEle;
            if(! Flag) {//flag is true to get the relative top and left values of the parent element, not passed or passedfalseThe top and left references are relative to the body elementwhile(p.tagName ! = ='BODY') {// If the parent reference has not found the body, go up and calculate it at the original offset (plus the offset of each parent reference).let {clientLeft, clientTop, offsetLeft, offsetTop, offsetParent}=p,
                        {userAgent}=window.navigator;
                    // if (window.navigator.userAgent.indexOf('MSIE 8') = = = 1) {if (userAgent.indexOf('MSIE 8') === -1) {// ie8 l += clientLeft; t += clientTop; } l += offsetLeft; t += offsetTop; p = offsetParent; // Keep looking up until the level reference finds the body}}return{top: t, left: l}; } static init(curEle) {// Use the init static method to return an instance of Drag. No new Drag (oBox)returnnew Drag(curEle); } / / static init (curEle, {index = 0} = {}) {/ / {index = 0} = {} the configuration parameter method / /returnnew Drag(curEle); // } } window.Drag = Drag; } (); / / perform the Drag method / / Drag. The init (oBox, / /} {/ / index: 0);Copy the code