本文由AI辅助撰写，可能存在不准确之处，请读者注意甄别！在文章《让MathJax更好地兼容谷歌翻译和延时加载》中，原作者探讨了Cool Papers引入MathJax解析LaTeX公式后的兼容性问题。虽已解决部分问题，但在Cool Papers中，MathJax与Markdown渲染库Marked之间的冲突依然存在。这篇文章将专注于如何完美解决这个问题。问题背景Markdown是一种轻量级的标记语言，广泛用于编写文档。Cool Papers使用的Kimi功能输出的是Markdown语法，并通过Marked库在前端将其转换为HTML。然而，LaTeX公式与Markdown有部分语法重合，这导致Marked可能会错误处理LaTeX代码，导致MathJax无法正确渲染公式。一个简单的代码展示了问题所在： 在这段代码中，\\(a^2 + b^2\\)和\\\\(c^2 + d^2\\\\)代表LaTeX公式，但只有后者能被MathJax正确渲染。原因是Marked误解析了部分LaTeX代码，导致公式失效。已有解决方案目前，社区已经提出了几种解决MathJax与Marked冲突的方法：手动转义：通过手动修改LaTeX代码以适应Marked的解析方式，虽然有效但不直观，且Cool Papers使用的公式是自动生成的，不能轻易修改。保护公式：将LaTeX代码放在代码块中避免被Marked解析，但这种方式容易与实际的代码块混淆。更换引擎：使用更好的渲染引擎，如Pandoc，但这种方案主要针对后端，前端渲染没有很好的替代方案。修改Marked引擎：修改Marked的规则，避免其解析LaTeX代码。但这种方式治标不治本，需要不断手动调整规则。这些方案都存在一定的局限性，因此我们需要一个更加优雅的解决方案。逆向思路：先MathJax，后Marked问题的根源在于Marked与MathJax的渲染顺序——Marked会误解析LaTeX代码。那么，如果我们反过来处理，先用MathJax渲染公式，再用Marked处理Markdown内容，这样便可以从根本上解决问题。以下是实现该思路的代码： 该方案能够让MathJax优先处理LaTeX公式，确保公式能够被正确解析，然后再由Marked处理剩余的Markdown内容。进一步优化尽管上述方案能够有效解决问题，但对于有“强迫症”的用户来说，仍有两个小瑕疵：1. 初始页面显示乱码在渲染完成之前，用户会短暂看到未处理的Markdown文本，类似乱码。为了改善这一体验，可以在渲染完成后再将内容显示给用户： 通过在隐藏的元素中进行渲染，用户可以直接看到最终渲染结果，避免看到中间的乱码。2. MathJax菜单消失另一个问题是，MathJax自带的右键菜单功能消失了。原因是，重新渲染HTML内容时，绑定在公式上的事件监听器被移除了。为了解决这个问题，可以在Markdown解析后，重新调用MathJax的Typeset方法来渲染公式： 在此代码中，删除已渲染的公式并重新调用Typeset确保MathJax功能正常。3. 保存原始公式代码Marked会错误解析嵌入的 通过这种方式，我们能够避免Marked对公式进行错误解析，同时保证MathJax的正常渲染。结论通过逆向思路，先用MathJax处理公式，再用Marked渲染Markdown，我们可以有效解决MathJax与Marked的冲突问题，并进一步通过优化，提升页面的显示效果和用户体验。这种方法不仅适用于前端渲染的场景，也可以为后端渲染提供参考。参考资料：近乎完美地解决MathJax与Marked的冲突 - 科学空间|Scientific Spaces给自己的站点增加基于MathJax的LaTeX公式支持 - 知乎
在项目\js\lay-module\layuimini\miniTab.js文件中，修改listenSwitch方法：listenSwitch: function (options) { options.filter = options.filter || null; options.multiModule = options.multiModule || false; options.urlHashLocation = options.urlHashLocation || false; options.listenSwichCallback = options.listenSwichCallback || function () { }; element.on('tab(' + options.filter + ')', function (data) { console.log('页面切换123........'); var tabId = $(this).attr('lay-id'); if (options.urlHashLocation) { location.hash = '/' + tabId; } if (typeof options.listenSwichCallback === 'function') { options.listenSwichCallback(); } // 判断是否为新增窗口 if ($('.layuimini-menu-left').attr('layuimini-tab-tag') === 'add') { $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no') } else { $("[layuimini-href]").parent().removeClass('layui-this'); if (options.multiModule) { miniTab.listenSwitchMultiModule(tabId); } else { miniTab.listenSwitchSingleModule(tabId); } $(".layui-tab-item.layui-show").find("iframe")[0].contentWindow.location.reload(); //尝试刷新 } miniTab.rollPosition(); }); },在最后一行加上$(".layui-tab-item.layui-show").find("iframe")[0].contentWindow.location.reload(); //尝试刷新如下图所示：参考文章：https://icode.best/i/52249049464567https://blog.csdn.net/weixin_44828157/article/details/115290927
前言Laydate选择时间模块在手机使用时需要先手动在框里点击一下的问题在一年前困扰我和学长许久（都是这方面的强迫症，没办法）。记得去年有一次（不止一次尝试解决这个问题）我独自尝试用js的focus等事件通过条件对焦的方法调试了一晚上，看着眼花缭乱的父子DOM结点变化而无法在互联网上查阅到任何一种有效监听方法的绝望仍然记忆犹新。为减小Laydate的兼容性bug对请假系统项目体验的不良影响，学长在项目中写了前端代码通过增大可选时间跨度以及根据当前时间展示可选范围。然而我们当时万万没想到的是：正确解决这个前端问题的方法竟然是两行CSS代码。分析既然JavaScript无从解决，那就从CSS下手：分析到时间选择列表ol对应的overflow属性值为hidden，其作用包括溢出隐藏、清除浮动和解决外边距塌陷（点击查看详情）的意思，其中触发visible的默认条件是hover。然而手机端触发hover必须得点一下，而PC端只需将光标移上即可。因此，只需修改overflow对应的属性即可完美解决问题：/* 允许手机端laydate选择时间时上下滑动 */ .laydate-time-list ol{ overflow-x: hidden !important; overflow-y:auto !important; }目前，该解决方案已部署于我的毕设和学生请假系统git项目及正式环境中。总结通过今天晚上（昨天晚上今天凌晨）在请假系统项目的实战中对CSS和汉字编码有了更深一步的理解。参考资料：https://www.php.cn/css-tutorial-412426.htmlhttps://www.w3school.com.cn/tags/tag_ol.asphttps://blog.csdn.net/boysky0015/article/details/72824172https://blog.csdn.net/Start2019/article/details/116226021https://blog.csdn.net/qq_41638795/article/details/83304388
前言近日在毕设中引入了搜索框，巧妙设计前端样式后遇到了在点击搜索按钮时搜索框失去焦点事件与点击搜索按钮事件冲突的现象，并且浏览器会优先执行blur事件从而导致click事件无法执行。知识下面是关于二者的介绍：blur事件：当元素失去焦点时触发blur事件；早前，blur 事件仅发生于表单元素上。在新浏览器中，该事件可用于任何元素，blur和focus事件不会冒泡，其他表单事件都可以。click事件：当点击元素时触发click事件；所有元素都有此事件，会产生冒泡。至于为什么会出现上述问题：Javascript为单线程，同一时间只能执行处理一个事件，所以当blur执行时，会导致其后续click事件并不会执行。解决方法一：让click事件比blur事件先触发，可以给blur事件加定时器延迟触发：/*删除图标的点击事件*/ $(".delete-icon").on("click",function () { $(this).prev("input").val("").focus(); }); /*输入框失去焦点的blur事件*/ $("input[name='username'],input[name='password']").on("blur",function () { var $this = $(this); setTimeout(function(){ $this.parent().removeClass("active"); $this.next(".delete-icon").hide(); },250) });缺点：设置多久的延时是一个难以两全的问题，时间太短不能保证click事件的100%触发，时间太长则会造成卡顿的感觉，影响用户体验方法二：将click事件改为mousedown事件，mousedown事件会优先于blur事件执行/*删除图标的点击事件*/ $(".delete-icon").on("mousedown",function () { $(this).prev("input").val("").focus(); }); /*输入框失去焦点的blur事件*/ $("input[name='username'],input[name='password']").on("blur",function () { var $this = $(this); $this.parent().removeClass("active"); $this.next(".delete-icon").hide(); });缺点：鼠标按下便触发了事件，不收起、长按也会触发，可能在特殊场景下造成用户体验不好（足够满足我的需求了）方法三：给图标再添加一个mousedown事件，在其中执行event.preventDefault()阻止浏览器默认事件，这样点击按钮时输入框就不会失去焦点了/*阻止浏览器默认事件*/ $(".delete-icon").on("mousedown",function(e) { e.preventDefault(); }) /*删除图标的点击事件*/ $(".delete-icon").on("click",function () { $(this).prev("input").val("").focus(); }); /*输入框失去焦点的blur事件*/ $("input[name='username'],input[name='password']").on("blur",function () { var $this = $(this); $this.parent().removeClass("active"); $this.next(".delete-icon").hide(); });方法四：动态绑定blur事件，当鼠标进入input框父级元素时，移除input绑定事件blur，当鼠标移出输入框父级元素时，给input绑定blur事件/*动态绑定blur事件*/ $(".login-con li").mouseenter(function(){ $(this).find("input").unbind("blur"); }); $(".login-con li").mouseleave(function(event){ $(this).find("input").bind("blur"); }); /*删除图标的点击事件*/ $(".delete-icon").on("click",function () { $(this).prev("input").val("").focus(); }); /*输入框失去焦点的blur事件*/ $("input[name='username'],input[name='password']").on("blur",function () { var $this = $(this); $this.parent().removeClass("active"); $this.next(".delete-icon").hide(); });方法三、四几乎没缺点（欢迎大佬们留言补充），可以优先考虑。旁通该方案亦可解决下图所示问题：参考资料：https://www.jianshu.com/p/791b30924c1ahttps://www.w3school.com.cn/jquery/event_blur.asphttps://blog.csdn.net/ligang2585116/article/details/51764828
本文转载自互联网，已在文末注明来源。本人后续将把实践中积累的相关经验归并总结到本文中。题纲关于跨域，有N种类型，本文只专注于ajax请求跨域(,ajax跨域只是属于浏览器"同源策略"中的一部分,其它的还有Cookie跨域iframe跨域,LocalStorage跨域等这里不做介绍)，内容大概如下:什么是ajax跨域原理表现(整理了一些遇到的问题以及解决方案)如何解决ajax跨域JSONP方式CORS方式代理请求方式如何分析ajax跨域http抓包的分析一些示例什么是ajax跨域ajax跨域的原理ajax出现请求跨域错误问题,主要原因就是因为浏览器的“同源策略”,可以参考浏览器同源政策及其规避方法(阮一峰)CORS请求原理CORS是一个W3C标准，全称是"跨域资源共享"（Cross-origin resource sharing）。它允许浏览器向跨源服务器，发出XMLHttpRequest请求，从而克服了AJAX只能同源使用的限制。基本上目前所有的浏览器都实现了CORS标准,其实目前几乎所有的浏览器ajax请求都是基于CORS机制的,只不过可能平时前端开发人员并不关心而已(所以说其实现在CORS解决方案主要是考虑后台该如何实现的问题)。关于CORS，强烈推荐阅读 跨域资源共享 CORS 详解(阮一峰)另外，这里也整理了一个实现原理图(简化版):如何判断是否是简单请求?浏览器将CORS请求分成两类：简单请求（simple request）和非简单请求（not-so-simple request）。只要同时满足以下两大条件，就属于简单请求。请求方法是以下三种方法之一：HEAD,GET,POSTHTTP的头信息不超出以下几种字段：AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type(只限于三个值application/x-www-form-urlencoded、 multipart/form-data、text/plain)凡是不同时满足上面两个条件，就属于非简单请求。ajax跨域的表现说实话，当初整理过一篇文章，然后作为了一个解决方案，但是后来发现仍然有很多人还是不会。无奈只能耗时又耗力的调试。然而就算是我来分析，也只会根据对应的表现来判断是否是跨域，因此这一点是很重要的。ajax请求时,如果存在跨域现象,并且没有进行解决,会有如下表现:(注意，是ajax请求，请不要说为什么http请求可以，而ajax不行，因为ajax是伴随着跨域的，所以仅仅是http请求ok是不行的)注意:具体的后端跨域配置请看题纲位置。第一种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 404出现这种情况的原因如下：本次ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS)服务器端后台接口没有允许OPTIONS请求,导致无法找到对应接口地址解决方案: 后端允许options请求第二种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 405这种现象和第一种有区别,这种情况下，后台方法允许OPTIONS请求,但是一些配置文件中(如安全配置),阻止了OPTIONS请求,才会导致这个现象解决方案: 后端关闭对应的安全配置第三种现象:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且status 200这种现象和第一种和第二种有区别,这种情况下，服务器端后台允许OPTIONS请求,并且接口也允许OPTIONS请求,但是头部匹配时出现不匹配现象比如origin头部检查不匹配,比如少了一些头部的支持(如常见的X-Requested-With头部),然后服务端就会将response返回给前端,前端检测到这个后就触发XHR.onerror,导致前端控制台报错解决方案: 后端增加对应的头部支持第四种现象:heade contains multiple values '*,*'表现现象是，后台响应的http头部信息有两个Access-Control-Allow-Origin:*说实话，这种问题出现的主要原因就是进行跨域配置的人不了解原理，导致了重复配置，如:常见于.net后台(一般在web.config中配置了一次origin,然后代码中又手动添加了一次origin(比如代码手动设置了返回*))常见于.net后台(在IIS和项目的webconfig中同时设置Origin:*)解决方案(一一对应):建议删除代码中手动添加的*，只用项目配置中的即可建议删除IIS下的配置*，只用项目配置中的即可如何解决ajax跨域一般ajax跨域解决就是通过JSONP解决或者CORS解决,如以下:(注意，现在已经几乎不会再使用JSONP了，所以JSONP了解下即可)JSONP方式解决跨域问题jsonp解决跨域问题是一个比较古老的方案(实际中不推荐使用),这里做简单介绍(实际项目中如果要使用JSONP,一般会使用JQ等对JSONP进行了封装的类库来进行ajax请求)实现原理JSONP之所以能够用来解决跨域方案,主要是因为 脚本拥有跨域能力,而JSONP正是利用这一点来实现。具体原理如图实现流程JSONP的实现步骤大致如下(参考了来源中的文章)客户端网页网页通过添加一个 元素，向服务器请求JSON数据，这种做法不受同源政策限制function addScriptTag(src) { var script = document.createElement('script'); script.setAttribute("type","text/javascript"); script.src = src; document.body.appendChild(script); } window.onload = function () { addScriptTag('http://example.com/ip?callback=foo'); } function foo(data) { console.log('response data: ' + JSON.stringify(data)); }; 请求时,接口地址是作为构建出的脚本标签的src的,这样,当脚本标签构建出来时,最终的src是接口返回的内容服务端对应的接口在返回参数外面添加函数包裹层foo({ "test": "testData" }); 由于 元素请求的脚本，直接作为代码运行。这时，只要浏览器定义了foo函数，该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象，而不是字符串，因此避免了使用JSON.parse的步骤。注意,一般的JSONP接口和普通接口返回数据是有区别的,所以接口如果要做JSONO兼容,需要进行判断是否有对应callback关键字参数,如果有则是JSONP请求,返回JSONP数据,否则返回普通数据使用注意基于JSONP的实现原理,所以JSONP只能是“GET”请求,不能进行较为复杂的POST和其它请求,所以遇到那种情况,就得参考下面的CORS解决跨域了(所以如今它也基本被淘汰了)CORS解决跨域问题CORS的原理上文中已经介绍了，这里主要介绍的是，实际项目中，后端应该如何配置以解决问题(因为大量项目实践都是由后端进行解决的)，这里整理了一些常见的后端解决方案:PHP后台配置PHP后台得配置几乎是所有后台中最为简单的,遵循如下步骤即可:第一步:配置Php 后台允许跨域<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept'); //主要为跨域CORS配置的两大基本信息,Origin和headers第二步:配置Apache web服务器跨域(httpd.conf中)原始代码<Directory /> AllowOverride none Require all denied </Directory>改为以下代码<Directory /> Options FollowSymLinks AllowOverride none Order deny,allow Allow from all </Directory>Node.js后台配置(express框架)Node.js的后台也相对来说比较简单就可以进行配置。只需用express如下配置:app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS"); res.header("X-Powered-By", ' 3.2.1') //这段仅仅为了方便返回json而已 res.header("Content-Type", "application/json;charset=utf-8"); if(req.method == 'OPTIONS') { //让options请求快速返回 res.sendStatus(200); } else { next(); } });JAVA后台配置JAVA后台配置只需要遵循如下步骤即可:第一步:获取依赖jar包下载 cors-filter-1.7.jar, java-property-utils-1.9.jar 这两个库文件放到lib目录下。(放到对应项目的webcontent/WEB-INF/lib/下)第二步:如果项目用了Maven构建的,请添加如下依赖到pom.xml中:(非maven请忽视)<dependency> <groupId>com.thetransactioncompany</groupId> <artifactId>cors-filter</artifactId> <version>[ version ]</version> </dependency>其中版本应该是最新的稳定版本,CORS过滤器第三步:添加CORS配置到项目的Web.xml中( App/WEB-INF/web.xml) <filter> <filter-name>CORS</filter-name> <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class> <init-param> <param-name>cors.allowGenericHttpRequests</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.allowOrigin</param-name> <param-value>*</param-value> </init-param> <init-param> <param-name>cors.allowSubdomains</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>cors.supportedMethods</param-name> <param-value>GET, HEAD, POST, OPTIONS</param-value> </init-param> <init-param> <param-name>cors.supportedHeaders</param-name> <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value> </init-param> <init-param> <param-name>cors.exposedHeaders</param-name> <param-value>X-Test-1, X-Test-2</param-value> </init-param> <init-param> <param-name>cors.supportsCredentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.maxAge</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <filter-name>CORS</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>请注意,以上配置文件请放到web.xml的前面,作为第一个filter存在(可以有多个filter的)第四步:可能的安全模块配置错误(注意，某些框架中-譬如公司私人框架，有安全模块的，有时候这些安全模块配置会影响跨域配置，这时候可以先尝试关闭它们)JAVA Spring Boot配置20171230补充仅列举简单的全局配置@Configuration public class CorsConfig { private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); // 可以自行筛选 corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); return corsConfiguration; } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); return new CorsFilter(source); } }新建配置，然后添加Configuration注解即可配置成功PS：这一部分方法是收录的，没有亲身实践过，但根据反馈，理论上可行NET后台配置.NET后台配置可以参考如下步骤:第一步:网站配置打开控制面板，选择管理工具,选择iis;右键单击自己的网站，选择浏览;打开网站所在目录,用记事本打开web.config文件添加下述配置信息,重启网站请注意,以上截图较老,如果配置仍然出问题,可以考虑增加更多的headers允许,比如:"Access-Control-Allow-Headers":"X-Requested-With,Content-Type,Accept,Origin" 第二步:其它更多配置,如果第一步进行了后,仍然有跨域问题，可能是:接口中有限制死一些请求类型(比如写死了POST等)，这时候请去除限 制接口中，重复配置了Origin:*，请去除即可IIS服务器中，重复配置了Origin:*，请去除即可代理请求方式解决接口跨域问题注意，由于接口代理是有代价的，所以这个仅是开发过程中进行的。与前面的方法不同，前面CORS是后端解决，而这个主要是前端对接口进行代理，也就是:前端ajax请求的是本地接口本地接口接收到请求后向实际的接口请求数据，然后再将信息返回给前端一般用node.js即可代理关于如何实现代理，这里就不重点描述了，方法和多，也不难，基本都是基于node.js的。搜索关键字node.js,代理请求即可找到一大票的方案。OPTIONS预检的优化Access-Control-Max-Age: 这个头部加上后，可以缓存此次请求的秒数。在这个时间范围内，所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据。非常有用，可以大幅优化请求次数如何分析ajax跨域上述已经介绍了跨域的原理以及如何解决，但实际过程中，发现仍然有很多人对照着类似的文档无法解决跨域问题，主要体现在，前端人员不知道什么时候是跨域问题造成的，什么时候不是，因此这里稍微介绍下如何分析一个请求是否跨域:抓包请求数据第一步当然是得知道我们的ajax请求发送了什么数据，接收了什么，做到这一步并不难，也不需要fiddler等工具，仅基于Chrome即可Chrome浏览器打开对应发生ajax的页面，F12打开Dev Tools发送ajax请求右侧面板->NetWork->XHR，然后找到刚才的ajax请求，点进去示例一(正常的ajax请求)上述请求是一个正确的请求，为了方便，我把每一个头域的意思都表明了，我们可以清晰的看到，接口返回的响应头域中，包括了Access-Control-Allow-Headers: X-Requested-With,Content-Type,Accept Access-Control-Allow-Methods: Get,Post,Put,OPTIONS Access-Control-Allow-Origin: *所以浏览器接收到响应时，判断的是正确的请求，自然不会报错，成功的拿到了响应数据。示例二(跨域错误的ajax请求)为了方便，我们仍然拿上面的错误表现示例举例。这个请求中，接口Allow里面没有包括OPTIONS，所以请求出现了跨域、这个请求中，Access-Control-Allow-Origin: *出现了两次，导致了跨域配置没有正确配置，出现了错误。更多跨域错误基本都是类似的，就是以上三样没有满足(Headers,Allow,Origin)，这里不再一一赘述。示例三(与跨域无关的ajax请求)当然，也并不是所有的ajax请求错误都与跨域有关，所以请不要混淆，比如以下:比如这个请求，它的跨域配置没有一点问题，它出错仅仅是因为request的Accept和response的Content-Type不匹配而已。更多基本上都是这样去分析一个ajax请求，通过Chrome就可以知道了发送了什么数据，收到了什么数据，然后再一一比对就知道问题何在了。原文地址：https://segmentfault.com/a/1190000012469713
通过Ajax以表单的形式提交多变量键值对： function AJAX(b64) { var xmlhttp; if (window.XMLHttpRequest) { // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码 xmlhttp = new XMLHttpRequest(); } else { // IE6, IE5 浏览器执行代码 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { document.getElementById("myDiv").innerHTML = xmlhttp.responseText; } } xmlhttp.open("POST", "/try/ajax/demo_post.php", true); xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xmlhttp.send( "test=" + encodeURIComponent('123456') + "&b64value=" + encodeURIComponent(b64) ); }参考文章：https://www.runoob.com/ajax/ajax-xmlhttprequest-send.htmlhttps://www.itbaoku.cn/post/49055.htmlhttps://blog.csdn.net/KingJin_CSDN_/article/details/53156864https://blog.csdn.net/qq_34549618/article/details/78480128https://www.cnblogs.com/han-1034683568/p/7199168.htmlhttps://www.w3cschool.cn/ajax/ajax-uy1r2or1.html
未成功的方法记录第一种：在浏览器中点击返回或者前进按钮时，页面不刷新的问题。如果是移动端下，可能有两种情况：第一种是在自己的app下点击返回的时候页面不刷新，这有可能是你们原生开发人员，只是关闭了当前的一个窗口，也就是说那个窗口是新开的。这种解决方案，老夫只能说找你们的原生开发吧。第二种则是在微信、uc这类的浏览器出现，这是因为浏览器保存了DOM和js的状态，相当于保存了整个页面，这种特性称作 “往返缓存”（back-forward cache，或bfcache）。对于这种情况可以用“pageshow”事件来解决，“pageshow”事件表示浏览器展示文档的时候触发，并且是在“onload”事件之后触发。如果浏览器是存在往返缓存机制的话，那么onload事件就只会触发一次，而“pageshow”事件则每次都会触发。这里需要注意“pageshow”事件必须绑定在window这个对象中，可根据以下方法来让浏览器刷新如下代码：window.addEventListener('pageshow', function(event) { //event.persisted属性为true时，表示当前文档是从往返缓存中获取 if(event.persisted) location.reload(); $(".loading").hide(); });结论：安卓未测试；iOS、Windows测试无效第二种：一、多页面下浏览器返回多页面时浏览器返回的上一个页面如果数据是用ajax加载的则页面会显示不出数据，可以通过以下方法判断在浏览器的返回前进时刷新当前页面，以下方法放到jquery的ready或者HTML的onload方法里，主要针对移动端H5开发function backForwardListen(){ //window.performance.navigation.type=2表示当前页面行为是history.back()或history.forward() if(window.performance.navigation.type == 2) { reloadDeal(window.location.href);//reloadDeal为监测到前进后退时的处理方法，在这里简单的刷新页面所以把当前页面的链接作为参数传进该方法 } }二、单页面下浏览器返回在单面中通过显示和隐藏不同的部分来模拟页面跳转时，如果触发浏览器返回事件则会关闭当前页面，以下例子可以在触发浏览器返回事件时按自己的需要显示不同的部分，主要针对移动端H5开发功能说明：页面上有tag1,tag2,tag3三个标签，点击某个标签时该标签的背景变红，其他标签背景变白，当前在tag3标签时浏览器返回会改变到tag2，在tag2时会改变到tag1，在tag1时不变，或者可以跳转到其他页面 测试 TAG1 TAG2 TAG3 结论：安卓未测试；iOS、Windows测试无效有效的方法记录需要被刷新的页面：window.addEventListener("pageshow", function(){ if(sessionStorage.getItem("need-refresh")){ location.reload(); sessionStorage.removeItem("need-refresh"); } });触发添加需要刷新条件的页面：sessionStorage.setItem("need-refresh", true); 参考文章备份在做移动端项目的时候经常遇到这样一个功能比如：返回后页面不刷新，一些失效的信息依然显示在页面上。这个问题在iphone手机上会出现，在Android手机上返回时会自动刷新（由于手机机器种类不多，无法做更多测试，欢迎补充）。为了解决这个问题实验了很多解决办法用计时器呀onload呀都不行，后来找到了一个方法pageshow。onpageshow 事件在用户浏览网页时触发。onpageshow 事件类似于 onload 事件，onload 事件在页面第一次加载时触发， onpageshow 事件在每次加载页面时触发，即 onload 事件在页面从浏览器缓存中读取时不触发，此外还有pagehide在不显示的时候触发。为了查看页面是直接从服务器上载入还是从缓存中读取，可以使用 PageTransitionEvent 对象的 persisted 属性来判断。window.addEventListener('pageshow', function(event) { console.log("PageShow Event " + event.persisted); console.log(event) })如果页面从浏览器的缓存中读取该属性返回 ture，否则返回 false。然后在根据true或false在执行相应的页面刷新动作或者直接ajax请求接口更新数据。这一点有个缺陷就是，无论是不是需要更新数据这个页面都会刷新，我们要做的只是数据变化了才需要更新。于是想到另一个办法在可能会出现数据变化的页面设置缓存，即为只要页面数据变化了就写缓存一条记录，在返回页面后检测到这条记录就说明需要页面刷新或调用接口刷新。处理方法为：// a.html 设置刷新 检测缓存是否有标志 要是有就说明数据有变化 a.html跳转到b.html页面 window.addEventListener("pageshow", function(){ if(sessionStorage.getItem("need-refresh")){ location.reload(); sessionStorage.removeItem("need-refresh"); } }); // b.html 如果是数据变化了就写一条缓存 b.html返回到a.html页面 sessionStorage.setItem("need-refresh", true);下面给出测试pageshow等的测试代码：地址http://www.ofoyou.com/blog/pageshow.html 页面显示与隐藏 前往百度 参考资料：https://blog.csdn.net/Angel_girl319/article/details/106348829https://blog.csdn.net/weixin_30271447/article/details/114173037https://blog.csdn.net/immrma/article/details/79428671https://www.cnblogs.com/ivan5277/p/10138838.html
Title 这是菜单1 这是菜单2 这是菜单3 这是菜单4 这是菜单5 这是菜单6 这是菜单7 这是菜单8 效果：原文地址：https://www.cnblogs.com/liubeimeng/p/5509103.html
6月12号晚上，辅助温春阳调试请假系统bug期间，留意到复制绑定密钥时自动复制的需求，想起两年前给电脑120网站配置复制自动复制QQ群号的场景，扒出了当年的代码： 电脑120 <marquee direction="left" scrollamount="7" scrolldelay="10" border="10" width="88%" > 欢迎加入服务群和大家交流计算机问题，群1：322935908，群2：181626714。期待在春暖花开的时节与大家在兰亭116重逢... </marquee> 使用方法 ①群 | ②群 关于我们 Copyright © 2019 电脑120 版权所有 然而没想到这段复制代码在其请假系统上针对iOS设备无论如何都不能生效，于是乎，和学长一起并肩开始了干到近凌晨3点的debug之旅。直接贴出结论吧，最后问题在“缩量”和“断点”等各种神仙调试过后仍然无法解决后由“增量”大法得以找出。问题核心在于iOS针对ajax异步请求做出了“非交互不得复制”的安全措施。（也就是说除非搞个复制按钮上去，否则你的数据就是“自动”进不了它的剪切板）解决方法：对单个页面指定ajax请求指定为同步。前些时候刚做出PHP上传功能，就有了落地需求-->多人同步调试CSS：于是乎：上传插件拿来开干，同时希望大家上传css文件后可以直接手动复制上传的文件地址，复制功能拿来开干：index.html： 上传CSS入口 上传CSS文件（不得超过2M）： upload.php：<?php // 后端验证防止上传超过2M的文件，定义最大值常量 define('MAX_SIZE',2097152); define('MuLu','css/'); // echo $_FILES; 返回Array // print_r($_FILES); // 返回这种结构： /* Array ( [userfile] => Array ( [name] => 1.jpg [type] => image/jpeg [tmp_name] => C:\Users\soarli\AppData\Local\Temp\php5449.tmp [error] => 0 [size] => 376151 ) ) */ // 只允许上传jpg格式的图片 // if ($_FILES['userfile']['type'] != 'image/jpeg' && $_FILES['userfile']['type'] != 'image/png' && $_FILES['userfile']['type'] != 'image/gif') { // echo " "; // exit; // } // 使用以下方法设置格式白名单更加直观 // switch ($_FILES['userfile']['type']){ // case 'image/jpeg': // break; // case 'image/png': // break; // case 'image/gif': // break; // default: echo " "; // exit; // } // 如果上传失败，根据$_FILES的error值判断报错类型并在前端提示 if ($_FILES['userfile']['error'] > 0) { switch ($_FILES['userfile']['error']) { case 1: echo " 上传失败，上传文件超过PHP配置文件限定值大小（后端的限制，由后端发现）！"; break; case 2: echo " 上传失败，上传文件超过HTML表单限定值大小（前端的限制，由后端发现）！"; break; case 3: echo " 上传失败（部分被上传）！"; break; case 4: echo " 上传失败，没有任何部分被上传！"; break; } exit; } // 后端判断上传文件的大小 if($_FILES['userfile']['size'] > MAX_SIZE){ echo " 上传失败，上传文件超过限定值大小（由后端大小检测模块发现）！"; exit; } // 只允许上传图片 $file_Extension_string = strrev($_FILES['userfile']['name']); // 从$_FILES数组中获取name字段并反转字符串 $file_Extension_array = explode('.',$file_Extension_string); // 以.号为分割拆分成为新的数组 $houZhui = strrev($file_Extension_array[0]); // 反转反转过的扩展名字符串存为$houZhui // 以下两行代表的两种方法在实际应用中仅保留第二种即可（第一种抓包篡改Content-Type即可绕过，第二种即便抓包篡改Content-Disposition绕过检测也无法执行后续恶意操作‘后缀名都变了’） $fileMimes = array('text/css'); //允许上传的文件类型，实际应用时记得写前面（方便维护人员调试） $accepted_houzhui = array('css'); //允许上传的文件扩展名类型，实际应用时记得写前面（方便维护人员调试） // 判断类型/后缀是否同时分别包含在两个数组 if (is_array($fileMimes)) { if (!in_array($_FILES['userfile']['type'],$fileMimes) || !in_array($houZhui,$accepted_houzhui)) { echo " 上传失败，请选择css文件上传。（由后端类型检测模块发现）"; exit; } } // 判断目录是否存在，若无则创建 if(!is_dir(MuLu)){ mkdir(MuLu,0777); } // 以上模块均没异常，开始将接收到的临时文件按照本规则重命名并移动到指定目录 if (is_uploaded_file($_FILES['userfile']['tmp_name'])) { if(!move_uploaded_file($_FILES['userfile']['tmp_name'],MuLu.$_FILES['userfile']['name'])){ echo " 【后端错误】文件移动失败！"; exit; } } else { echo " 【后端错误】临时文件夹找不到上传的文件！"; exit; } // 以上都正常执行，则认为文件上传成功，并显示上传成功的提示 $success = 'http://172.28.21.166:20020/upload/css/'.$_FILES['userfile']['name']; echo " "; echo "文件上传成功,地址如下: "; echo $success; echo " 直接返回 复制并返回 点击查看 "; // echo " 文件上传成功！"; // 图片上传成功的提示，随即显示图片预览 // echo " "; ?>
建模实习作业是做一个界面，果断上html+css+js：https://lab.soarli.top/web/html/calc/其中，js监听键盘输入通过document.onkeydown=function(event)方法实现，下面是关于keyCode的总结记录（内容来自互联网，已在文末放置参考资料链接）：js判定不能输入某个字母或符号οnkeydοwn=“if(event.keyCode==32) return false”字母和数字键的键码值(keyCode)（左侧）按键键码按键键码按键键码按键键码A65J74S83149B66K75T84250C67L76U85351D68M77V86452E69N78W87553F70O79X88654G71P80Y89755H72Q81Z90856I73R82048957数字键盘上键的键码值（右侧）按键键码按键键码按键键码0966102Enter1081977103-1092989104.1103999105/1114100*106 5101+107 F键键码值按键键码按键键码F1112F7118F2113F8119F3114F9120F4115F10121F5116F11122F6117F12123控制键键码值(keyCode)按键键码按键键码按键键码按键键码BackSpace8Esc27Right Arrow39-_189Tab9Spacebar32Dw Arrow40.>190Clear12Page Up33Insert45/?191Enter13Page Down34Delete46`~192Shift16End35Num Lock144[{219Control17Home36;:186\ 220Alt18Left Arrow37=+187]}221Cape Lock20Up Arrow38,<188'"222多媒体键码值按键键码音量加175音量减174停止179静音173浏览器172邮件180搜索170收藏171参考资料：https://blog.csdn.net/weixin_44476265/article/details/110531227https://www.cnblogs.com/zhulmz/p/11623685.htmlhttps://www.cnblogs.com/fubuki/p/9835581.html