js

组件开发(1)

Posted by liyaozr on April 11, 2017

前面写过什么是面向对象编程以及如何进行面向对象编程:

之前我们采取的是继承的方式来复用代码,假如我们现在需要写多种不同表现形式的对象呢?例如弹窗,可能是登录框,也有可能是广告,或者其他的弹窗形式。这个时候再采取继承就有点不合适了,我们可以采用类似于兄弟关系的形式来提高对象的复用性。

还是用代码来说明。假设现在页面上有四个div,这四个div都有最基本的拖拽功能:

  • div1的功能是实现简单的拖拽就可以了;
  • div2需要在鼠标按下的时候,修改文档的标题;
  • div3则是在鼠标按下及抬起的时候分别修改一次标题;
  • div4需要在鼠标抬起的时候修改文档的标题;
window.onload = function () {
  var d1 = new Drag();
  d1.init('div1');
  var d2 = new Drag();
  d2.init('div2',function () {
    document.title = 'hello';
  });
  var d3 = new Drag();
  d3.init('div3',function () {
    document.title = '明天';
  },
  function () {
    document.title = '你好';
  });
  var d4 = new Drag();
  d4.init('div4',function () {
    document.title = 'bye~';
  });
};
function Drag() {
  this.obj = null;
  this.disX = 0;
  this.disY = 0;
}
Drag.prototype.init = function(id,toDown,toUp) {
  this.obj = document.getElementById(id);
  var that = this;
  this.obj.onmousedown = function (e) {
    e = e||window.event;
    that.fnDown(e);
    toDown();

    document.onmousemove = function (e) {
      e = e||window.event;
      that.fnMove(e);
    };
    document.onmouseup = function () {
      that.fnUp();
      toUp();
    };
    return false;
  };
};
Drag.prototype.fnDown = function(e) {
  var that = this;
  this.disX = e.clientX - this.obj.offsetLeft;
  this.disY = e.clientY - this.obj.offsetTop;
};
Drag.prototype.fnMove = function(e) {
  this.obj.style.left = e.clientX-this.disX +'px';
  this.obj.style.top = e.clientY-this.disY +'px';
};
Drag.prototype.fnUp = function() {
  document.onmousemove = null;
  document.onmouseup = null;
};

OK,问题来了。

  1. init中传入了三个参数,并且调用了两个回调函数,那么div1因为没有传参会报错:toDown is not a function
  2. div4传入了两个参数,系统无法确认参数的顺序,默认将传入的参数当成idtoDown,虽然我们想要的是toUp的效果

解决方案:

  1. 传入的参数采用json格式,只传入一个json对象,但是里面可以放很多东西。
  2. 使用配置参数默认参数,当有配置参数的时候,采用配置参数;没有配置参数的时候采用默认参数
  var d1 = new Drag();
  d1.init({   //配置参数
    id:'div1',
  });
  var d2 = new Drag();
  d2.init({   //配置参数
    id:'div2',
    toDown:function () {
      document.title = 'hello';
      document.body.background = 'black';
    }
  });
  var d3 = new Drag();
  d3.init({   //配置参数
    id:'div3',
    toDown:function () {
      document.title = '明天';
    },
    toUp:function () {
      document.title = '你好';
    }
  });
  var d4 = new Drag();
  d4.init({   //配置参数
    id:'div4',
    toUp:function () {
      document.title = 'bye~';
    }
  });
};
function extend(obj1,obj2){
  for(var attr in obj2){
    obj1[attr] = obj2[attr];
  }
}
//构造函数
function Drag() {
  this.obj = null;
  this.disX = 0;
  this.disY = 0;
  this.settings={    //默认参数
    toDown:function () {},
    toUp:function () {}
  };
}
//初始化函数
Drag.prototype.init = function(opt) {
  this.obj = document.getElementById(opt.id);
  extend( this.settings , opt ); // 更新参数
  var that = this;
  this.obj.onmousedown = function (e) {
    e = e||window.event;
    that.fnDown(e);
    that.settings.toDown();//这里调用默认参数

    document.onmousemove = function (e) {
      e = e||window.event;
      that.fnMove(e);
    };
    document.onmouseup = function () {
      that.fnUp();
      that.settings.toUp();//这里调用默认参数
    };
    return false;
  };
};
//下面的代码是一样的就不贴了

代码效果请戳☞[这里]

1.什么是组件?

所以,组件开发到底是什么?

  1. 对面向对象的深入应用(如:UI组件,功能组件)
  2. 将配置参数、方法、事件三者进行分离(如JqueryUI)

好的组件都是配置参数、方法、事件三者分离的,之前的拖拽例子并没有完整的实现组件开发。

下面是jqueryUI拖拽组件的API接口 Paste_Image.png

参数和方法我们都知道,那么自定义事件是什么鬼?

(1)什么是自定义事件

自定义事件就是让函数具备事件的某些特性。

直接来栗子吧。

//这是一个正常的函数
function show(){
    alert(1);
}
show(); //1

//自定义事件
window.addEventListener('show',function(){
    alert(1);
},false);
show(); //1

2.原始类型的自动转换

var str = 'hello';
alert(str.length);  //5

str.number = 10;
alert( str.number );  //undefined

3.包装对象自定义方法

var str = 'hello';

String.prototype.lastValue = function(){
    return this.charAt(this.length-1);
};

alert( str.lastValue() );  //o