利用不到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 相关文章推荐
19个很有用的 JavaScript库推荐
Jun 27 Javascript
使用基于jquery的gamequery插件做JS乒乓球游戏
Jul 31 Javascript
JavaScript中获取鼠标位置相关属性总结
Oct 11 Javascript
浅谈jquery事件处理
Apr 24 Javascript
jquery跟随屏幕滚动效果的实现代码
Apr 13 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
Jul 12 Javascript
node.js实现博客小爬虫的实例代码
Oct 08 Javascript
js实现符合国情的日期插件详解
Jan 19 Javascript
angularjs通过过滤器返回超链接的方法
Oct 26 Javascript
超详细动手搭建一个VuePress 站点及开启PWA与自动部署的方法
Jan 27 Javascript
vue中利用Promise封装jsonp并调取数据
Jun 18 Javascript
vue axios封装httpjs,接口公用配置拦截操作
Aug 11 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
2020最新CPU的性能排名
2020/04/02 数码科技
[转帖]PHP世纪万年历
2006/12/06 PHP
php中神奇的fastcgi_finish_request
2011/05/02 PHP
如何在php中正确的使用json
2013/08/06 PHP
PHP实现抓取HTTPS内容
2014/12/01 PHP
PHP简单的MVC框架实现方法
2015/12/01 PHP
php安装扩展mysqli的实现步骤及报错解决办法
2017/09/23 PHP
PHP正则判断一个变量是否为正整数的方法
2019/02/27 PHP
正则表达式判断是否存在中文和全角字符和判断包含中文字符串长度
2008/09/27 Javascript
jQuery validate验证插件使用详解
2016/05/11 Javascript
详解本地Node.js服务器作为api服务器的解决办法
2017/02/28 Javascript
如何给ss bash 写一个 WEB 端查看流量的页面
2017/03/23 Javascript
详解jquery插件jquery.viewport.js学习使用方法
2017/09/08 jQuery
vue3.0 CLI - 2.6 - 组件的复用入门教程
2018/09/14 Javascript
发布Angular应用至生产环境的方法
2018/12/10 Javascript
深入理解JavaScript 箭头函数
2019/05/30 Javascript
express如何解决ajax跨域访问session失效问题详解
2019/06/20 Javascript
Python编程之微信推送模板消息功能示例
2017/08/21 Python
使用python爬虫实现网络股票信息爬取的demo
2018/01/05 Python
python实现多张图片拼接成大图
2019/01/15 Python
Python3实现的简单三级菜单功能示例
2019/03/12 Python
Django框架模板文件使用及模板文件加载顺序分析
2019/05/23 Python
简单了解python变量的作用域
2019/07/30 Python
python实现简单的五子棋游戏
2020/09/01 Python
python爬取招聘要求等信息实例
2020/11/20 Python
Python使用tkinter制作在线翻译软件
2021/02/22 Python
CSS3 滤镜 webkit-filter详细介绍及使用方法
2012/12/27 HTML / CSS
网络维护中文求职信
2014/01/03 职场文书
大二学生职业生涯规划书
2014/02/05 职场文书
公证委托书大全
2014/04/04 职场文书
老干部工作先进集体事迹材料
2014/05/21 职场文书
党员“四风”方面存在问题及整改措施
2014/09/24 职场文书
2014年统战工作总结
2014/12/09 职场文书
2016年会领导致辞稿
2015/07/29 职场文书
修改MySQL的数据库引擎为INNODB的方法
2021/05/26 MySQL
2021好看的国漫排行榜前十名 《完美世界》上榜,《元龙》排名第一
2022/03/18 国漫