利用不到200行代码写一款属于你自己的js类库


Posted in Javascript onJuly 08, 2019

前言

JavaScript 的核心是支持面向对象的,同时它也提供了强大灵活的 OOP 语言能力。本文将使用面向对象的方式,来教大家用原生js写出一个类似jQuery这样的类库。我们将会学到如下知识点:

  • 闭包:减少变量污染,缩短变量查找范围
  • 自执行函数在对象中的运用
  • extend的实现原理
  • 如何实现跨浏览器的事件监听
  • 原型链与继承

接下来我会对类库的核心api进行讲解和展示,文章最后后附带类库的完整源码,在我之前的文章《3分钟教你用原生js实现具有进度监听的文件上传预览组件》中也使用了类似的方式,感兴趣的可以一起学习,交流。

更加完整的类库地址,请移步github《Xuery——仿jquery API风格的轻量级可扩展的原生js框架》(本地下载)

类库设计思路

利用不到200行代码写一款属于你自己的js类库

API介绍和效果展示

1、事件绑定 Xuery.on(eventName, fn)案例如下:

Xuery('#demo').on('click', function(e){
 alert('hello world!')
})

2、访问和设置css Xuery.css(string|object, ?[string])案例如下:

// 访问css
Xuery('#demo').css('width')
// 设置css
Xuery('#demo').css('width', '1024px')
// 设置css
Xuery('#demo').css({
 width: '1024px',
 height: '1024px'
})

3、访问和设置属性 Xuery.attr(string|object, ?[string])案例如下:

// 访问attr
Xuery('#demo').attr('title')
// 设置attr
Xuery('#demo').attr('title', '1024px')
// 设置attrs
Xuery('#demo').attr({
 title: '1024px',
 name: '1024px'
})

4、访问和设置html案例如下:

// 访问
Xuery('#demo').html()
// 设置
Xuery('#demo').html('前端学习原生框架')

还有其他几个常用的API在这里就不介绍了,大家可以在我的github上查看,或者基于这套基础框架,去扩展属于自己的js框架。

核心源码

以下源码相关功能我做了注释,建议大家认真阅读,涉及到原型链和构造函数的指向的问题,是实现上述调用方式的核心,又不懂可以在评论区交流沟通。

/**
 * 链模式实现自己的js类库
 */
(function(win, doc){
 var Xuery = function(selector, context) {
  return new Xuery.fn.init(selector, context)
 };

 Xuery.fn = Xuery.prototype = {
 constructor: Xuery,
 init: function(selector, context) {
  // 设置元素长度
  this.length = 0;
  // 默认获取元素的上下文document
  context = context || document;
  // id选择符,则按位非将-1转化为0
  if(~selector.indexOf('#')) {
  this[0] = document.getElementById(selector.slice(1));
  this.length = 1;
  }else{
  // 在上下文中选择元素
  var doms = context.getElementsByTagName(selector),
  i = 0,
  len = doms.length;
  for(; i<len; i++){
   this[i] = doms[i];
  }
  }
  this.context = context;
  this.selector = selector;
  return this
 },
 // 增强数组
 push: [].push,
 sort: [].sort,
 splice: [].splice
 };

 // 方法扩展
 Xuery.extend = Xuery.fn.extend = function(){
 // 扩展对象从第二个参数算起
 var i = 1,
 len = arguments.length,
 target = arguments[0],
 j;
 if(i === len){
  target = this;
  i--;
 }
 // 将参数对象合并到target
 for(; i<len; i++){
  for(j in arguments[i]){
  target[j] = arguments[i][j];
  }
 }
 return target
 }

 // 扩展事件方法
 Xuery.fn.extend({
 on: (function(){
  if(document.addEventListener){
  return function(type, fn){
   var i = this.length -1;
   for(; i>=0;i--){
   this[i].addEventListener(type, fn, false)
   }
   return this
  }
  // ie浏览器dom2级事件
  }else if(document.attachEvent){
  return function(type, fn){
   var i = this.length -1;
   for(; i>=0;i--){
   this[i].addEvent('on'+type, fn)
   }
   return this
  }
  // 不支持dom2的浏览器
  }else{
  return function(type, fn){
   var i = this.length -1;
   for(; i>=0;i--){
   this[i]['on'+type] = fn;
   }
   return this
  }
  }
 })()
 })

 // 将‘-'分割线转换为驼峰式
 Xuery.extend({
 camelCase: function(str){
  return str.replace(/\-(\w)/g, function(all, letter){
  return letter.toUpperCase();
  })
 }
 })

 // 设置css
 Xuery.extend({
 css: function(){
  var arg = arguments,
  len = arg.length;
  if(this.length < 1){
  return this
  }
  if(len === 1) {
  if(typeof arg[0] === 'string') {
   if(this[0].currentStyle){
   return this[0].currentStyle[arg[0]];
   }else{
   return getComputedStyle(this[0], false)[arg[0]]
   }
  }else if(typeof arg[0] === 'object'){
   for(var i in arg[0]){
   for(var j=this.length -1; j>=0; j--){
    this[j].style[Xuery.camelCase(i)] = arg[0][i];
   }
   }
  }
  }else if(len === 2){
  for(var j=this.length -1; j>=0; j--){
   this[j].style[Xuery.camelCase(arg[0])] = arg[1];
  }
  }
  return this
 }
 })

 // 设置属性
 Xuery.extend({
 attr: function(){
  var arg = arguments,
  len = arg.length;
  if(len <1){
  return this
  }
  if(len === 1){
  if(typeof arg[0] === 'string'){
   return this[0].getAttribute(arg[0])
  }else if(typeof arg[0] === 'object'){
   for(var i in arg[0]){
   for(var j=this.length -1; j>= 0; j--){
    this[j].setAttribute(i, arg[0][i])
   }
   }
  }
  }
  else if(len === 2){
  for(var j=this.length -1; j>=0; j--){
   this[j].setAttribute(arg[0], arg[1]);
  }
  }
  return this
 }
 })

 // 获取或者设置元素内容
 Xuery.fn.extend({
 html: function(){
  var arg = arguments,
  len = arg.length;
  if(len === 0){
  return this[0] && this[0].innerHTML
  }else{
  for(var i=this.length -1; i>=0; i--){
   this[i].innerHTML = arg[0];
  }
  }
  return this
 }
 })

 Xuery.fn.init.prototype = Xuery.fn;
 window.Xuery = Xuery;
})(window, document);

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jquery异步请求实例代码
Jun 21 Javascript
js二维数组排序的简单示例代码
Jan 24 Javascript
dreamweaver 8实现Jquery自动提示
Dec 04 Javascript
jQuery实现的Div窗口震动效果实例
Aug 07 Javascript
JavaScript获取当前url根目录(路径)
Jun 17 Javascript
微信小程序 SocketIO 实例讲解
Oct 13 Javascript
JavaScript实现选中文字提示新浪微博分享效果
Jun 15 Javascript
关于vue的语法规则检测报错问题的解决
May 21 Javascript
JS编写兼容IE6,7,8浏览器无缝自动轮播
Oct 12 Javascript
vscode 插件开发 + vue的操作方法
Jun 05 Javascript
vantUI 获得piker选中值的自定义ID操作
Nov 04 Javascript
详解Vue的sync修饰符
May 15 Vue.js
Vue中util的工具函数实例详解
Jul 08 #Javascript
详解基于 Node.js 的轻量级云函数功能实现
Jul 08 #Javascript
使用 node.js 模仿 Apache 小部分功能
Jul 07 #Javascript
echarts统计x轴区间的数值实例代码详解
Jul 07 #Javascript
vue + typescript + video.js实现 流媒体播放 视频监控功能
Jul 07 #Javascript
详解django模板与vue.js冲突问题
Jul 07 #Javascript
django中使用vue.js的要点总结
Jul 07 #Javascript
You might like
PHP获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
Javascript typeof 用法
2008/12/28 Javascript
JS关键字变色实现思路及代码
2013/02/21 Javascript
CSS或者JS实现鼠标悬停显示另一元素
2016/01/22 Javascript
jQuery EasyUI封装简化操作
2016/09/18 Javascript
详解MVC如何使用开源分页插件(shenniu.pager.js)
2016/12/16 Javascript
简单实现node.js图片上传
2016/12/18 Javascript
jquery实现input框获取焦点的方法
2017/02/06 Javascript
javascript实现数据双向绑定的三种方式小结
2017/03/09 Javascript
详解Weex基于Vue2.0开发模板搭建
2017/03/20 Javascript
React中ES5与ES6写法的区别总结
2017/04/21 Javascript
Angular移动端页面input无法输入的解决方法
2017/11/14 Javascript
vue3.0 CLI - 2.6 - 组件的复用入门教程
2018/09/14 Javascript
JavaScript实现的级联算法示例【省市二级联动功能】
2018/12/25 Javascript
详解angular2 控制视图的封装模式
2018/12/27 Javascript
生成无限制的微信小程序码的示例代码
2019/09/20 Javascript
three.js 如何制作魔方
2020/07/31 Javascript
[01:18:45]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第三场2月1日
2021/03/11 DOTA
python之DataFrame实现excel合并单元格
2021/02/22 Python
python实现淘宝秒杀脚本
2020/06/23 Python
python实现四人制扑克牌游戏
2020/04/22 Python
Python urllib库如何添加headers过程解析
2020/10/05 Python
html5的自定义data-*属性与jquery的data()方法的使用
2014/07/02 HTML / CSS
机工车间主任岗位职责
2014/03/05 职场文书
入党积极分子学习两会心得体会范文
2014/03/17 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书
二年级评语大全
2014/04/23 职场文书
民主生活会对照检查材料思想汇报
2014/09/27 职场文书
预备党员思想汇报1000字
2014/10/07 职场文书
2015年中秋节演讲稿
2015/03/20 职场文书
农业项目投资意向书
2015/05/09 职场文书
有关朝花夕拾的读书笔记
2015/06/29 职场文书
保险公司增员口号
2015/12/25 职场文书
PHP 技巧 * SVG 保存为图片(分享图生成)
2021/04/02 PHP
Python中json.load()和json.loads()有哪些区别
2021/06/07 Python
JavaScript 数组去重详解
2021/09/15 Javascript