jQuery-UI mouse.js源码解读

2023-11-02 22:48

本文主要是介绍jQuery-UI mouse.js源码解读,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.总体架构

为两类事件提供接口,点击事件和拖拽事件,其中点击事件需要向元素添加preventClickEvent,以阻止默认的表单提交或文件上传事件发生。

两类事件都是通过向元素绑定mouseDown事件触发函数发生。

点击事件在_mouseDown函数中判断配置项中是否要求延时以及拖拽距离,如果没有,在_mouseDown函数中触发_mouseStart函数,并记录_mouseStarted(两次点击有效),第二次点击的时候调用_mouseUp函数,触发用户定义的_mouseStop函数,mouseStop函数里向元素添加preventClickEvent,该事件有过多疑问处;

拖拽事件在_mouseDown向文档节点绑定mousemove和mouseup事件,mouseMove事件中执行用户定义的_mouseStart函数,并记录_mouseStarted,方便第二次移动的时候直接判断该值,调用_mouseDrag函数,_mouseUp函数中执行_mouseStop函数。

 

2.插件的使用

配置项options

包括cancel(免于交互的element元素)、delay(规定的延时,在_mouseMove中判断该值,由结果决定_mouseDrag是否被触发)、distance(规定的移动距离,同样在_mouseMove中判断该值,由结果决定_mouseDrag是否被触发)

方法

_mouseDelayMet判断是否有延时;

_mouseDistanceMet判断移动距离是否符合要求;

_mouseInit绑定mousedown和click事件,click事件需要判断元素的preventClickEvent属性,由此决定是否执行;

_mouseDown将事件拆分成点击事件和拖拽事件两类,由配置项决定是否有函数被执行,点击事件触发_mouseUp和_mouseStart、_mouseStop函数,拖拽事件先向文档节点绑定mousemove、mouseup事件,再触发_mouseMove、_mouseUp和_mouseStart、_mouseDrag、_mouseStop函数;

_mouseMove拖拽事件触发_mouseStart、_mouseDrag函数;

_mouseUp触发_mouseStart函数;

接口

_mouseCapture返回否时意味着不触发交互事件;

_mouseDown鼠标按下时触发的函数;

_mouseDrag鼠标移动时触发的函数;

_mouseUp鼠标松开时触发的函数。

 

 http://api.jqueryui.com/mouse/

 

3.JS及jQuery的新认识

在类中的function函数中,使用self或that代替this,用来指代类,避免this值可能的变更;

closest()从当前元素开始,沿着dom树向上寻找,包含当前元素;

parentsUntil()向上遍历寻找父级元素,传入的参数是遍历的截止位置;

contents()查询文本节点和html元素节点,可以获取iframe内的元素节点,部分功能同find();

event.pageX.left/top鼠标偏离文档编辑器的坐标;

event.which鼠标左键值为1,中键为2,右键为3,没有按鼠标为0;

event.button判断鼠标按键,ie9开始和标准浏览器相同,左键为0,中键为1,右键为2,ie8左键为1,中键为4,右键为2。

 

// 使用自调用匿名函数将构建的function函数作为factory的实参,define未定义时使用require模块化工具,否则将jquery传入function函数中
( function( factory ) {if ( typeof define === "function" && define.amd ) {define( ["jquery","../ie","../version","../widget"], factory );} else {factory( jQuery );}
}( function( $ ) {// 各记录项mouseHandled、_mouseMoved、_mouseStarted在事件过程中记录为真,开始时为否则不执行该事件,事件结尾记录为否
// mouseHandled鼠标按下时判断,mousedown函数结尾处记录为真,阻止其他widget部件触发事件,鼠标松开时记录为否,代表执行完毕
// _mouseMoved鼠标按下时记录为否,鼠标移动时记录为真,处理间歇性的两次鼠标移动事件
/** * _mouseStarted当mouseStart返回值为真时记录为真,mouseUp事件开始的时候将其置为false,mousedrag执行前需要为真* _mouseDown函数中mouseStart启动需要无延时、无移动距离,鼠标按下触发mouseStart函数,直接跳转至mouseUp函数,mouseUp函数中执行mouseStop函数,没有执行mouseMove函数* _mouseMove函数中mouseStart启动时可以有延时,需要移动距离,鼠标移动时触发mouseMove函数,mouseMove函数中执行mouseStart、mouseDrag函数,最终跳转到mouseUp函数,并执行mouseStop函数* _mouseMove函数随着鼠标每移动一个像素点反复执行,*/
// mouseDelayMet为否时有延时,options.delay存在时延时触发,mouseDelayMet延时过程中赋值为真
var mouseHandled = false;
$( document ).on( "mouseup", function() {mouseHandled = false;
} );return $.widget( "ui.mouse", {version: "@VERSION",options: {cancel: "input, textarea, button, select, option",// 免于交互的元素distance: 1,delay: 0},// 绑定mouseDown事件,同时click不触发点击事件,this.started记录初始化是否完成// click事件包含mousedown和mouseup事件_mouseInit: function() {var that = this;this.element.on( "mousedown." + this.widgetName, function( event ) {return that._mouseDown( event );} ).on( "click." + this.widgetName, function( event ) {if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {$.removeData( event.target, that.widgetName + ".preventClickEvent" );// 包含阻止事件冒泡stopPropgation的功能之外,也阻止该元素绑定的同类型事件event.stopImmediatePropagation();return false;}} );this.started = false;},/** *  mouseDown函数中率先判断是否为无延时、无移动距离的事件,是则执行mouseStart函数,即鼠标按下时触发的函数*  不是则在文档节点上绑定mousemove、mouseup事件,先后触发mouseStart、mouseMove函数,即鼠标移动时触发的函数*/// mouseDestory函数用于在事件结尾处清空绑定在文档节点上的事件,问题是mouseUp函数中已经解除绑定???_mouseDestroy: function() {this.element.off( "." + this.widgetName );if ( this._mouseMoveDelegate ) {this.document.off( "mousemove." + this.widgetName, this._mouseMoveDelegate ).off( "mouseup." + this.widgetName, this._mouseUpDelegate );}},_mouseDown: function( event ) {if ( mouseHandled ) {return;}this._mouseMoved = false;// _mouseStarted两次点击的时候有有效值?促发_mouseUp函数???( this._mouseStarted && this._mouseUp( event ) );this._mouseDownEvent = event;var that = this,btnIsLeft = ( event.which === 1 ),// 鼠标左键// event.target.nodeName works around a bug in IE 8 with disabled inputs (#7620)// closest()从当前元素开始,沿着dom树向上寻找,包含当前元素// 不是鼠标左键点击,或者触发元素是表单元素及其子元素,或者_mouseCapture函数返回为否,则推出mouseDown函数,mouseCapture返回为否禁用交互事件elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ? $( event.target ).closest( this.options.cancel ).length : false );if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {return true;}// setTimeout回调函数的异步机制,后续代码块会先执行,即有延迟事件delay或规定距离distance的时候,后一条语句不被执行// 在function中,用that代替this,避免this值可能发生的变化this.mouseDelayMet = !this.options.delay;if ( !this.mouseDelayMet ) {this._mouseDelayTimer = setTimeout( function() {that.mouseDelayMet = true;}, this.options.delay );}// 点击事件触发时event怎样传入回调函数中???event的C++接口原理???// distance和delay均为0、mouseStart有返回值的情况,利用if语句执行mouseStart函数,阻止默认事件,如提交表单、按钮上传文件按钮// 语句的作用是设置鼠标按下时的事件,_mouseStart即是_mousedown事件触发时执行的函数,取代默认的点击事件if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {this._mouseStarted = ( this._mouseStart( event ) !== false );if ( !this._mouseStarted ) {event.preventDefault();return true;}}/*** mouse.js将事件分为两类,一类是鼠标按下又松开,和点击事件起冲突,需要记录preventClickEvent阻止默认的点击事件,这一类事件触发的函数是mouseDown、mouseUp、mouseStart、mouseStop* 另一类是鼠标按下后移动了一段距离再松开,和点击事件没有冲突,不需要preventClickEvent阻止默认的点击事件,这一类事件触发的函数是mouseDown、mouseMove、mouseUp、mouseStart、mouseDrag、mouseStop*/if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {$.removeData( event.target, this.widgetName + ".preventClickEvent" );}this._mouseMoveDelegate = function( event ) {return that._mouseMove( event );};this._mouseUpDelegate = function( event ) {return that._mouseUp( event );};this.document.on( "mousemove." + this.widgetName, this._mouseMoveDelegate ).on( "mouseup." + this.widgetName, this._mouseUpDelegate );event.preventDefault();mouseHandled = true;return true;},_mouseMove: function( event ) {	//随着鼠标移动反复执行// 怎样判断ie中鼠标越出文档范围,以及safari的跨iframe拖拽的问题???// Only check for mouseups outside the document if you've moved inside the document// at least once. This prevents the firing of mouseup in the case of IE<9, which will// fire a mousemove event if content is placed under the cursor. See #7778// Support: IE <9if ( this._mouseMoved ) {// IE mouseup check - mouseup happened when mouse was out of window// documentMode文档兼容模式,低版本中没有,判断ie渲染页面的方式,也即ie的版本// event.button判断鼠标按键,ie9开始和标准浏览器相同,左键为0,中键为1,右键为2,ie8左键为1,中键为4,右键为2if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button ) {return this._mouseUp( event );// Iframe mouseup check - mouseup occurred in another document} else if ( !event.which ) {// Support: Safari <=8 - 9// Safari sets which to 0 if you press any of the following keys// during a drag (#14461)// event.originalEvent保存了浏览器原生事件对象,是jquery的机制,altkey指alt键被点击且保持状态if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||event.originalEvent.metaKey || event.originalEvent.shiftKey ) {this.ignoreMissingWhich = true;} else if ( !this.ignoreMissingWhich ) {return this._mouseUp( event );}}}// event.which鼠标左键值为1,中键为2,右键为3,没有按鼠标为0,mouseDown函数中有要求event.which为1???if ( event.which || event.button ) {this._mouseMoved = true;}// 鼠标未松开时第二次移动时,_mouseStarted和_mouseMoved记录在案,方便调用if ( this._mouseStarted ) {this._mouseDrag( event );return event.preventDefault();}// 移动距离、延迟时间合乎规范的时候调用mouseStart和mouseDrag函数,延迟时间从鼠标按下时计时,定时mouseDelayMet变为真if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {this._mouseStarted =( this._mouseStart( this._mouseDownEvent, event ) !== false );( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );}return !this._mouseStarted;},_mouseUp: function( event ) {this.document.off( "mousemove." + this.widgetName, this._mouseMoveDelegate ).off( "mouseup." + this.widgetName, this._mouseUpDelegate );if ( this._mouseStarted ) {this._mouseStarted = false;// 鼠标按下又松开的事件,没有向文档节点绑定事件,mouseDown和mouseUp事件中的事件元素相同,鼠标移动事件绑定了文档节点if ( event.target === this._mouseDownEvent.target ) {$.data( event.target, this.widgetName + ".preventClickEvent", true );}this._mouseStop( event );}if ( this._mouseDelayTimer ) {clearTimeout( this._mouseDelayTimer );delete this._mouseDelayTimer;}this.ignoreMissingWhich = false;mouseHandled = false;event.preventDefault();},// 当前事件的坐标和鼠标按下时的坐标相比较得出水平及垂直距离_mouseDistanceMet: function( event ) {return ( Math.max(Math.abs( this._mouseDownEvent.pageX - event.pageX ),Math.abs( this._mouseDownEvent.pageY - event.pageY )) >= this.options.distance);},_mouseDelayMet: function( /* event */ ) {return this.mouseDelayMet;},// _mouseCapture决定交互是否应该基于交互的事件目标开始,返回为否的时候禁用交互事件// _mouseStart处理交互的开始,_mouseDrag处理鼠标移动事件,_mouseStop交互的结束_mouseStart: function( /* event */ ) {},_mouseDrag: function( /* event */ ) {},_mouseStop: function( /* event */ ) {},_mouseCapture: function( /* event */ ) { return true; }
} );} ) );

这篇关于jQuery-UI mouse.js源码解读的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/333827

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

MCU7.keil中build产生的hex文件解读

1.hex文件大致解读 闲来无事,查看了MCU6.用keil新建项目的hex文件 用FlexHex打开 给我的第一印象是:经过软件的解释之后,发现这些数据排列地十分整齐 :02000F0080FE71:03000000020003F8:0C000300787FE4F6D8FD75810702000F3D:00000001FF 把解释后的数据当作十六进制来观察 1.每一行数据

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL