利用不到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 相关文章推荐
JS实现在Repeater控件中创建可隐藏区域的代码
Sep 16 Javascript
判断js对象是否拥有某一个属性的js代码
Aug 16 Javascript
node.js中的fs.rename方法使用说明
Dec 16 Javascript
JavaScript中扩展Array contains方法实例
Aug 23 Javascript
EasyUI的doCellTip实现鼠标放到单元格上提示单元格内容
Aug 24 Javascript
利用jQuery插件imgAreaSelect实现获得选择域的图像信息
Dec 02 Javascript
js 作用域和变量详解
Feb 16 Javascript
JS实现可针对算术表达式求值的计算器功能示例
Sep 04 Javascript
解决vue点击控制单个样式的问题
Sep 05 Javascript
JavaScript使用localStorage存储数据
Sep 25 Javascript
微信小程序开发中var that =this的用法详解
Jan 18 Javascript
Ajax异步刷新功能及简单案例
Nov 20 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
php将数据库中的电话号码读取出来并生成图片
2008/08/31 PHP
php UTF-8、Unicode和BOM问题
2010/05/18 PHP
ubuntu 编译安装php 5.3.3+memcache的方法
2010/08/05 PHP
SWFUpload与CI不能正确上传识别文件MIME类型解决方法分享
2011/04/18 PHP
php中session_unset与session_destroy的区别分析
2011/06/16 PHP
PHP持久连接mysql_pconnect()函数使用介绍
2012/02/05 PHP
php开发文档 会员收费1期
2012/08/14 PHP
解析PHP中DIRECTORY_SEPARATOR,PATH_SEPARATOR两个常量的作用
2013/06/21 PHP
php数组键名技巧小结
2015/02/17 PHP
实现超用户体验 table排序javascript实现代码
2009/06/22 Javascript
js下通过prototype扩展实现indexOf的代码
2010/12/08 Javascript
jquery里的正则表达式说明
2011/08/03 Javascript
在页面中js获取光标/鼠标的坐标及光标的像素坐标
2013/11/11 Javascript
转换字符串为json对象的方法详解
2013/11/29 Javascript
javascript实现多级联动下拉菜单的方法
2015/02/06 Javascript
深入理解JavaScript系列(39):设计模式之适配器模式详解
2015/03/04 Javascript
js跨域请求的5中解决方式
2015/07/02 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
jQuery多级联动下拉插件chained用法示例
2016/08/20 Javascript
AngularJS实现数据列表的增加、删除和上移下移等功能实例
2016/09/05 Javascript
浅谈在js传递参数中含加号(+)的处理方式
2016/10/11 Javascript
文本溢出插件jquery.dotdotdot.js使用方法详解
2017/06/22 jQuery
微信小程序滚动Tab实现左右可滑动切换
2017/08/17 Javascript
JavaScript实现飞舞的泡泡效果
2020/02/07 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
webpack安装配置与常见使用过程详解(结合vue)
2020/06/01 Javascript
wxpython 学习笔记 第一天
2009/02/09 Python
python3+PyQt5实现文档打印功能
2018/04/24 Python
Python爬虫实现自动登录、签到功能的代码
2020/08/20 Python
Html5与App的通讯方式详解
2019/10/24 HTML / CSS
amazeui模态框弹出后立马消失并刷新页面
2020/08/19 HTML / CSS
英国休闲奢华的缩影:Crew Clothing
2019/05/05 全球购物
个人自我评价分享
2013/12/20 职场文书
大学共青团员个人自我评价
2014/04/16 职场文书
给客户的感谢信
2015/01/21 职场文书
Spring Security中用JWT退出登录时遇到的坑
2021/10/16 Java/Android