利用不到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 相关文章推荐
Flexigrid在IE下不显示数据的处理的解决方法
Oct 24 Javascript
javasctipt如何显示几分钟前、几天前等
Apr 30 Javascript
JS返回iframe中frameBorder属性值的方法
Apr 01 Javascript
Jquery简单实现GridView行高亮的方法
Jun 15 Javascript
JavaScript的设计模式经典之代理模式
Feb 24 Javascript
JavaScript代码里的判断小结
Aug 22 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(同步显示图像位置信息)
Dec 02 Javascript
JS实现的DIV块来回滚动效果示例
Feb 07 Javascript
解决vue热替换失效的根本原因
Sep 19 Javascript
详解CommonJS和ES6模块循环加载处理的区别
Dec 26 Javascript
Vue CLI 3.x 自动部署项目至服务器的方法
Apr 02 Javascript
梳理一下vue中的生命周期
Dec 30 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+Html+缓存
2006/11/25 PHP
php调用mysql数据 dbclass类
2011/05/07 PHP
二招解决php乱码问题
2012/03/25 PHP
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
php递归遍历删除文件的方法
2015/04/17 PHP
PHP API接口必备之输出json格式数据示例代码
2017/06/27 PHP
Thinkphp 在api开发中异常返回依然是html的解决方式
2019/10/16 PHP
php生成随机数/生成随机字符串的方法小结【5种方法】
2020/05/27 PHP
Avengerls vs KG BO3 第一场2.18
2021/03/10 DOTA
JavaScript中的函数模式详解
2015/02/11 Javascript
javascript高级编程之函数表达式 递归和闭包函数
2015/11/29 Javascript
第五篇Bootstrap 排版
2016/06/21 Javascript
jQuery实现对象转为url参数的方法
2017/01/11 Javascript
浅谈$_FILES数组为空的原因
2017/02/16 Javascript
20行JS代码实现网页刮刮乐效果
2017/06/23 Javascript
详解require.js配置路径的用法和css的引入
2017/09/06 Javascript
Vue.js 父子组件通信的十种方式
2018/10/30 Javascript
angular 实现下拉列表组件的示例代码
2019/03/09 Javascript
Vue Echarts实现可视化世界地图代码实例
2019/05/07 Javascript
详解jenkins自动化部署vue
2019/05/14 Javascript
RxJS在TypeScript中的简单使用详解
2020/04/13 Javascript
es6函数之rest参数用法实例分析
2020/04/18 Javascript
探究一道价值25k的蚂蚁金服异步串行面试题
2020/08/21 Javascript
JavaScript实现雪花飘落效果
2020/12/27 Javascript
python使用urllib2实现发送带cookie的请求
2015/04/28 Python
python批量提取word内信息
2015/08/09 Python
python with提前退出遇到的坑与解决方案
2018/01/05 Python
django表单实现下拉框的示例讲解
2018/05/29 Python
Python 3.9的到来到底是意味着什么
2020/10/14 Python
Myprotein葡萄牙官方网站:英国优质运动营养品牌
2016/09/12 全球购物
一套Delphi的笔试题一
2016/02/14 面试题
民警个人对照检查剖析材料
2014/09/17 职场文书
2014年终个人工作总结
2014/11/07 职场文书
教师节大会主持词
2015/07/06 职场文书
暑期社会实践新闻稿
2015/07/17 职场文书
励志语录:只有自己足够强大,才能不被别人践踏
2020/01/09 职场文书