利用不到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的inArray 方法介绍
Oct 08 Javascript
jquery 页面滚动到底部自动加载插件集合
Jan 31 Javascript
JavaScript三元运算符的多种使用技巧
Apr 16 Javascript
js比较日期大小的方法
May 12 Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
Nov 15 Javascript
深入理解JavaScript中的块级作用域、私有变量与模块模式
Oct 31 Javascript
浅析使用BootStrap TreeView插件实现灵活配置快递模板
Nov 28 Javascript
BootStrap Fileinput初始化时的一些参数
Dec 30 Javascript
BOM之navigator对象和用户代理检测
Feb 10 Javascript
jQuery.cookie.js使用方法及相关参数解释
Mar 06 Javascript
vue v-for 使用问题整理小结
Aug 04 Javascript
vue悬浮可拖拽悬浮按钮的实例代码
Aug 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上传图片、删除图片实现代码
2010/05/12 PHP
PHP开发框架Laravel数据库操作方法总结
2014/09/03 PHP
PDO::errorInfo讲解
2019/01/28 PHP
php使用mysqli和pdo扩展,测试对比mysql数据库的执行效率完整示例
2019/05/09 PHP
IE与FireFox的兼容性问题分析
2007/04/22 Javascript
js继承 Base类的源码解析
2008/12/30 Javascript
js indexOf()定义和用法
2012/10/21 Javascript
原生js和css实现图片轮播效果
2017/02/07 Javascript
vue2.0移除或更改的一些东西(移除index key)
2017/08/28 Javascript
JavaScript实现省市联动过程中bug的解决方法
2017/12/04 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
JavaScript怎样在删除前添加确认弹出框?
2019/05/27 Javascript
vue下使用nginx刷新页面404的问题解决
2019/08/02 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
JavaScript实现省市区三级联动
2020/02/13 Javascript
ant-design表单处理和常用方法及自定义验证操作
2020/10/27 Javascript
Django自定义manage命令实例代码
2018/02/11 Python
对python使用http、https代理的实例讲解
2018/05/07 Python
python中的插值 scipy-interp的实现代码
2018/07/23 Python
flask-restful使用总结
2018/12/04 Python
pytorch程序异常后删除占用的显存操作
2020/01/13 Python
python实现录屏功能(亲测好用)
2020/03/02 Python
pycharm开发一个简单界面和通用mvc模板(操作方法图解)
2020/05/27 Python
利用Vscode进行Python开发环境配置的步骤
2020/06/22 Python
解决python运行效率不高的问题
2020/07/20 Python
python Zmail模块简介与使用示例
2020/12/19 Python
Python tkinter之ComboBox(下拉框)的使用简介
2021/02/05 Python
Nike荷兰官方网站:Nike.com (NL)
2018/04/19 全球购物
建筑设计所实习生自我鉴定
2013/09/25 职场文书
公司司机岗位职责范本
2014/03/03 职场文书
协议书怎么写
2014/04/21 职场文书
2014年维修工作总结
2014/11/22 职场文书
《一面五星红旗》教学反思
2016/02/23 职场文书
TV动画《八十龟酱观察日记》第四季宣传PV公布
2022/04/06 日漫
vue项目配置sass及引入外部scss文件
2022/04/14 Vue.js
python绘制云雨图raincloud plot
2022/08/05 Python