<<上篇 | 首页 | 下篇>>

每个jQuery开发者应该知道的重要技巧

 

1. stopPropagation or preventDefault or return false?

 

开发新手对stopPropagation,preventDefault和返回false经常混淆该使用哪一个技术以及什么时候用。

 

 

stopPropagation()

 

要了解stopPropagation,我们需要首先了解事件冒泡。让我们来举个例子。让我们假设你有链接<a>在<div>里,如下所示:

<div id="divone">

    <a href="#" id="aone">Click me</a>

</div>

 

click事件挂在链接和DIV上:

$("#divone").click(function (e) {

    alert("div clicked");

});

 

$("a").click(function (e) {

    alert("link clicked");

});

 

当你点击链接,click()事件触发以及函数运行显示一个警告框“link clicked”。然而,事件并没有就此止步。你会看到另一个警告框“div clicked”。换句话说,即使你单击<a>,由于<div>是它的祖先元素,也接收到click事件。这就是所谓的事件冒泡或事件传播。

 

因此为了从阻止冒泡事件,需要以下列方式使用stopPropagation:

$("a").click(function (e) {

    alert("link clicked");

    e.stopPropagation();

});

 

 

现在,当你点击链接,单击事件将激发以及功能运行显示一个警告框“link clicked”。然而,由于e.stopPropagation,该事件不会冒泡。这就是为什么你不会看到第二个警告框。

 

preventDefault()

 

如果你想阻止Web浏览器事件的正常反应,使用preventDefault()。默认情况下,当你点击超链接,事件正常反应,转向到超链接href属性所示的网址。让我们以同样的例子定义超链接在div里如下:

<div id="divone">

    <a href="http://www.jquerycookbook.com" id="aone">Click me</a>

</div>

 

在这里,点击超链接将转移到网页www.jquerycookbook.com。如果你想阻止这种默认行为,使用preventDefault(),如下所示:

$("#divone").click(function (e) {

    alert("div clicked");

});

 

$("a").click(function (e) {

    e.preventDefault();

});

 

 

现在,当您运行代码,你会看到,点击超链接并没有转向到网站地址,因为我们已经阻止了浏览器的默认事件。

 

然而,“div clicked”警告框显示了,因为我们阻止默认事件,而没有阻止发生事件冒泡/传播。如果你想阻止事件的发生冒泡,再同时使用,如下所示:

$("a").click(function (e) {

    e.stopPropagation();

    e.preventDefault();

});

 

现在,我们这两个都做了,所以浏览器不按照链接转向并且div事件也不会触发,因此我们没有看到alert()框。

 

return false

 

返回false实际上是调用stopPropagation()和preventDefault()的快捷方式。它告诉jQuery来防止缺省事件和停止冒泡的一种方式。大多数时候,你不想调用stopPropagation,所以我强烈建议不使用return false,而在代码中使用preventDefault()。

 

2、一些选择器技巧

这里有一些选择器技巧,你可以用它来提高选择的性能:

 

a。如果可能的话,使用ID选择器去选择代码中的元素。

 

b。在选择之前,不要在前面加上了标签名。所以,来看看下面:

<input type="text" id="code" value="54325454" />

..不要用 $("input#code"), 应该用 $("#code").

 

 

c. 只要有可能,使用过滤器方法来提高性能。可以使用$("div").has('p')来代替$( "div:has(p)"),这里 .has() 使用本地的DOM querySelectorAll() 方法 因此理论上比 :has更快。

 

d. 使用slice() 代替使用 :lt和 :gt 选择器

 

e. 推荐优先使用伪选择器,例如带有tag名的:text或者其他的选择器,否则隐含的通用选择器 ("*")就被使用了。也就是,$(":text") 相当于 $( "*:text"),所以应该使用$("input:text")

 

f. 不用 Not Equal 不等于选择器,尽可能使用 .not()获得小小的性能优势

 

g。不用过滤器,使用相当的属性选择器。例如用$('[type=image]' 来代替 $(':image')

 

延伸阅读:

http://learn.jquery.com/performance/optimize-selectors/

 

http://api.jquery.com/?s=selectors

 

3 - 使用 attr() 还是 prop()

attr() 处理 attributes 而 prop() 处理 properties. 考虑下面的标签:

<input type="text" value="original" />

 

输入域有attribute "value",有一个缺省的值并且这个attribute不会随着用户的输入交互而改变。如果用户输入改变了这个输入域,它在DOM Tree里改变了property的"value"而不是attribute的"value"

 

 

看看 jsfiddle 上 的demo 来理解两者的不同:

http://jsfiddle.net/jquerycookbook/s1gsLcLb/

 

运行演示,一旦你从“original”输入别的东西改变文本框的值,回车。你会看到,ATTR()将返回原来的价值,但prop()返回更改后的值。

 

所以attributes不会改变,但properties可以在后台通过用户操作来改变(选中/取消选中复选框)或以编程方式。

 

因此,什么时候使用什么?如果你想设置一个HTML标记属性的默认值,可以使用ATTR()。然而,当您在窗口或文档对象设置属性,你应该总是使用道具prop()。

 

虽然我用这个文本框例子说明目的,实际上,既不用.attr(),也不用.prop()用于获取/设定值。你应该使用.val()方法。

 

jQuery的1.6之前,我们只有ATTR()。

 

延伸阅读: http://blog.jquery.com/2011/05/12/jquery-1-6-1-released/

 

4 - <script> in head or body?

 

在一个HTML文件里可以在两个地方放置js,在</ body>标记结束之前和<head>里面。网页浏览器处理一个HTML页,从上到下,执行任何它找到<script>标记之间的JavaScript。由于这个原因,如果脚本中的一个需要花费时间来执行,网页的加载被阻止。因此,最好放在body元素结束之前,以确保您的脚本在加载DOM后运行。

 

在我的一些文章,甚至我的书,我经常选择把脚本中的<head>标签里面,但是这仅仅是为了可读性。不过,我也请务必使用$(document).ready() 或快捷方式$(function(){ }),它可确保只有当浏览器加载所有的HTML文档中的内容后脚本才执行。因此,我把脚本放在结束</ body>标签之前达到相同的效果。

 

说了这么多,记住,通过在页面底部引入你的脚本,就可以完全避免使用$(document).ready()。事实上,在我所有的生产准备的应用程序,我的脚本都在页面的底部。

 

5 - Difference between this, $this and $(this)

 

 

让我们用一个例子来理解$this和$(this)的不同。看看下面的代码:

$('div').each(function () {

    var $this = $(this);

    $this.css("background-color", "blue");

    $this.slideUp('3000');

    $this.slideDown('3000');            

});

 

在这里,我们使用each()遍历了一堆div。一旦在你的循环中,this引用的是不是一个jQuery对象的DOM元素。因此,要使它成为一个jQuery对象,并在其上运行jQuery方法,我们用$(this)。现在就来看看这句话中:var $this = $(this);

 

如果你要引用的DOM元素多次在代码中,像我们上面这个例子;那么由于性能考虑,你应该获得一个jQuery的引用它,然后保存到一个变量。在这里,$this是那个变量。这也被称为高速缓存选择器,因为它是昂贵的运行jQuery函数$(this)各一次。因此,存储在一个变量的输出可以让您重用这个选择器,而不会再次调用jQuery函数。

 

注意:不要混淆$this。你可以把它叫做任何你喜欢的。我通常是指包含的jQuery对象作为$ VARIABLENAME变量。

原创文章转载请保留原文链接
英文地址

 

标签 : ,

mysql-5.6 Slave支持crash-safe | ISADBA|FH.CN

mysql异常关机会导致slave复制故障,slave复制中断,解决办法是启用crash-safe,或者找到前一个pos号重新启动进行同步,或者使用relay_log_recovery=ON参数启动。
 
slave支持crash-safe是mysql-5.6复制功能最重要的改进之一。但是如何正确配置开启这个功能呢?我们来澄清一下如何完成.
具体方法:
1、停止slave的mysql实例
2、my.cnf文件中添加relay_log_info_repository=TABLE 和 relay_log_recovery=ON
3、重启slave的mysql实例
 
重要的细节:
为了完全明白为什么要这样设置才能开启crash-safe的功能,首先看看什么原因会导致slave crash后复制中断。
在slave上,复制包含两个线程:
IO线程负责从master拷贝binlog文件保存到本地,拷贝过来的binlog称为relay-log.SQL线程负责执行relay-log.
当前两个线程的执行进度(偏移量)都保存在文件中.IO线程的进度保存在master.info,SQL线程的进度保存在relay-log.info文件。
 
到目前为止还没有问题。第一个问题是这些文件被修改后不是同步写入磁盘的,每当发生crash,存储的偏移量可能都不准确.mysql-5.5修复了这个问题,使用sync_master_info=1和
sync_replay_log_info=1来保证两个文件的修改和写入是一个事务。同步当然不是免费的,需要消耗性能,如果你的raid设备设置为write-back,那么这种方法是可以接受的。
 
但是,即时设置了sync_master_info=1和sync_relay_info=1,坏事还是可能发生。原因是复制信息是在transactions提交后写入的,如果crash发生在事务提交和写文件之间,那么relay-log.info就可能
是错误的。当slave从新启动的时候,最后那个事务可能会被执行两次.具体的影响取决于事务的具体操作.复制可能会继续运行,或者报错,主从数据的一致性可能会被破坏。
 
mysql-5.6可以通过将复制的信息存放到表中代替文件来解决此问题.当relay_log_info_repository=TABLE时,mysql.slave_relay_log_info表会被创建。master_info_repository=TABLE时,mysql.slave_master_info表会被创建.
这个方法很简单,就是把SQL线程的事务和更新mysql.slave_replay_log_info的语句看成一个事务处理,这样就会一直同步的.

伪代码如下:

old:
START TRANSACTION;
--Statement 1
--...
--Statement N
COMMIT;

--Update replication info files

new:
START TRANSACTION;
--...Statement1
.....
--...Statement N
UPdate replication info
COMMIT;
不幸的是,这不是看起来那么简单,现在sql线程看上去没有问题了,但是IO线程,他更新表没有办法依赖任何事务。所以服务器不知道什么时候更新表?
答案就是:通过sync_master_info来控制.默认值是10000,表示IO线程的偏移量每10000个事务更新一次.这个样明显的不能支持slave的crash-safe.一种解决方案是sync_master_info=1,
但是注意,这样会影响性能.
 
另外一种更加高雅的处理方案是使用relay_log_recovery = ON,但是设置这个参数生效,需要服务器重启。这个参数可以让slave重启的时候,抛弃现有的IOthread的偏移量,从slave_relay_log_info表中获取当前的
IO线程偏移量,这样你就不需要以为crash-safe存储IO线程的信息到表里。也就是说master_info_repository = TABLE不是必须的。
 
最后注意,relay_log_info_repository = TABLE和sync_relay_log_info是没有关联的.所以你可以放心的从配置文件中移除sync_relay_log_info。
http://www.mysqlperformanceblog.com/2013/09/13/enabling-crash-safe-slaves-with-mysql-5-6/

+++++++++++++++++++++++++++++++++++++++++++++++++++++++
TIPS:
针对mariadb-10.0.12环境.
还不支持master_info_repository功能.但是支持sync_master_info,sync_relay_log,sync_relay_log_info,relay_log_recovery
所以可以通过这些参数最大限度保证slave crash safe。

阅读全文……

标签 : ,

浏览器缓存机制

 

浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如: Expires Cache-control等)。但是也有非HTTP协议定义的缓存机制,如使用HTML Meta 标签,Web开发者可以在HTML页面的<head>节点中加入<meta>标签,代码如下:

html code

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。使用上很简单,但只有部分浏览器可以支持,而且所有缓存代理服务器都不支持,因为代理不解析HTML内容本身。

下面我主要介绍HTTP协议定义的缓存机制。

Expires策略

ExpiresWeb服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

下面是宝宝PK项目中,浏览器拉取jquery.js web服务器的响应头:

clip_image001

注:Date头域表示消息发送的时间,时间的描述格式由rfc822定义。例如,Date: Mon,31 Dec 2001 04:25:57GMT

Web服务器告诉浏览器在2012-11-28 03:30:01这个时间点之前,可以使用缓存文件。发送请求的时间是2012-11-28 03:25:01,即缓存5分钟。

不过Expires HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。

Cache-control策略(重点关注

Cache-ControlExpires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control选择更多,设置更细致,如果同时设置的话,其优先级高于Expires

http协议头Cache-Control   

值可以是publicprivateno-cacheno- storeno-transformmust-revalidateproxy-revalidatemax-age

各个消息中的指令含义如下:

  1. Public指示响应可被任何缓存区缓存。
  2. Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
  3. no-cache指示请求或响应消息不能缓存
  4. no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
  5. max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
  6. min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
  7. max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。

还是上面那个请求,web服务器返回的Cache-Control头的值为max-age=300,即5分钟(和上面的Expires时间一致,这个不是必须的)。

clip_image002

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since要配合Cache-Control使用。

l  Last-Modified:标示这个响应资源的最后修改时间。web服务器在响应请求时,告诉浏览器资源的最后修改时间。

l  If-Modified-Since:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Last-Modified声明,则再次向web服务器请求时带上头 If-Modified-Since,表示请求时间。web服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。若最后修改时间较新,说明资源又被改动过,则响应整片资源内容(写在响应消息包体内),HTTP 200;若最后修改时间较旧,说明资源无新修改,则响应HTTP 304 (无需包体,节省浏览),告知浏览器继续使用所保存的cache

Etag/If-None-Match

Etag/If-None-Match也要配合Cache-Control使用。

l  Etagweb服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器觉得)。Apache中,ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的

l  If-None-Match:当资源过期时(使用Cache-Control标识的max-age),发现资源具有Etage声明,则再次向web服务器请求时带上头If-None-Match Etag的值)web服务器收到请求后发现有头If-None-Match 则与被请求资源的相应校验串进行比对,决定返回200304

既生Last-Modified何生Etag

你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag(实体标识)呢?HTTP1.1Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:

l  Last-Modified标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的修改时间

l  如果某些文件会被定期生成,当有时内容并没有任何变化,但Last-Modified却改变了,导致文件没法使用缓存

l  有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形

Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的唯一标识符,能够更加准确的控制缓存。Last-ModifiedETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304

用户行为与缓存

浏览器缓存行为还有用户的行为有关!!!

用户操作

Expires/Cache-Control

Last-Modified/Etag

地址栏回车

有效

有效

页面链接跳转

有效

有效

新开窗口

有效

有效

前进、后退

有效

有效

F5刷新

无效

有效

Ctrl+F5刷新

无效

无效

总结

浏览器第一次请求:

clip_image004

浏览器再次请求时:

clip_image006

 

 

 

作者:吴秦
出处:http://www.cnblogs.com/skynet/
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接).

 
 
标签 : ,