首页 文章 精选 留言 我的

精选列表

搜索[javascript库],共10000篇文章
优秀的个人博客,低调大师

JavaScript中发布/订阅模式的理解

订阅发布模式的介绍 发布订阅模式,它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到。 在生活中我们常常遇到这样一种情况,我们在使用新闻APP看新闻的时候,每个人喜欢的新闻类型各不一样,比如我喜欢NBA,但是我们总不可能一天24小时在手机上一遍又一遍的刷新,我们就会去新闻频道中选择NBA专栏来收藏,当勇士或者湖人有最新消息,就会通知我们去观看。 当然从上面的场景中是一个典型的发布订阅模式,APP的NBA专栏属于发布者,像我一样广大爱好篮球的小伙伴梦就属于订阅者,当一有最新的消息,它们就会发布给我们。 实际用途 1.在jquery中很多地方都有发布订阅的踪迹,例如事件中on和trigger中封装的方法。 2.尤大大的Vue,中子父组件通信使用的emit()和on()方法,使得组件得到解耦,开发更加高效。 如何实现订阅发布模式 1、首先想好谁是发布者(比如上边的APP的NBA专栏就是发布者); 2、然后给发布者添加一个缓存列表,用于存放回调函数来通知订阅者(比如上面的我们球迷爱好者收藏了NBA专栏,相当于向发布者注入了通知我们的函数); 3、最后就是发布消息,发布者遍历这个缓存列表,依次触发订阅的函数。 表捉急,端起小板凳,先看一下这个简单的发布订阅模式: let NBAcol={};//自定义一个NBA专栏对象 NBAcol.list=[];// 这里放一个列表用来缓存订阅者的回调函数 NBAcol.on=function(fun){ this.list.push(fun); //把fn先存到列表中 }; //发布事件 NBAcol.emit=function(){ this.list.forEach(cb => { cb.apply(this, arguments); });// 当发布的时候再把列表里存的函数依次执行 }; //小明的订阅NBA专栏 NBAcol.on(function(team){ console.log("我订阅的球队是:"+team) }) //小李的订阅NBA专栏 NBAcol.on(function(team){ console.log("我订阅的球队是:"+team) }) NBAcol.emit('湖人'); NBAcol.emit('勇士'); /* 我订阅的球队是:湖人; 我订阅的球队是:湖人; 我订阅的球队是:勇士; 我订阅的球队是:勇士; */ 上面就实现了一个简单的订阅发布模式,不过从打印结果来看,有些尴尬,因为其实,小明只想订阅湖人,小李要订阅勇士。可是专栏都给他们推送了,显然不太合理。之所以出现这种情况是因为在执行on方法的时候将订阅函数列表中的函数依次都执行了。所以我们要对代码进行改造,我们可以先增加一个key,使订阅者只订阅自己感兴趣的消息。 let NBAcol={};//自定义一个NBA专栏对象 NBAcol.list={};// 这里放一个列表用来缓存订阅者的回调函数 NBAcol.on=function(key,fun){ // 如果还没有订阅过此类消息,给该类消息创建一个缓存列表 if(!this.list[key]){ this.list[key]=[]; } this.list[key].push(fun); //把fn先存到列表中 }; //发布事件 NBAcol.emit=function(){ let key=Array.prototype.shift.call(arguments);// 取出消息类型名称 let funs=this.list[key];//匹配对应的回调函数的结合 if(!funs||funs.length===0){//如果没有订阅过消息,则return; return; }; funs.forEach(fun => { fun.apply(this, arguments); });// 当发布的时候再把列表里存的函数依次执行 }; //小明的订阅NBA专栏 NBAcol.on('xiaomin',function(team){ console.log("我订阅的球队是:"+team) }) //小李的订阅NBA专栏 NBAcol.on('xiaoli',function(team){ console.log("我订阅的球队是:"+team) }) NBAcol.emit('xiaomin','湖人'); NBAcol.emit('xiaoli','勇士'); /* 我订阅的球队是:湖人; 我订阅的球队是:勇士; */ 这样子就可以啦,这个订阅发布的核心功能已经体现了。 如何取消事件的订阅 比如上面的列子,假如我们订阅了很多东西,不喜欢的时候我们要取消订阅,该怎么办呢?看如下代码: NBAcol.remove=function(key, fun) { // 这回我们加入了取消订阅的方法 let funs = this.list[key]; // 如果缓存列表中没有函数,返回false if (!funs) return false; // 如果没有传对应函数的话 // 就会将key值对应缓存列表中的函数都清空掉 if (!fun) { funs && (funs.length = 0); } else { // 遍历缓存列表,看看传入的fun与哪个函数相同 // 如果相同就直接从缓存列表中删掉即可 funs.forEach((cb, i) => { if (cb === fun) { funs.splice(i, 1); } }); } } // 取消dog方法的订阅 NBAcol.remove('xiaoli',function(team){ console.log("我订阅的球队是:"+team) }); 这样就可以取消订阅啦,但是实际的开源代码中,封装远比这要复杂,比如要考虑订阅数量,还有多模块订阅的封装等等,所以在这里我们还得在实际的业务模块中详细考虑。 发布订阅模式的缺点: 当然一个任何一个东西都是有两面性的,同样发布订阅模式存在以下问题: 1、创建订阅者需要消耗一定的时间和内存。 2、虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等。 原文发布时间为:2018年06月24日 原文作者:viyoung 本文来源:掘金 如需转载请联系原作者

优秀的个人博客,低调大师

Javascript:npm模块安装机制简介

正因为有了npm,我们只要一行命令,就能安装别人写好的模块 。 $ npm install 1 本文介绍 npm 模块安装机制的细节,以及如何解决安装速度慢的问题。 一、从npm install说起 npm install 命令用来安装模块到node_modules目录。 $ npm install <packageName> 1 安装之前,npm install会先检查,node_modules目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也是如此。 如果你希望,一个模块不管是否安装过,npm 都要强制重新安装,可以使用-f或–force参数。 $ npm install <packageName> --force 1 二、npm update 如果想更新已安装模块,就要用到npm update命令。 $ npm update <packageName> 1 它会先到远程仓库查询最新版本,然后查询本地版本。如果本地版本不存在,或者远程版本较新,就会安装。 三、registrynpm update命令怎么知道每个模块的最新版本呢? 答案是 npm 模块仓库提供了一个查询服务,叫做 registry 。以 npmjs.org 为例,它的查询服务网址是https://registry.npmjs.org/。 这个网址后面跟上模块名,就会得到一个 JSON 对象,里面是该模块所有版本的信息。比如,访问https://registry.npmjs.org/react,就会看到 react 模块所有版本的信息。 它跟下面命令的效果是一样的。 $ npm view react # npm view 的别名 $ npm info react $ npm show react $ npm v react 1 2 3 4 5 registry 网址的模块名后面,还可以跟上版本号或者标签,用来查询某个具体版本的信息。比如, 访问https://registry.npmjs.org/react/v0.14.6,就可以看到 React 的 0.14.6 版。 返回的 JSON 对象里面,有一个dist.tarball属性,是该版本压缩包的网址。 dist: { shasum: '2a57c2cf8747b483759ad8de0fa47fb0c5cf5c6a', tarball: 'http://registry.npmjs.org/react/-/react-0.14.6.tgz' }, 1 2 3 4 到这个网址下载压缩包,在本地解压,就得到了模块的源码。npm install和npm update命令,都是通过这种方式安装模块的。 四、缓存目录npm install或npm update命令,从 registry 下载压缩包之后,都存放在本地的缓存目录。 这个缓存目录,在 Linux 或 Mac 默认是用户主目录下的.npm目录,在 Windows 默认是%AppData%/npm-cache。通过配置命令,可以查看这个目录的具体位置。 $ npm config get cache $HOME/.npm 1 2 你最好浏览一下这个目录。 $ ls ~/.npm # 或者 $ npm cache ls 1 2 3 你会看到里面存放着大量的模块,储存结构是{cache}/{name}/{version}。 $ npm cache ls react ~/.npm/react/react/0.14.6/ ~/.npm/react/react/0.14.6/package.tgz ~/.npm/react/react/0.14.6/package/ ~/.npm/react/react/0.14.6/package/package.json 1 2 3 4 5 每个模块的每个版本,都有一个自己的子目录,里面是代码的压缩包package.tgz文件,以及一个描述文件package/package.json。 除此之外,还会生成一个{cache}/{hostname}/{path}/.cache.json文件。比如,从 npm 官方仓库下载 react 模块的时候,就会生成registry.npmjs.org/react/.cache.json文件。 这个文件保存的是,所有版本的信息,以及该模块最近修改的时间和最新一次请求时服务器返回的 ETag 。 { "time":{ "modified":"2016-01-06T23:52:45.571Z", // ... }, "_etag":"\"7S37I0775YLURCFIO8N85FO0F\"" } 1 2 3 4 5 6 7 对于一些不是很关键的操作(比如npm search或npm view),npm会先查看.cache.json里面的模块最近更新时间,跟当前时间的差距,是不是在可接受的范围之内。如果是的,就不再向远程仓库发出请求,而是直接返回.cache.json的数据。 .npm目录保存着大量文件,清空它的命令如下。 $ rm -rf ~/.npm/* # 或者 $ npm cache clean 1 2 3 五、模块的安装过程 总结一下,Node模块的安装过程是这样的。 发出npm install命令 npm 向 registry 查询模块压缩包的网址 下载压缩包,存放在~/.npm目录 解压压缩包到当前项目的node_modules目录 注意,一个模块安装以后,本地其实保存了两份。一份是~/.npm目录下的压缩包,另一份是node_modules目录下解压后的代码。 但是,运行npm install的时候,只会检查node_modules目录,而不会检查~/.npm目录。也就是说,如果一个模块在~/.npm下有压缩包,但是没有安装在node_modules目录中,npm 依然会从远程仓库下载一次新的压缩包。 这种行为固然可以保证总是取得最新的代码,但有时并不是我们想要的。最大的问题是,它会极大地影响安装速度。即使某个模块的压缩包就在缓存目录中,也要去远程仓库下载,这怎么可能不慢呢? 另外,有些场合没有网络(比如飞机上),但是你想安装的模块,明明就在缓存目录之中,这时也无法安装。 六、–cache-min 参数 为了解决这些问题,npm 提供了一个--cache-min参数,用于从缓存目录安装模块。 --cache-min参数指定一个时间(单位为分钟),只有超过这个时间的模块,才会从 registry 下载。 $ npm install --cache-min 9999999 <package-name> 1 上面命令指定,只有超过999999分钟的模块,才从 registry 下载。实际上就是指定,所有模块都从缓存安装,这样就大大加快了下载速度。 它还有另一种写法。 $ npm install --cache-min Infinity <package-name> 1 但是,这并不等于离线模式,这时仍然需要网络连接。因为现在的--cache-min实现有一些问题。 (1)如果指定模块不在缓存目录,那么 npm 会连接 registry,下载最新版本。这没有问题,但是如果指定模块在缓存目录之中,npm 也会连接 registry,发出指定模块的 etag ,服务器返回状态码304,表示不需要重新下载压缩包。 (2)如果某个模块已经在缓存之中,但是版本低于要求,npm会直接报错,而不是去 registry 下载最新版本。 1 2 3 npm 团队知道存在这些问题,正在重写 cache。并且,将来会提供一个--offline参数,使得 npm 可以在离线情况下使用。 不过,这些改进没有日程表。所以,当前使用--cache-min改进安装速度,是有问题的。 七、离线安装的解决方案 社区已经为npm的离线使用,提出了几种解决方案。它们可以大大加快模块安装的速度。 解决方案大致分成三类。 第一类,Registry 代理。 npm-proxy-cache local-npm(用法) npm-lazy 1 2 3 上面三个模块的用法很类似,都是在本机起一个 Registry 服务,所有npm install命令都要通过这个服务代理。 # npm-proxy-cache $ npm --proxy http://localhost:8080 \ --https-proxy http://localhost:8080 \ --strict-ssl false \ install # local-npm $ npm set registry http://127.0.0.1:5080 # npm-lazy $ npm --registry http://localhost:8080/ install socket.io 1 2 3 4 5 6 7 8 9 10 11 有了本机的Registry服务,就能完全实现缓存安装,可以实现离线使用。 第二类,npm install替代。 如果能够改变npm install的行为,就能实现缓存安装。npm-cache工具就是这个思路。凡是使用npm install的地方,都可以使用npm-cache替代。 $ npm-cache install 1 第三类,node_modules作为缓存目录。 这个方案的思路是,不使用.npm缓存,而是使用项目的node_modules目录作为缓存。 Freightnpmbox 上面两个工具,都能将项目的node_modules目录打成一个压缩包,以后安装的时候,就从这个压缩包之中取出文件。 原文发布时间:2018-6-19 原文作者: 阮一峰 本文来源csdn博客如需转载请紧急联系作者

优秀的个人博客,低调大师

Javascript 开启浏览器全屏模式

通常在某些情况下,我们需要让浏览器开启全屏模式,以便获得更好的视觉体验,先看下全屏模式简单的几个API。 浏览器默认绑定 非全屏模式下, document的F11按键绑定开启全屏模式 全屏模式下, document的esc和F11 按键绑定关闭全屏模式 屏幕全屏模式改变事件 当成功进入全屏模式后, document会收到一个fullscreenchange 事件。 当退出全屏状态后, document又会收到fullscreenchange 事件。 varscreenChange='webkitfullscreenchange'||'mozfullscreenchange'||'fullscreenchange' 判断当前是否处于全屏状态 非标准: varisFullScreen=document.fullScreen||document.mozFullScreen||document.webkitIsFullScreen; 标准: varisFullScreen=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement 开启全屏模式 functionlaunchFullScreen(element){ if(element.requestFullscreen){ element.requestFullscreen(); }elseif(element.mozRequestFullScreen){ element.mozRequestFullScreen(); }elseif(element.webkitRequestFullscreen){ element.webkitRequestFullscreen(); }elseif(element.msRequestFullscreen){ element.msRequestFullscreen(); } } 注意:requestFullscreen是规范的书写模式( s是小写), 但在Gecko内核中仍使用带前缀的大写模式mozRequestFullScreen。 关闭全屏模式 functionexitFullscreen(){ if(document.exitFullscreen){ document.exitFullscreen(); }elseif(document.mozCancelFullScreen){ document.mozCancelFullScreen(); }elseif(document.webkitExitFullscreen){ document.webkitExitFullscreen(); } 全屏模式只能由手势触发 了解API后,假如我们监听window.onload事件执行launchFullScreen方法,Chrome浏览器会提示“开启全屏模式API只能由用户手势触发”。 "Failed to execute 'requestFullScreen' on 'Element': API can only be initiated by a user gesture." 原因是浏览器采用安全的机制, 将这种强制全屏模式意为“恶意行为”,一切非用户主观意愿带来的变化都是不允许的。 因此如果你的应用有全屏需求,有两种方案。 1.页面初始化给用户一个“F11开启全屏” 的提示, 并且在延迟几秒之后消失。 2.页面设置一个全屏按钮,单击全屏按钮进入全屏模式,并且隐藏按钮(视觉效果最佳)。 对于第二种方案,需要监听键盘事件: document.addEventListener("keydown",function(e){ varcurrKey=0 //在FireFox或Opera中,隐藏的变量e是存在的,那么e||event返回e,如果在IE中,隐藏变量e是不存在,则返回event。 vare=e||event; //IE中,只有keyCode属性,而FireFox中有which和charCode属性,Opera中有keyCode和which属性 varcurrKey=e.keyCode||e.which||e.charCode; if(currKey==112){ launchFullScreen(); } },false); 具备了兼容各种浏览器按键模式的监听,但不知道keycode肿么办,112是哪个键? 字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 74 S 83 1 49 B 66 K 75 T 84 2 50 C 67 L 76 U 85 3 51 D 68 M 77 V 86 4 52 E 69 N 78 W 87 5 53 F 70 O 79 X 88 6 54 G 71 P 80 Y 89 7 55 H 72 Q 81 Z 90 8 56 I 73 R 82 0 48 9 57 数字键盘上的键的键码值(keyCode) 按键 键码 按键 键码 0 96 8 104 1 97 9 105 2 98 * 106 3 99 + 107 4 100 Enter 108 5 101 – 109 6 102 . 110 7 103 / 111 功能键键码值(keyCode) 按键 键码 按键 键码 F1 112 F7 118 F2 113 F8 119 F3 114 F9 120 F4 115 F10 121 F5 116 F11 122 F6 117 F12 123 控制键键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 BackSpace 8 Esc 27 Right Arrow 39 -_ 189 Tab 9 Spacebar 32 Dw Arrow 40 .> 190 Clear 12 Page Up 33 Insert 45 /? 191 Enter 13 Page Down 34 Delete 46 `~ 192 Shift 16 End 35 Num Lock 144 [{ 219 Control 17 Home 36 ;: 186 \ 220 Alt 18 Left Arrow 37 =+ 187 ]} 221 Cape Lock 20 Up Arrow 38 ,< 188 ‘“ 222 避免使用非标准化的方法 非标准化的方法指的是进入草案前浏览器实现的一些方法,避免使用。window.fullScreen(Firefox)HTMLMediaElement.webkitDisplayingFullscreenHTMLMediaElement.webkitEnterFullscreenHTMLMediaElement.webkitExitFullscreenHTMLMediaElement.webkitSupportsFullscreen 原文发布时间:2018-6-19 原文作者:伯乐在线 本文来源csdn博客如需转载请紧急联系作者

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册