请选择 进入手机版 | 继续访问电脑版
查看: 156|回复: 1

【JavaScript高级进阶】实现事件框架的封装及其源代码分享

[复制链接]

699

主题

740

帖子

6196

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
6196
发表于 2018-7-6 13:10:15 | 显示全部楼层 |阅读模式
  1. /**
  2. * Created by xiuxiu on 2018/6/16
  3. */

  4. // 框架的本质

  5. /**
  6. * 函数:工具
  7. * 对象:工具包
  8. * 框架:多个工具包
  9. */


  10. /*

  11. * V1.0:使用原型的方式实现一个框架
  12. *       实现了对象获取,字符串操作,数据类型的检测等功能【extend, queryString, query是核心功能】
  13. *       on函数的封装(事件监听,考虑浏览器的兼容性)
  14. * V2.0:使用对象的字面量方式来封装一个框架(JSON格式来封装一个框架)
  15. * V3.0:使用Extend方式来封装一个框架
  16. * V4.0: 事件框架的封装
  17. *       事件流机制Dom2.0
  18. *       on,un,getEvent, getTarget,delegate等方法
  19. * */





  20. // 框架基础代码
  21. var xframe = function () {
  22. }
  23. /**
  24. * 使用原型方式封装框架
  25. * @type {{$id: xframe.$id, $tag: xframe.$tag, ltrim: xframe.ltrim, rtrim: xframe.rtrim, trim: xframe.trim, formateString: xframe.formateString, isNumber: xframe.isNumber, isBoolean: xframe.isBoolean, isString: xframe.isString, isUndefined: xframe.isUndefined, isObject: xframe.isObject, isNull: xframe.isNull, isArray: xframe.isArray, extend: xframe.extend, queryString: xframe.queryString, query: xframe.query, on: xframe.on}}
  26. */
  27. xframe.prototype = {
  28.     // 先写出接口,不用事先事先这个方法
  29.     /**
  30.      * 给一个对象扩充功能:将一个对象的所有属属性拷贝到另外一个对象上去(如果没有的话,就直接把属性添加进去)
  31.      * // 将一个对象的方法,拷贝给另外一个对象
  32.      * @param target
  33.      * @param source
  34.      * @returns {*}
  35.      */
  36.     extend: function (target, source) {
  37.         // 把source对象的所有属性拷贝到target中去
  38.         for (var i in source) {
  39.             target[i] = source[i];
  40.         }
  41.         return target;
  42.     },

  43. }
  44. // 创建一个我的框架对象实例
  45. var $ = new xframe();




  46. //Extend的好处:可以把框架的功能进行模块化, 实现功能的分类管理
  47. /**
  48. * 字符串的操作
  49. */
  50. $.extend($, {
  51.     // 常用的字符串的操作-----------------------------------------------------------------------
  52.     /**
  53.      * 去除字符串左边的空格
  54.      * @param str
  55.      */
  56.     ltrim: function (str) {
  57.         return str.replace(/(^\s*)/g, "");
  58.     },
  59.     /**
  60.      * 去除字符串右边的空格
  61.      * @param str
  62.      */
  63.     rtrim: function (str) {
  64.         return str.replace(/(\s*$)/g, "");
  65.     },
  66.     /**
  67.      * 去除字符串中的空格
  68.      * @param str
  69.      */
  70.     trim: function (str) {
  71.         return str.replace(/(^\s*)|(\s*$)/g, "");
  72.     },
  73.     /**
  74.      * 实现一个简单的数据绑定
  75.      * @param str
  76.      * @param data
  77.      */
  78.     formateString: function (str, data) {
  79.         return str.replace(/@\((\w+)\)/g, function (match, key) {
  80.             return typeof data[key] === 'undefined' ? '' : data[key]
  81.         })
  82.     },

  83. })


  84. /**
  85. * 查询功能的模块化
  86. */
  87. $.extend($, {
  88.     /**
  89.      * 查询地址栏的字符串,用于页面间的传参(通过location.search可以获取查询字符串)
  90.      * @returns {{}}
  91.      */
  92.     queryString: function () {
  93.         var str = window.location.search.substring(1);      // 获取查询字符串,即"id=1&name=location"的部分
  94.         var arr = str.split('&');                           // 用&分割数组
  95.         var json = {};                                      // 定义一个临时对象

  96.         // 遍历数组
  97.         for (var i = 0; i < arr.length; i++) {
  98.             var c = arr[i].indexOf("=");                    // 获取每个参数中的等号=小标的位置
  99.             if (c == -1)
  100.                 continue                                    // 如果没有发现等号=的位置,则忽略


  101.             var d = arr[i].substring(0, c);                 // 截取等号前的参数名称
  102.             var e = arr[i].substring(c + 1);                  // 截取等号后面的位置

  103.             json[d] = e;                                     // 用名称 : 值 的格式存储在json对象中
  104.         }

  105.         return json;                                        // 返回json对象【json中存储数据的时候,key必须是唯一的,否则后面的会覆盖掉前面的内容哈】
  106.     },
  107.     /**
  108.      *  页面参数的查询(普通查询)
  109.      * @returns {string[]}
  110.      */
  111.     query: function () {
  112.         var params = window.location.search;                // 获取 arams : ? id , date……
  113.         var arr = params.substring(1).split(',');
  114.         return arr;
  115.     },
  116. })


  117. /**
  118. * 常用数据类型的检测
  119. */
  120. $.extend($, {
  121.     // 常用数据类型检测-----------------------------------------------------------------------------
  122.     /**
  123.      * 用于检测一个值是不是数字
  124.      * 要点:1.js中的==和!= 比较, 若两者类型不同,会先转换类型,再做值比较,最后返回值比较结果(不严格)
  125.      *      2.===和!=== 只有在相同类型的情况下,才会比较二者的值,否则直接返回false (比较更严格)
  126.      * @param val
  127.      * @returns {boolean}
  128.      */
  129.     isNumber: function (val) {
  130.         // isFinite()函数是js自带函数,会过滤掉NaN和Infinity类型
  131.         return typeof val === 'number' && isFinite(val)
  132.     },
  133.     /**
  134.      * 是不是布尔类型
  135.      * @param val
  136.      * @returns {boolean}
  137.      */
  138.     isBoolean: function (val) {
  139.         return typeof val === 'boolean';
  140.     },
  141.     /**
  142.      * 是不是字符串类型
  143.      * @param val
  144.      * @returns {boolean}
  145.      */
  146.     isString: function (val) {
  147.         return typeof val === 'string';
  148.     },
  149.     /**
  150.      * 是不是未定义类型
  151.      * @param val
  152.      * @returns {boolean}
  153.      */
  154.     isUndefined: function (val) {
  155.         return typeof  val === 'undefined';
  156.     },
  157.     /**
  158.      * 是不是Object类型
  159.      * @param str
  160.      * @returns {boolean}
  161.      */
  162.     isObject: function (str) {
  163.         if (str == null || typeof str === 'undefined') {
  164.             return false;
  165.         }
  166.         return typeof  str === 'object';
  167.     },
  168.     /**
  169.      * 是否为null
  170.      * @param val
  171.      * @returns {boolean}
  172.      */
  173.     isNull: function (val) {
  174.         return val === null;
  175.     },
  176.     /**
  177.      * 是否为数组类型
  178.      * @param arr
  179.      * @returns {boolean}
  180.      */
  181.     isArray: function (arr) {
  182.         if (arr === null || typeof arr === 'undefined') {
  183.             return false;
  184.         }
  185.         // 这里可以通过两种方式来判断
  186.         return arr.constructor === Array || arr.prototype.toString.call(arr) === '[object Array]';
  187.     },
  188. })


  189. /**
  190. * 事件监听的核心代码
  191. */
  192. $.extend($, {
  193.     /**
  194.      * 实现一个兼容各大浏览器的事件监听方法
  195.      * @param id 对象的ID
  196.      * @param type 事件类型:click, mouseover, mouseout……
  197.      * @param fn 事件处理的回调函数
  198.      */
  199.     on: function (id, type, fn) {
  200.         //var dom = this.$id(id);             // 获取这个dom对象
  201.         // 这种写法的好处:(三目运算符的使用,增强框架的健壮性)
  202.         // 1. 可以直接解析DOM节点
  203.         // 2. 可以直接把传过来的ID号码转换为DOM节点
  204.         var dom = !$.isString(id) ? id : document.getElementById(id);
  205.         // 如果浏览器支持addEventlistener方法
  206.         if (dom.addEventListener) {
  207.             // W3C
  208.             dom.addEventListener(type, fn, false);
  209.         } else {
  210.             // 微软公司提供的时间监听方法(不支持事件冒泡的方法)
  211.             if (dom.attachEvent) {
  212.                 // btn.attachEvent('onclick', fn)
  213.                 dom.attachEvent('on' + type, fn);
  214.             }
  215.         }
  216.     },
  217.     /**
  218.      * 用于解除事件的绑定(兼容浏览器)【使用较少】
  219.      * @param id
  220.      * @param type
  221.      * @param fn
  222.      */
  223.     un : function (id, type, fn) {
  224.         // 这里先换一种方式来判断
  225.         var dom = !$.isString(id) ? id : document.getElementById(id);
  226.         // 判断浏览器是否兼容某种特效
  227.         if (dom.removeEventListener){
  228.             // 标准的W3c方式
  229.             dom.removeEventListener(type, fn);
  230.         } else if (dom.attachEvent){
  231.             // 微软的解除方式
  232.             dom.detachEvent(type, fn);
  233.         }
  234.     },
  235.     /**
  236.      * 鼠标点击事件
  237.      * @param id
  238.      * @param fn
  239.      */
  240.     click : function (id, fn) {
  241.         this.on(id, 'click', fn);
  242.     },
  243.     /**
  244.      * 鼠标进入事件
  245.      * @param id
  246.      * @param fn
  247.      */
  248.     mouseover : function (id, fn) {
  249.         this.on(id, 'mouseover', fn);
  250.     },
  251.     /**
  252.      * 鼠标移出事件
  253.      * @param id
  254.      * @param fn
  255.      */
  256.     mouseout : function (id, fn) {
  257.         this.on(id, 'mouseout', fn);
  258.     },
  259.     /**
  260.      * 鼠标移入移出【鼠标悬浮事件】
  261.      * @param id
  262.      * @param fnOver
  263.      * @param fnOut
  264.      */
  265.     hover : function (id, fnOver, fnOut) {
  266.         if (fnOver){
  267.             this.on(id, 'mouseover', fnOver);
  268.         }
  269.         if (fnOut){
  270.             this.on(id, 'mouseout', fnOut);
  271.         }
  272.     },

  273.     /**
  274.      * 用于获取Event对象(解决了浏览器的兼容性问题)
  275.      * @param e
  276.      * @returns {Event}
  277.      */
  278.     getEvent : function (e) {
  279.         return e ? e : window.event;
  280.     },
  281.     /**
  282.      * 使用短路表达式来进行代码优化(尽量少用if语句)
  283.      * @param e
  284.      * @returns {*|Event | undefined}
  285.      */
  286.     getEvent : function (e) {
  287.         return e || window.event;
  288.     },
  289.     /**
  290.      * 获取事件目标对象(兼容性)
  291.      * @param e
  292.      * @returns {Element | any}
  293.      */
  294.     getTarget : function (e) {
  295.         // 获取事件目标
  296.         var e = this.getEvent(e);
  297.         // 使用短路表达式去获取目标
  298.         return e.target || e.srcElement;
  299.     },
  300.     /**
  301.      * 阻止默认事件的行为(兼容性)
  302.      * @param e
  303.      */
  304.     preventDefault : function (e) {
  305.         var ev = this.getEvent(e)
  306.         // 三木表达式阻止默认事件
  307.         ev.preventDefault ? ev.preventDefault() : (ev.returnValue = false);
  308.     },
  309.     /**
  310.      * 阻止事件冒泡(兼容性)
  311.      * 防止事件向外传播
  312.      * @param e
  313.      */
  314.     stopPropagation : function (e) {
  315.         // 获取事件Event对象,解除事件冒泡
  316.         this.getEvent(e).stopPropagation || (this.getEvent(e).cancelBubble = true);
  317.     },
  318.     /**
  319.      * 使用委托的方式实现事件
  320.      * @param pid
  321.      * @param eventType
  322.      * @param selector
  323.      * @param fn
  324.      */
  325.     delegate: function(pid, eventType, selector, fn) {
  326.         var parent = $.$id(pid);
  327.         function handle(e) {
  328.             var target = $.getTarget(e);
  329.             // 这里会打印输出nodeName
  330.             console.log(target.nodeName);       // tr
  331.             // select 这里传过来的是一个选择器, selector == 'tr'
  332.             if (target.nodeName.toLowerCase() === selector || target.id === selector || target.className.indexOf(selector) != -1){
  333.                 // 使用call修改了this的指向, 去调用fn传过来的函数, 把当前的这个target对象传过去
  334.                 fn.call(target);
  335.             }
  336.         }
  337.         parent[eventType] = handle;
  338.     }
  339. })



  340. /**
  341. * 选择器的操作
  342. */
  343. $.extend($, {
  344. // 根据ID,Tag获取对象-------------------------------------------------------------------------
  345.     /**
  346.      * 根据ID获取对象
  347.      * @param id
  348.      * @returns {HTMLElement | null}
  349.      */
  350.     $id: function (id) {
  351.         return document.getElementById(id)
  352.     },
  353.     /**
  354.      * 根据tagName获取对象
  355.      * @param tag
  356.      * @returns {any}
  357.      */
  358.     $tag: function (tag) {
  359.         return document.getElementsByTagName(tag)
  360.     },
  361.     $class : function () {
  362.         
  363.     }
  364. })





复制代码






上一篇:修复Vmvare安装完成后启动虚拟机错误:二进制转换与此平台长模式不兼容……
下一篇:WEBGL开发视频+文档资料PDF(WEBGL,Three.js,JavaScript中英文学习资料)
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案; 如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题加上【已解决】。
回复过本主题
的还回复过:

0

主题

15

帖子

32

积分

新手上路

Rank: 1

积分
32
发表于 2019-1-11 18:46:39 | 显示全部楼层
厉害了 楼主
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

微信扫一扫

我爱科技论坛(www.52tech.tech)旨在打造全网最大的免费资源共享平台。目前论坛包括考研资料、编程学习、黑科技/科学上网、开源软件等资源模块,竭力服务于正在学习道路上的每一个人。我爱科技论坛,爱科技,更爱分享。致力于营造一个资源丰富、内容完善的大型网络学习交流资源共享平台!

QQ|Archiver|手机版|小黑屋|我爱科技论坛 快乐学习交流

(请勿发布违反中华人民共和国法律法规的言论,会员观点不代表我爱科技论坛的官方立场)

Powered by Discuz! X3.4© 2001-2013 Technology Inc.

返回顶部 返回列表