利用不到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 相关文章推荐
用正则xmlHttp实现的偷(转)
Jan 22 Javascript
url地址自动加#号问题说明
Aug 21 Javascript
JavaScript去掉数组中的重复元素
Jan 13 Javascript
获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome的方法介绍
Nov 08 Javascript
JavaScript自定义事件介绍
Aug 29 Javascript
js使用eval解析json实例与注意事项分享
Jan 18 Javascript
javascript制作坦克大战全纪录(2)
Nov 27 Javascript
jQuery平滑旋转幻灯片特效代码分享
Sep 07 Javascript
浅析javascript函数表达式
Feb 10 Javascript
浅谈移动端之js touch事件 手势滑动事件
Nov 07 Javascript
JS自定义函数实现时间戳转换成date的方法示例
Aug 27 Javascript
js对象数组和对象的使用实例详解
Aug 27 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
杏林同学录(九)
2006/10/09 PHP
php SQL防注入代码集合
2008/04/25 PHP
采用thinkphp自带方法生成静态html文件详解
2014/06/13 PHP
分享五个PHP7性能优化提升技巧
2015/12/07 PHP
PHP简单实现上一页下一页功能示例
2016/09/14 PHP
JS在IE和FireFox之间常用函数的区别小结
2010/03/12 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
js加入收藏夹代码(兼容ie/ff/op)
2014/05/16 Javascript
node.js中的buffer.slice方法使用说明
2014/12/10 Javascript
利用JavaScript脚本实现滚屏效果的方法
2015/07/07 Javascript
JavaScript实现的浮动层框架用法实例分析
2015/10/10 Javascript
15个常用的jquery代码片段
2015/12/19 Javascript
超赞的jQuery图片滑块动画特效代码汇总
2016/01/25 Javascript
Easyui的组合框的取值与赋值
2016/10/28 Javascript
webpack踩坑之路图片的路径与打包
2017/09/05 Javascript
Vue-router 类似Vuex实现组件化开发的示例
2017/09/15 Javascript
详解使用vuex进行菜单管理
2017/12/21 Javascript
d3.js实现图形拖拽
2019/12/19 Javascript
Node.JS获取GET,POST数据之queryString模块使用方法详解
2020/02/06 Javascript
linux系统使用python监测网络接口获取网络的输入输出
2014/01/15 Python
Python 文件操作的详解及实例
2017/09/18 Python
Python读取YUV文件,并显示的方法
2018/12/04 Python
Python read函数按字节(字符)读取文件的实现
2019/07/03 Python
Python generator生成器和yield表达式详解
2019/08/08 Python
python多线程使用方法实例详解
2019/12/30 Python
python实现电子词典
2020/03/03 Python
Python PyQt5运行程序把输出信息展示到GUI图形界面上
2020/04/27 Python
css3实现一款模仿iphone样式的注册表单
2013/03/20 HTML / CSS
html5 canvas里绘制椭圆并保持线条粗细均匀的技巧
2013/03/25 HTML / CSS
手工制作的豪华英式沙发和沙发床:Willow & Hall
2019/05/03 全球购物
求职信内容怎么写
2014/05/26 职场文书
党的群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
小学科学教学计划
2015/01/21 职场文书
涨价通知
2015/04/23 职场文书
详解CocosCreator消息分发机制
2021/04/16 Javascript
mysql使用 not int 子查询隐含陷阱
2022/04/12 MySQL