利用不到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 相关文章推荐
JavaScript 函数调用规则
Sep 14 Javascript
如何用ajax来创建一个XMLHttpRequest对象
Dec 10 Javascript
Area 区域实现post提交数据的js写法
Apr 22 Javascript
js检测输入内容全为空格的方法
May 03 Javascript
JavaScript中的迭代器和生成器详解
Oct 29 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
Aug 26 Javascript
jQuery javascript获得网页的高度与宽度的实现代码
Apr 26 Javascript
angularjs使用directive实现分页组件的示例
Feb 07 Javascript
JS身份证信息验证正则表达式
Jun 12 Javascript
使用bootstrap实现下拉框搜索功能的实例讲解
Aug 10 Javascript
关于vue状态过渡transition不起作用的原因解决
Apr 09 Javascript
Element-ui中元素滚动时el-option超出元素区域的问题
May 30 Javascript
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
VML绘图板②脚本--VMLgraph.js、XMLtool.js
2006/10/09 PHP
Yii视图CGridView列表用法实例分析
2016/07/12 PHP
Javascript 作用域使用说明
2009/08/13 Javascript
学习ExtJS accordion布局
2009/10/08 Javascript
JQuery勾选指定name的复选框集合并显示的方法
2015/05/18 Javascript
简单实现异步编程promise模式
2015/07/31 Javascript
JS动态添加iframe的代码
2015/09/14 Javascript
JS实现单击输入框弹出选择框效果完整实例
2015/12/14 Javascript
WordPress中利用AJAX技术进行评论提交的实现示例
2016/01/12 Javascript
jquery实现全选和全不选功能效果的实现代码【推荐】
2016/05/05 Javascript
jQuery解决IE6、7、8不能使用 JSON.stringify 函数的问题
2016/05/31 Javascript
JavaScript之iterable_动力节点Java学院整理
2017/06/29 Javascript
tangram.js库实现js类的方式实例分析
2018/01/06 Javascript
jQuery实现鼠标移入移出事件切换功能示例
2018/09/06 jQuery
Vue常见面试题整理【值得收藏】
2018/09/20 Javascript
vue响应式系统之observe、watcher、dep的源码解析
2019/04/09 Javascript
js实现3D照片墙效果
2019/10/28 Javascript
Vue搭建后台系统需要注意的问题
2019/11/08 Javascript
Js on及addEventListener原理用法区别解析
2020/07/11 Javascript
Vue router安装及使用方法解析
2020/12/02 Vue.js
js动态生成表格(节点操作)
2021/01/12 Javascript
[45:52]2018DOTA2亚洲邀请赛 4.1小组赛 A组加赛 LGD vs Liquid
2018/04/02 DOTA
[36:33]完美世界DOTA2联赛循环赛 Matador vs Forest 第一场 11.06
2020/11/06 DOTA
wxPython学习之主框架实例
2014/09/28 Python
Tensorflow卷积神经网络实例进阶
2018/05/24 Python
matplotlib阶梯图的实现(step())
2021/03/02 Python
Omio法国:全欧洲低价大巴、火车和航班搜索和比价
2017/11/13 全球购物
SQL Server提供的3种恢复模型都是什么? 有什么区别?
2012/05/13 面试题
EntityManager都有哪些方法
2013/11/01 面试题
应届毕业生简历自我评价
2014/01/31 职场文书
教室标语大全
2014/06/21 职场文书
传播学专业毕业生自荐书
2014/07/01 职场文书
重阳节慰问信
2015/02/15 职场文书
决心书格式及范文
2019/06/24 职场文书
go使用Gin框架利用阿里云实现短信验证码功能
2021/08/04 Golang
Java 常见的限流算法详细分析并实现
2022/04/07 Java/Android