最近在做兼容多浏览器能跨域访问的本地存储实施方案。一开始打算是用localStorage加userData的方式实现,支持localStorage的使用localStorage,不支持的(IE6,7)使用userData;本域下的直接调用,需要跨域的则加载对应域名下的crossdomain.html作为iframe,然后调用iframe里面的contentWindow来实现。

想法是很好的,也实现了很多功能,但是在实现之后的的评审和准备应用阶段,却发现了很多开发的时候没有注意到的问题。

Document Limit/Doamin Limit

可以看看下面的表格,在每个域名下的存储限制是1M,这个很多很令人满意,但是还有个Document Limit在当初使用的时候却忽略了。userData的实现方式就是加载一个放在用户文件夹下的XML文件,在里面进行I/O操作。这每一个XML文件就是一个Document。而操作的时候,必须明确指定加载哪个XML文件。这就和localStorage的实现方式上有了很大的差别,不利于统一。而且单个Document的大小是128KB,这个很难保证后期能否足够使用。

Security Zone Document Limit (KB) Domain Limit (KB)
Local Machine 128 1024
Intranet 512 10240
Trusted Sites 128 1024
Internet 128 1024
Restricted 64 640

same directory and same protocol to access

上面那个文档的大小限制和明确指定加载的XML文件,还不算很坑的。因为短时间内128KB肯定是足够使用的,也可以在实施方案里面统一各域名下加载同一个名称的XML就好了。也就是看起来像每个域名下只有128kb的存储空间。

可是下面这个限制就很坑了。

对于userData,数据之间的划分,不单单是域名,协议和端口号这三个。它还更加严格的以文档路径进行划分,对的,不用怀疑:http://www.demo-domain.com/test/index.html是没法访问到http://www.demo-domain.com/test2/index.html里面的userData数据的。

当然,这个也能绕开,就是在使用userData的情况下,所有的I/O操作都是走的iframe,哪怕是同域名下。然后给所有域名的根域放置一个crossdomain.html。但是这样的实施方法确实有点复杂

can’t be set/get in <head>

接着还有问题,这个问题是个使用上的限制。在公司的应用环境里,有些情况,需要在加载head的时候,就能读到本地的数据,然后做一个是否跳转的判断。而userData绑定的标签是不包括head里面能放置的那些。所以很不幸userData无法实现

而且通常的使用方式是认为的createElement,然后在这个element上面进行文档的绑定。而在IE6下,向文档插入dom是必须要在document.ready之后进行的,不然会容易出现问题

can’t clear and Traversal(like function key in localStorage)

最后一个问题,在实施方案里面,公开的接口都是仿造localStorage的接口。其中有两个接口clear(清空所有内容)和key(遍历本地数据)。这两个接口使用的场景不多,但是肯定是会有使用到的时候,可惜userData的官方文档里面并没有看到有这相关的接口提供。

所以,因为上面这么多的问题,只好忍痛放弃已经开发完的localStorage和userData的组合,改为使用localStorage和FlashCookie的组合。

方法一

今天在做一个兼容且可跨越的localStorage的实施方案,打算使用github进行项目的代码管理和版本控制。工作环境是Windows,用的git工具是msysgit。

git clone,git commit,git push。这一套下来工作的很流畅,很正常,可是有一点比较麻烦,就是每次push的时候,总是要输入一次在github上面的帐号和密码。就想着能不能在本地存储这个帐号和密码,每次push的时候就自动提交这个去验证。

Google了一下,在一个github的帮助教程的快照上面看到了详细的关于如何在push到远程仓库时,不同系统下面如何去保存验证信息。其中提到了一个软件:git-credential-winstore,这个是专门在Windows下面用来管理git的验证信息的。然后在github的官方帮助文档:上面,找到了软件的官方地址(其实上面那个快照对应的就是下面那个地址的,可能是github更新了,所以内容有些不同,过段时间,Google那边更新快照之后应该就相同了)

可是在安装git-credential-winstore.exe的时候出了问题,会提示无法识别git,软件里面给的解决方式有两种:

  1. 在系统的环境变量PATH里面加上git的安装目录
  2. 通过cmd进行安装 安装使用如下命令行

明确的指定git所在位置

git-credential-winstore.exe -i C:Program Files(x86)Gitcmdgit.exe

可惜这两种方式我试过了都失败了。最后在这个文章上才找到解决方式:git-credential-winstore.exe必须放到git的安装目录里面,在bin/文件夹下。

安装这篇文章里面指示的放置文件之后,双击安装,还是报之前的错误。不过幸运的是,通过cmd的方式进行安装成功了。

原因应该是我的环境变量设定有问题吧,不清楚C:Program Files(x86)Gitcmd和C:Program Files(x86)Gitbin应该使用哪一个,这两个目录下面都是有git.exe的。

安装完成之后,就是如何在git里面配置和使用了。

在最开始看的那篇文章里面,说的配置是这样的

git config --global credential.helper cache

作用是启用验证信息缓存功能

可是我按上面的配置之后,在push的时候,却提示:‘credential-cache’ is not a git command

很明显,配置有问题的,可是git实在是新手,只好再次Google之,然后在Stack Overflow上面看到了这个帖子
说在Windows下面,那个配置中的cache应该改成winstore,正确的命令应该是这样的:

git config --global credential.helper winstore

按照这个命令重新执行了下,果然可以,在第一次push的时候,会有个弹窗,让你输入在github上面的帐号和密码,然后再次push的时候,就不必再输入帐号和密码了。

估计那篇文章里面使用cache,是指的在Linux下的吧,而在Windows下面使用git-credential-winstore来管理验证信息,所以credential.helper就应该是winstore

方法二

昨天(20150310),有个同事介绍了一个我认为使用上虽然啰嗦一点但是更便捷的方法,虽然在安全性上,有点无法保障。在这里跟大家介绍一下,也可以看这里原文地址

直接进入正题,步骤如下:
1. Windows中添加一个用户变量(开始-系统-高级系统设置-环境变量),名称为:HOME,值为%USERPROFILE%
设置用户变量
2. 在“开始-运行”中输入%Home%后确定,在打开的文件夹下新建一个名为_netrc的文件。
运行%Home%
新建_netrc文件
3. 用记事本打开_netrc文件,输入Git服务器名、用户名、密码,并保存,例如:

machine git.yourserver.org ---- git服务器名称
login yourlogin@email.com ---- git用户名
password yourpassword123 ---- git账号密码

关于localStorage,在简单不过的接口,getItem,setItem,removeItem,clear,key.这些大家都很了解,可是也有一些细节,如果不注意的话也是可能导致一些问题的。

支持范围

localStorage的支持范围比想象的要广很多,市面上手机端和PC端的浏览器,除开IE,几乎都支持(指从很低版本就开始支持),而一向拖后腿的IE,在IE8中也是支持localStorage的。所以,放心使用吧!以下是各浏览器下的支持情况:

IE FIREFOX SAFARI CHROME OPERA IPHONE ANDROID
8.0+ 3.5+ 4.0+ 4.0+ 10.5+ 2.0+ 2.0+

来源限制

localStorage对来源的认定是根据以下规则:协议+域名+端口

协议

http:// 里面的数据和 https:// 里面的是分离的

所以http://www.demo-domain.com/下面localStorage里面的数据,在https://www.demo-domain.com/里面是没法访问到的

域名

域名是必须完全一致的,下属的二级,三级域名都是没法访问根域名下面的数据的。

所以http://t.www.demo-domain.com/是没法访问到http://www.demo-domain.com/页面里面localStorage的数据

端口

这个比较少见,大部分对外公开的网站,都是默认的80端口。同域名和协议,但是端口不同的页面,也是没法共享localStorage的数据的

比如:http://www.demo-domain.com:8080/ 页面是没法访问 http://www.demo-domain.com/ 页面中的localStorage数据

浏览器的“模式”

现在很多浏览器都提供了“匿名访问”,“安全模式”,“隐身窗口”等等功能。在这种情况下,浏览器都是会重新建立一个新的localStorage,所以这些模式下的页面是没法访问在正常模式下的页面中的数据。

借鉴的文章地址:http://htmlui.com/blog/2011-08-23-5-obscure-facts-about-html5-localstorage.html

起因

在知乎上面看一个关于回调函数的帖子时,有人为了表明观点,就给了个链接说是代码示例.好奇心强大,就点了过去.然后就发现了这么个前端代码在线调试和分享的利器–jsFiddle

jsFiddle的主要用途

个人觉得jsFiddle有下面几个使用场景:

  • 写代码的时候,(可能是html,可能是css,也可能是js,有些东西没把握或者不清楚,但是现有的工程复杂度太高,不好直接拿来测试.重新建立个html文件然后写doctype,html,head…这个过程又太麻烦。可能环境搭建好,想法也没了。这个时候比较直接的方式就是打开浏览器,地址栏输入jsFiddle.net。然后立马开始需要进行的测试工程。
  • 写技术博客或者回复评论(前提是这个评论支持加入iframe)的时候,需要展示一些代码。需要面临两个问题:一个是好的代码高亮,二是代码的实际运行结果。有些网站有这个功能(也许wordpress也有这样的插件,只是我还没接触到),一个展示代码的文本框,下面一个按钮“运行代码”,点击就会跳转到另一个页面看代码的实际运行效果。但是在jsFiddle的代码分享就有个比较好的地方,通过tab选项卡的方式可以方便的切换显示html,css,js的代码和实际的运行效果。当然,这个对于小片段的代码最有优势,如果是太复杂的效果则肯能不是很适合了
  • jsFiddle还有一个git思想的fork功能,这样就很方便你在查看别人代码的同时,能进行简单的修改调试,这样能进一步的理解

一些使用方面的技巧

jsFiddle网站本身也提供了很详细的使用文档,不过只有英文版的,英文还不错的同学可以看这里

界面介绍

界面有两种状态,一种是没保存前也就是通过地址直接访问的时候,一种是在前一种状态中点击顶部菜单中的”save”之后

两种状态的主要区别也是在顶部菜单栏。

两种状态下的菜单栏

保存之前的菜单

保存之前的菜单

保存之后的菜单

保存之后的菜单

第一种状态中特殊的按钮是”save”,可以把当前编辑的项目保持到jsFiddle的服务器上面,这样方便再次查看和分享

第二种状态中特殊的按钮有”update”,”fork”,”base”/”set as base”和”share”

像”update”和”fork”都是类似github的方式

“update”就是将当前状态保存为一个版本,方便调试(只有初始版本和update版本,这两个版本).

“fork”就是把当前的项目复制到一个新建项目中

“base”按钮出现在没有进行过”update”或者最初版本的项目中,表明这是最初始的版本,点击没效果,只是标识作用

“set as base”相反,出现在非初始版本的项目中。可点击,作用是把当前版本变成最初版本,原先的初始版本会被删除

“share”点击之后会展开一个面板,提供三种形式的分享方式

  • 一个是当前项目的地址,进入后看到的和作者当前看到的内容一样
  • 一个是全屏的tab选项卡展示代码和结果。不过默认提供的只是结果的展示。需要了解url的规则才好自定义
  • 第三种其实就是用iframe引用的第二个的地址。
    还有4个公用的菜单按钮

  • “run” 是执行代码,点击之后就能在右下角的result区域看到代码执行的结果
  • “debug on mobile”(就是那个类似手机上表示信号的图标), 是用来进行手机端调试使用的
  • “TidyUp” 是整洁代码
  • “JSHint” 是js的错误检查

代码编辑区

代码编辑区

代码编辑区

分为四个区块,分别是html,css,js的输入区域,和代码运行的结果展示区域result

可以拖动区块直接的框去控制各个区块的大小

功能区

功能区

功能区

功能区在代码编辑区的左侧

Framework&Extensions 是程序需要用到的类库,有jQuery,YUI,ExtJs,Dojo等等,但是很可惜,国内的KISSY貌似没有的

Fiddle Options

  • Name,Description 是对当前代码的一个命名和描述,方便以后在个人平台上面查看
  • Normalized CSS 这个是选择是否加载一个reset css的文件,去除一些浏览器默认添加的样式
  • Body tag 可以自定义body标签,这个是考虑到某些类库需要给body标签添加类或者别的属性
  • DTD 定义html文档的类型申明,默认是html5的
  • Framework attribute 用来定义加载类库的script标签上面的一些属性

编写代码

草稿

对于登录的用户,对于当前正在编辑的jsfiddle里面的代码,只要你点击过run,那么就可以通过访问jsfiddle.net/draft/ 来查看看看运行过的代码的执行页面,展示的内容和result里面一样。

这样做的一个很大的好处是:能够方便的比较在不同浏览器下,代码的执行结果的不同,当然,前提是在不同的浏览器下,得先登录了。

分享代码

jsFiddle里面,除了能够很方便开发者去写一些demo之外,很大的一个好处就是高度可自定义的设定分享的展示方式。在点击save按钮之后,得到的页面地址,只要把这个地址发送给你想分享的对象,那么对方就能通过这个地址看到和你save之后一模一样的界面。同时,点击share按钮,在弹出菜单里面Share link里面的值也就是这个值。Embed on your page,这个里面是一个html代码,可以放在你的文章里面,方便在文章中添加代码。就比如我这个

还有一种http://jsfiddle.net/shuizhongyueming/L49jh/embedded/result/。这个地址是可以配置的,在地址的embedded后面,有四种无序参数:html,css,js,result 以逗号分隔,只要在地址里面按需加入需要的即可。同样,那个IFrame的src值也是可以这样设定的
比如,如果我想向人分享我的demo里面的js和result。那么我可以http://jsfiddle.net/shuizhongyueming/L49jh/embedded/js,result/。那么demo的展示页面里面,就会有两个tab页,顺序和地址里面的顺序一致。

结语

以上差不多是我所知的关于jsfiddle的全部东西了。欢迎指正和补充

凄惨的经历

一杯水引发的惨案

今天在公司上班,因为干活比较用心,喝水的时候也盯着电脑,喝完之后就随便把杯子放笔记本边上,结果一个不小心,水就撒了一部分到键盘上。当时没怎么在意,随便拿个餐巾纸吸掉表面的水就继续干活,顺便跟个妹子聊天。

结果没两分钟,开始不对劲了,在编辑器里面,一直在触发换行,换别的软件获取焦点之后也是这样——原来是Enter键出毛病了,连按了几次之后,Enter事件不再被触发,但是按Enter键也没得效果。这个时候知道事情大条了,赶紧找公司的网管救命。

网管知道经过之后,一脸佩服的看着我,一般人电脑进水之后都是立马断电源拔电池的,我倒好,还这么悠闲的跟妹子聊天…..

检查的结果很不理想——就是网管也不知道是哪出问题了,但是帮我把键盘进水的键拔出来仔细擦干了藏在内里的水,然后告诉我:去维修点修吧,要是还在保修期,千万别说是进水了,不在维修期待话,破费一笔是难免的。

当时我对破费一笔的概念还停留在两三百多境界。

辛酸的维修过程

公司在中关村,经过网管指点,找维修点倒也简单,在鼎好电子商城的地下二层,A001就是(话说对于我后来修电脑的地方到底是不是联想到官方维修店,我是有点怀疑的,因为我找到了A005,A004,按照摊位的延续,到那家店也差不多是A001,可是偏偏那个店没在店名上挂个联想的名字或者logo,也没有牌子表明序号)。

在维修点,维修人员弄个仪器左测测右弄弄。在那个时候,我的心情还是比较悠闲的,因为两三百块钱虽然很心疼,但还是能接受的,我就在他们检测的时候在一边拿手机看小说去了。最后,给出个答案——硬盘损坏

话说这个解释一出来,我挺惊讶的,报修的时候按照网管的指点,我没说是电脑进水而是说突然的就这么开不了机,反正怎么显得自己小白就怎么说,这样保修的时候可以避免自身的责任。可是硬盘损坏,这个跟进水貌似没有什么关联。我有点怀疑对方是不是想坑我的钱,就拿出一个杀手锏:Enter键不能用——这个总不能也跟硬盘坏联系上吧。可是对方又说他们也发现这个问题了,因为boot的时候没法按Enter键进入子菜单。可是在把硬盘移除之后,Enter键就能使用。这我就没解了,而且对方也保证了,要是最后换了硬盘之后,Enter键也没用就是他们的责任。这个时候,只能暂时承认是硬盘坏了,等着他们报价维修了。

硬盘损坏,换硬盘,320G的400,500G的500,这个价格一出,我就感觉事情开始超出自己能够掌控的范围了,开始不淡定了。可是后面,最最无奈的一个破财点出来了——数据恢复。据他们的说法是:硬盘磁道坏了,一般的方式无法通过数据线连接到机器上识别硬盘,然后用软件做数据恢复,而是在一个无尘的环境里面,拆开硬盘,把坏的硬盘上面磁盘的内容查找对应分区和文件夹复制到一个新的硬盘里面。这样做的手续费是600,然后推荐换个500G的硬盘(这个也是我想的,因为320G的的确有点小).加起来总共的费用1100.

这个时候,我已经开始有点想崩溃了,一杯水==>1100大洋,这样的一个因果实在是太超出意料。如果不做数据恢复的话,价格倒是便宜,可是电脑里面的确有很多对我来说很重要的数据,一些公司的进行了很久的项目,一些自己平时的技术积累,还有收集了放在桌面上一个妹子发给我的很多文件。这些在我心里的价格是很珍贵的,所以我不得不痛苦的承认,我得挨宰!

回公司找同事准备借个1200,路上维修点的人又打来电话说可以用一种克隆的方式,把硬盘里面的数据都拷贝到另外一个硬盘上面,然后价格是800.因为是在电话里面,一时说不清,我就跟对方说等我过去再说,可是让同事取钱的时候,还是让他取了1500,已经预测到这笔另加的钱应该是避免不了了。

再回到维修点,对方说用一个跟坏的磁盘一模一样大小的磁盘,在无尘的环境(又是无尘,无尘你妹啊)里把坏的磁盘的数据完全的拷贝到新磁盘上面。这样的做法一来恢复的数据很多,不用考虑专门恢复哪个文件夹里面的数据了,二来时间上也很快速(因为手上接了个任务,已经承诺了要明后两天完成,所以要求他们尽量快的修复电脑)。看起来这方法的确很好,可是价格不便宜(800),而且有个缺点,C盘里面的东西没法被恢复。这就意味着我桌面,我的文档,等很多地方的文件没法恢复了,特别是那个妹子发的那些文件…可是从时间和恢复的数据量上面来看,这又是唯一解。

最终的结果是,我倒了一杯水在键盘上,给了别人1200块钱,换了个除C盘没了和F,G,H变成E,F,G的新的320G的磁盘,64位的win8变成64位的win7.仅此而已,一切都和原先一样…..

回了公司,来不及哀悼,开始了悲催的加班节奏….

最重要的总结

数据的重要性

在维修的时候,和维修人员扯淡的时候,他的一句话让我很有感触:硬盘有价,数据无价,的确是这样,电脑上面任何一个部件坏了,换个一样或者更优的部件就能正常工作甚至比之前工作的更好。可是数据一旦没有了就真心没有了,不管那个是你心仪女子的照片,是你苦苦收集的一张张桌面背景,一首首高品质的好歌或者一部部的经典影片,也不管那个是你辛苦工作几个月甚至几年的论文或者程序。失去了就是失去了。所以要注意数据的备份

如何进行数据备份

作为一个到最后花了这么多钱做数据恢复的我,说这个话题也许有点不着调,但是我的确在这个方面有着一定的经验,只是之前是明白如何做却没有认识到这样做的重要性,最后就因为麻烦放弃了坚持。

数据的备份要考虑到下面几个问题:

  • 备份的频率
  • 备份的便捷性
  • 备份点的安全性
  • 备份点的稳定性

常见的备份方法就我所知有两种:本地备份(比如移动硬盘),云备份(各种网盘,Dropbox,Google Drive,金山快盘,百度云盘,115网盘)

本地备份:这个备份点的安全性和稳定性,只要买个好的移动硬盘(此处以移动硬盘代表本地备份的备份点),平时注意一下移动硬盘的放置地点,设置好强度足够的密码就能保证。但是如果数据是那种更新比较频繁的,通过本地备份,每次手动的拷贝的话,那么频率和便捷性就是一个相斥的方向了。所以本地备份适合那些变动比较少的,比如一些好的电影,有纪念意义的照片等数据

云备份:有过相关经验的人都知道,只要开着个软件,就能很实时的将你的增删改的文件保存到云服务器上,便捷性和频率上都无可挑剔,只是如果数据量比较大,可能软件会占用电脑一定的内存和cpu(我当初就是因为这个原因没能坚持一直实时开着软件备份)。在稳定性方面,因为好的云盘都是有多个分布在各地的服务器保存着多份数据的备份。哪怕有一台服务器挂了也不影响数据的完整性。所以稳定性上面可以有保障。但是在安全性方面,安全指的是数据不被他包括云盘服务提供商自身)窃取或查看,这一点,就没法保证。因为数据在别人那儿,你没法监督他的操作。建议的方式是国内和国外的云盘服务交叉使用。国外的公司还是有一些素质的,所以一些重要的,机密程度不是很高的文件,比如公司的一些开发中的项目可以考虑使用国外的云盘。只要你的公司不是国内的顶级公司,那么你的文件就算真的被对方查看了,也没法带给对方什么商业价值。至于其他的一些个人的非私密的摄影摄像文件,自己写的小程序等等就可以放心的放在同步速度比较快而且可以方便的分享给不能翻墙的国内朋友的国内网盘。

对于那些公司的机密文件,特别是后台的一些文件,任何移动硬盘或者云盘都是不靠谱的,应该的做法是每个公司自己建立好一个svn或者git服务器,而作为使用者的我们,应该多svn up和git commit。保证自己的文件尽量及时的同步到服务器上面。

好了,以上就是本人的一些比较罗嗦的经验了。(完)

今天跟同事炫耀自己网站的排名从14020003上升到5248417(很坑啊),同事也是极度无语,然后顺便问了我下pv之类的。顿时尴尬了,之前一直想自己写个统计的,可是对于写个博客,花了两个星期都没完成的我,这写统计也不知道何年何月才能完成,只好先找个现成的。

cnzz注册了个帐号,写好网站信息,然后弄了段代码,放到body.php里面。OK,统计添加完成。回头看看每天都有多少人访问。因为主机是在港台的,不知道啥原因,总是很多老外跑来发垃圾评论,这下可以看看,分析一下了

  • 计划好的前端文档
  • 熬夜写好的chrome插件开发计划
  • 说好的翻译项目

好吧,如题,又废了一个周末,什么事都没干,唯一的安慰奖就是看了点jQuery Mobile,可是暂时还没制定app开发的计划,估计回头还得重新看一遍

已经轮回了多少个这样的周末了,死宅,熬夜,饿肚子,蒙头大睡,狂看小说

多少次的满满计划,多少次的雄心壮志,就这样在两天里埋葬,只留下写满懊悔的墓志铭


很担心啊,感觉自己在一步一步的变成那种自己十分讨厌的人。懒散,狭隘,目光短浅,斤斤计较。再这样死宅和颓废下去,后果估计真的会是这样,尼玛,真心烦躁

真心希望有个人在身边,至少不那么寂寞,至少能静下心来。

可是,这样把希望寄托在另外一个人身上,说到底也是对对方的不公平和对自己的逃避。

还是自己努力吧,骚年,人生如果只是一周又一周的轮回,到最后真的会痛哭流涕

起因

今天在公司忙活着一个项目,涉及到表单提交,要求在表单提交之前判断几个input的值是否为空,如果是,则阻止表单提交。

我的做法是给form添加了一个submit事件绑定,然后判断,如果有input的值为空则return false 阻止提交。判断input值是否为空,这一块走的正常,可是在判断有空值的时候,表单还是提交了,很是奇怪。

上网看了看大家的一些做法,也都是return false.为啥到我这边就不管用了?后来仔细看了下别人代码和自己的区别,这才找到了原因。

表单提交前判断的常用做法

一般来说,js要实现提交前的判断,有以下三种常见做法:

  1. 监听form标签的submit事件
  2. 监听input[type=submit]按钮的click事件
  3. 监听input[type=button]或者任何指定作为提交按钮的标签的任意事件,在条件符合之后调用form标签的submit()方法

一下是一个简单的例子:

<!DOCTYPE HTML>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>demo-form</title>
</head>
<body>
<form action="answer.php" id="form1" method="post">
    <input type="text" value="" id="txt">
    <input type="submit" value="提交" id="sbtn">
    <input type="button" value="按钮" id="btn">
</form>
<script type="text/javascript">
    var d = document,
        form1 = d.getElementById('form1'),
        txt = d.getElementById('txt'),
        sbtn = d.getElementById('sbtn'),
        btn = d.getElementById('btn');

        // 检测文本框内容是否为空
        function checkIsNull(){
            if(txt.value === ""){
                return false;
            }else{
                return true;
            }
        }
</script>
</body>
</html>

 

对于第三种方法,实现阻止表单提交最简单,只要条件不符合就不调用form标签的submit()方法即可

        btn.addEventListener('click',function(e){
            if(checkIsNull()){
                form1.submit();
            }else{
                alert('文本框内容不能为空');
            }
        });

 

对于第二种方法和第一种方法,就有比较多的可能性了

直接绑定到标签属性上

如果是使用直接绑定到标签属性上的方法,则第一和第二种方法都可以简单的使用return false;的方法去阻止表单提交。

        form1.onsubmit = function(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                return false;
            }
        };

 

        sbtn.onclick = function(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                return false;
            }
        };

 

这种直接注册到标签属性上的方法,方法内部的return false;就会直接作用到整个事件上,这一点我是在下面这个文章里面看到的,有兴趣的同学可以看看,传送门:由表单中onsubmit=”return false;”想到的

可是这种事件注册有个缺点就是没有办法给同一个标签的同一个事件注册多个回调函数函数,这个在某些情况下还是不行的。然后就是通过addEventListener(IE下面是attachEvent)

通过addEventListener/attachEvent注册事件

通过addEventListener方法注册的事件的回调函数,假设是:

form.addeventListener('submit',function doSubmit(e){
    return false;
},false);

 

其实就类似于:

form.onsubmit = function(e){
    doSubmit();
}

 

所以doSubmit()内部的return false;是没办法影响到整个事件的浏览器默认动作

这个时候,在非IE浏览器下,回调函数函数可以通过传入的event,调用该event对象的preventDefault()方法阻止浏览器的默认动作;如果是在IE浏览器下,则是通过window.event.returnValue = false;方法来阻止浏览器的默认动作。(这段内容参考的网站,传送门:js阻止浏览器的默认行为以及停止事件冒泡(用JQuery实现回车提交,兼容IE、FF浏览器)

所以可行的代码如下:

        function doSubmit(e){
            if(checkIsNull()){
                return true;
            }else{
                alert('文本框内容不能为空');
                //如果提供了事件对象,则这是一个非IE浏览器 
                if(e && e.preventDefault){
                    //阻止默认浏览器动作(W3C)
                    e.preventDefault();
                }else{
                    //IE中阻止函数器默认动作的方式 
                    window.event.returnValue = false;
                }
            }
        }

        // 判断是否支持IE的注册事件方法,如果支持则是IE浏览器,使用attachEvent进行事件注册
        if(sbtn.attachEvent){
            // attachEvent不支持捕捉,所以只有两个参数
            sbtn.attachEvent('click',doSubmit)
        }else{
            sbtn.addEventListener('click',duSubmit,false);
        }

 

form标签的submit事件也是类似的,就不重复写了

总结

return false;是能够阻止表单提交的,不过只能针对直接注册事件到标签属性上面的情况。对于addEventListener/attachEvent注册的事件,则需要通过event.preventDefaule()或window.event.returnValue=false的方式阻止表单的提交。针对其他浏览器默认行为,也大体上类似