<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>阿当</title>
	<atom:link href="http://adam.ofeva.com/feed" rel="self" type="application/rss+xml" />
	<link>http://adam.ofeva.com</link>
	<description>我是阿当，我爱阿夏</description>
	<pubDate>Wed, 27 Aug 2008 13:59:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>用户体验的十个基本法则</title>
		<link>http://adam.ofeva.com/blog/61.html</link>
		<comments>http://adam.ofeva.com/blog/61.html#comments</comments>
		<pubDate>Wed, 27 Aug 2008 13:58:51 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[UI/UE]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=61</guid>
		<description><![CDATA[Andreas Pfeiffer写的WHY FEATURES DON’T MATTER ANYMORE: THE NEW LAWS OF DIGITAL TECHNOLOGY，从用户体验角度强调了功能并不在重要，重要的在于用户对产品或服务的体验，并列出十大法则，10 fundamental rules for the age of user experience technology。 
在这个时代里10个基本法则是：
1、更多的功能并不好
More features isn’t better, it’s worse；
2、增加功能不会让事情更容易
You can’t make things easier by adding to them； 
3、让用户迷惑是毁掉业务的终级手段
Confusion is the ultimate deal-breaker；
4、风格很关键
Style matters；
5、只有在一项功能可以提升用户体验时才加上它
Only features that provide a good user experience will be used； 
6、任何需要学习的功能都只会吸引一小部分用户
Any feature that requires [...]]]></description>
			<content:encoded><![CDATA[<p>Andreas Pfeiffer写的WHY FEATURES DON’T MATTER ANYMORE: THE NEW LAWS OF DIGITAL TECHNOLOGY，从用户体验角度强调了功能并不在重要，重要的在于用户对产品或服务的体验，并列出十大法则，10 fundamental rules for the age of user experience technology。 </p>
<p>在这个时代里10个基本法则是：</p>
<p><strong>1、更多的功能并不好</strong><br />
More features isn’t better, it’s worse；</p>
<p><strong>2、增加功能不会让事情更容易</strong><br />
You can’t make things easier by adding to them； </p>
<p><strong>3、让用户迷惑是毁掉业务的终级手段</strong><br />
Confusion is the ultimate deal-breaker；</p>
<p><strong>4、风格很关键</strong><br />
Style matters；</p>
<p><strong>5、只有在一项功能可以提升用户体验时才加上它</strong><br />
Only features that provide a good user experience will be used； </p>
<p><strong>6、任何需要学习的功能都只会吸引一小部分用户</strong><br />
Any feature that requires learning will only be adopted by a small fraction of users； </p>
<p>7、无用的功能不止是无用，它会破坏易用性<br />
Unused features are not only useless, they can slow you down and diminish ease of use；</p>
<p><strong>8、用户不会关心技术，他们只想知道产品能做什么</strong><br />
Users do not want to think about technology: what really counts is what it does for them； </p>
<p><strong>9、忘掉关键功能，关注最重要的用户体验</strong><br />
Forget about the killer feature. Welcome to the age of the killer user-experience； </p>
<p><strong>10、简洁很难，因此少就是多</strong><br />
Less is difficult, that’s why less is more。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/61.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>MySQL 服务器调优</title>
		<link>http://adam.ofeva.com/blog/60.html</link>
		<comments>http://adam.ofeva.com/blog/60.html#comments</comments>
		<pubDate>Tue, 26 Aug 2008 04:48:53 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[database]]></category>

		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=60</guid>
		<description><![CDATA[
利用服务器的几个调优技巧，让 MySQL 服务器飞速运行
如今，开发人员不断地开发和部署使用 LAMP（Linux®、Apache、MySQL 和 PHP/Perl）架构的应用程序。但是，服务器管理员常常对应用程序本身没有什么控制能力，因为应用程序是别人编写的。这份 共三部分的系列文章 将讨论许多服务器配置问题，这些配置会影响应用程序的性能。本文是本系列文章的第三部分，也是最后一部分，将重点讨论为实现最高效率而对数据库层进行的调 优。
关于 MySQL 调优
有 3 种方法可以加快 MySQL 服务器的运行速度，效率从低到高依次为：
替换有问题的硬件。
对 MySQL 进程的设置进行调优。
对查询进行优化。
替换有问题的硬件通常是我们的第一考虑，主要原因是数据库会占用大量资源。不过这种解决方案也就仅限于此了。实际上，您通常可以让中央处理器（CPU）或磁盘速度加倍，也可以让内存增大 4 到 8 倍。
第二种方法是对 MySQL 服务器（也称为 mysqld）进行调优。对这个进程进行调优意味着适当地分配内存，并让 mysqld 了解将会承受何种类型的负载。加快磁盘运行速度不如减少所需的磁盘访问次数。类似地，确保 MySQL 进程正确操作就意味着它花费在服务查询上的时间要多于花费在处理后台任务（如处理临时磁盘表或打开和关闭文件）上的时间。对 mysqld 进行调优是本文的重点。
最好的方法是确保查询已经进行了优化。这意味着对表应用了适当的索引，查询是按照可以充分利用 MySQL 功能的方式来编写的。尽管本文并没有包含查询调优方面的内容（很多著作中已经针对这个主题进行了探讨），不过它会配置 mysqld 来报告可能需要进行调优的查询。
虽然已经为这些任务指派了次序，但是仍然要注意硬件和 mysqld 的设置以利于适当地调优查询。机器速度慢也就罢了，我曾经见过速度很快的机器在运行设计良好的查询时由于负载过重而失败，因为 mysqld 被大量繁忙的工作所占用而不能服务查询。
记录慢速查询
在一个 SQL 服务器中，数据表都是保存在磁盘上的。索引为服务器提供了一种在表中查找特定数据行的方法，而不用搜索整个表。当必须要搜索整个表时，就称为表扫描。通常 来说，您可能只希望获得表中数据的一个子集，因此全表扫描会浪费大量的磁盘 I/O，因此也就会浪费大量时间。当必须对数据进行连接时，这个问题就更加复杂了，因为必须要对连接两端的多行数据进行比较。
当然，表扫描并不总是会带来问题；有时读取整个表反而会比从中挑选出一部分数据更加有效（服务器进程中查询规划器用来作出这些决定）。如果索引 的使用效率很低，或者根本就不能使用索引，则会减慢查询速度，而且随着服务器上的负载和表大小的增加，这个问题会变得更加显著。执行时间超过给定时间范围 的查询就称为慢速查询。
您可以配置 mysqld 将这些慢速查询记录到适当命名的慢速查询日志中。管理员然后会查看这个日志来帮助他们确定应用程序中有哪些部分需要进一步调查。清单 1 给出了要启用慢速查询日志需要在 my.cnf 中所做的配置。
清单 1. 启用 MySQL 慢速查询日志



[mysqld] ; [...]]]></description>
			<content:encoded><![CDATA[<div class="cnt">
<p>利用服务器的几个调优技巧，让 MySQL 服务器飞速运行<br />
如今，开发人员不断地开发和部署使用 LAMP（Linux®、Apache、MySQL 和 PHP/Perl）架构的应用程序。但是，服务器管理员常常对应用程序本身没有什么控制能力，因为应用程序是别人编写的。这份 共三部分的系列文章 将讨论许多服务器配置问题，这些配置会影响应用程序的性能。本文是本系列文章的第三部分，也是最后一部分，将重点讨论为实现最高效率而对数据库层进行的调 优。</p>
<p>关于 MySQL 调优</p>
<p>有 3 种方法可以加快 MySQL 服务器的运行速度，效率从低到高依次为：<br />
替换有问题的硬件。<br />
对 MySQL 进程的设置进行调优。<br />
对查询进行优化。</p>
<p>替换有问题的硬件通常是我们的第一考虑，主要原因是数据库会占用大量资源。不过这种解决方案也就仅限于此了。实际上，您通常可以让中央处理器（CPU）或磁盘速度加倍，也可以让内存增大 4 到 8 倍。</p>
<p>第二种方法是对 MySQL 服务器（也称为 mysqld）进行调优。对这个进程进行调优意味着适当地分配内存，并让 mysqld 了解将会承受何种类型的负载。加快磁盘运行速度不如减少所需的磁盘访问次数。类似地，确保 MySQL 进程正确操作就意味着它花费在服务查询上的时间要多于花费在处理后台任务（如处理临时磁盘表或打开和关闭文件）上的时间。对 mysqld 进行调优是本文的重点。</p>
<p>最好的方法是确保查询已经进行了优化。这意味着对表应用了适当的索引，查询是按照可以充分利用 MySQL 功能的方式来编写的。尽管本文并没有包含查询调优方面的内容（很多著作中已经针对这个主题进行了探讨），不过它会配置 mysqld 来报告可能需要进行调优的查询。</p>
<p>虽然已经为这些任务指派了次序，但是仍然要注意硬件和 mysqld 的设置以利于适当地调优查询。机器速度慢也就罢了，我曾经见过速度很快的机器在运行设计良好的查询时由于负载过重而失败，因为 mysqld 被大量繁忙的工作所占用而不能服务查询。</p>
<p><strong>记录慢速查询</strong></p>
<p>在一个 SQL 服务器中，数据表都是保存在磁盘上的。索引为服务器提供了一种在表中查找特定数据行的方法，而不用搜索整个表。当必须要搜索整个表时，就称为表扫描。通常 来说，您可能只希望获得表中数据的一个子集，因此全表扫描会浪费大量的磁盘 I/O，因此也就会浪费大量时间。当必须对数据进行连接时，这个问题就更加复杂了，因为必须要对连接两端的多行数据进行比较。</p>
<p>当然，表扫描并不总是会带来问题；有时读取整个表反而会比从中挑选出一部分数据更加有效（服务器进程中查询规划器用来作出这些决定）。如果索引 的使用效率很低，或者根本就不能使用索引，则会减慢查询速度，而且随着服务器上的负载和表大小的增加，这个问题会变得更加显著。执行时间超过给定时间范围 的查询就称为慢速查询。</p>
<p>您可以配置 mysqld 将这些慢速查询记录到适当命名的慢速查询日志中。管理员然后会查看这个日志来帮助他们确定应用程序中有哪些部分需要进一步调查。清单 1 给出了要启用慢速查询日志需要在 my.cnf 中所做的配置。</p>
<p><strong>清单 1. 启用 MySQL 慢速查询日志</strong></p>
<table style="border: 1px solid rgb(153, 153, 153);font-size: 12px;width: 80%" align="center">
<tbody>
<tr>
<td><span style="color: rgb(0, 0, 0)">[mysqld] ; enable the slow query log, default 10 seconds log-slow-queries ; log queries taking longer than 5 seconds long_query_time = 5 ; log queries that don’t use indexes even if they take less than long_query_time ; MySQL 4.1 and newer only log-queries-not-using-indexes</span></td>
</tr>
</tbody>
</table>
<p>这三个设置一起使用，可以记录执行时间超过 5 秒和没有使用索引的查询。请注意有关 log-queries-not-using-indexes 的警告：您必须使用 MySQL 4.1 或更高版本。慢速查询日志都保存在 MySQL 数据目录中，名为 hostname-slow.log。如果希望使用一个不同的名字或路径，可以在 my.cnf 中使用 log-slow-queries = /new/path/to/file 实现此目的。</p>
<p>阅读慢速查询日志最好是通过 mysqldumpslow 命令进行。指定日志文件的路径，就可以看到一个慢速查询的排序后的列表，并且还显示了它们在日志文件中出现的次数。一个非常有用的特性是 mysqldumpslow 在比较结果之前，会删除任何用户指定的数据，因此对同一个查询的不同调用被计为一次；这可以帮助找出需要工作量最多的查询。</p>
<p><strong>对查询进行缓存</strong></p>
<p>很多 LAMP 应用程序都严重依赖于数据库，但却会反复执行相同的查询。每次执行查询时，数据库都必须要执行相同的工作 —— 对查询进行分析，确定如何执行查询，从磁盘中加载信息，然后将结果返回给客户机。MySQL 有一个特性称为查询缓存，它将（后面会用到的）查询结果保存在内存中。在很多情况下，这会极大地提高性能。不过，问题是查询缓存在默认情况下是禁用的。</p>
<p>将 query_cache_size = 32M 添加到 /etc/my.conf 中可以启用 32MB 的查询缓存。</p>
<p>监视查询缓存</p>
<p>在启用查询缓存之后，重要的是要理解它是否得到了有效的使用。MySQL 有几个可以查看的变量，可以用来了解缓存中的情况。清单 2 给出了缓存的状态。</p>
<p><strong>清单 2. 显示查询缓存的统计信息</strong><br />
mysql&gt; SHOW STATUS LIKE ‘qcache%’;<br />
<span>+————————-+————+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+————————-+————+<br />
| Qcache_free_blocks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 5216&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Qcache_free_memory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 14640664&nbsp;&nbsp;   |<br />
| Qcache_hits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 2581646882 |<br />
| Qcache_inserts&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 360210964  |<br />
| Qcache_lowmem_prunes&nbsp;&nbsp;&nbsp;   | 281680433  |<br />
| Qcache_not_cached&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 79740667&nbsp;&nbsp;   |<br />
| Qcache_queries_in_cache | 16927&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Qcache_total_blocks&nbsp;&nbsp;&nbsp;&nbsp;   | 47042&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+————————-+————+<br />
8 rows in set (0.00 sec)</span></p>
<p>这些项的解释如表 1 所示。</p>
<p>表 1. MySQL 查询缓存变量变量名 说明<br />
Qcache_free_blocks  缓存中相邻内存块的个数。数目大说明可能有碎片。FLUSH QUERY CACHE 会对缓存中的碎片进行整理，从而得到一个空闲块。<br />
Qcache_free_memory  缓存中的空闲内存。<br />
Qcache_hits  每次查询在缓存中命中时就增大。<br />
Qcache_inserts  每次插入一个查询时就增大。命中次数除以插入次数就是不中比率；用 1 减去这个值就是命中率。在上面这个例子中，大约有 87% 的查询都在缓存中命中。<br />
Qcache_lowmem_prunes 缓存出现内存不足并且必须要进行清理以便为更多查询提供空间的次数。这个数字最好长时间来看；如果这个数字在不断增长，就表示可能碎片非常严重，或者内 存很少。（上面的 free_blocks 和 free_memory 可以告诉您属于哪种情况）。<br />
Qcache_not_cached  不适合进行缓存的查询的数量，通常是由于这些查询不是 SELECT 语句。<br />
Qcache_queries_in_cache  当前缓存的查询（和响应）的数量。<br />
Qcache_total_blocks  缓存中块的数量。<br />
通常，间隔几秒显示这些变量就可以看出区别，这可以帮助确定缓存是否正在有效地使用。运行 FLUSH STATUS 可以重置一些计数器，如果服务器已经运行了一段时间，这会非常有帮助。</p>
<p>使用非常大的查询缓存，期望可以缓存所有东西，这种想法非常诱人。由于 mysqld 必须要对缓存进行维护，例如当内存变得很低时执行剪除，因此服务器可能会在试图管理缓存时而陷入困境。作为一条规则，如果 FLUSH QUERY CACHE 占用了很长时间，那就说明缓存太大了。</p>
<p>强制限制</p>
<p>您可以在 mysqld 中强制一些限制来确保系统负载不会导致资源耗尽的情况出现。清单 3 给出了 my.cnf 中与资源有关的一些重要设置。</p>
<p><strong>清单 3. MySQL 资源设置</strong><br />
<span>set-variable=max_connections=500<br />
set-variable=wait_timeout=10<br />
max_connect_errors = 100</span></p>
<p>连接最大个数是在第一行中进行管理的。与 Apache 中的 MaxClients 类似，其想法是确保只建立服务允许数目的连接。要确定服务器上目前建立过的最大连接数，请执行 SHOW STATUS LIKE ‘max_used_connections’。</p>
<p>第 2 行告诉 mysqld 终止所有空闲时间超过 10 秒的连接。在 LAMP 应用程序中，连接数据库的时间通常就是 Web 服务器处理请求所花费的时间。有时候，如果负载过重，连接会挂起，并且会占用连接表空间。如果有多个交互用户或使用了到数据库的持久连接，那么将这个值设 低一点并不可取！</p>
<p>最后一行是一个安全的方法。如果一个主机在连接到服务器时有问题，并重试很多次后放弃，那么这个主机就会被锁定，直到 FLUSH HOSTS 之后才能运行。默认情况下，10 次失败就足以导致锁定了。将这个值修改为 100 会给服务器足够的时间来从问题中恢复。如果重试 100 次都无法建立连接，那么使用再高的值也不会有太多帮助，可能它根本就无法连接。</p>
<p><strong>缓冲区和缓存</strong></p>
<p>MySQL 支持超过 100 个的可调节设置；但是幸运的是，掌握少数几个就可以满足大部分需要。查找这些设置的正确值可以通过 SHOW STATUS 命令查看状态变量，从中可以确定 mysqld 的运作情况是否符合我们的预期。给缓冲区和缓存分配的内存不能超过系统中的现有内存，因此调优通常都需要进行一些妥协。</p>
<p>MySQL 可调节设置可以应用于整个 mysqld 进程，也可以应用于单个客户机会话。</p>
<p>服务器端的设置</p>
<p>每个表都可以表示为磁盘上的一个文件，必须先打开，后读取。为了加快从文件中读取数据的过程，mysqld 对这些打开文件进行了缓存，其最大数目由 /etc/mysqld.conf 中的 table_cache 指定。清单 4 给出了显示与打开表有关的活动的方式。</p>
<p><strong>清单 4. 显示打开表的活动</strong><br />
mysql&gt; SHOW STATUS LIKE ‘open%tables’;<br />
<span>+—————+——-+<br />
| Variable_name | Value |<br />
+—————+——-+<br />
| Open_tables&nbsp;&nbsp;   | 5000  |<br />
| Opened_tables | 195&nbsp;&nbsp;   |<br />
+—————+——-+<br />
2 rows in set (0.00 sec)</span></p>
<p>清单 4 说明目前有 5,000 个表是打开的，有 195 个表需要打开，因为现在缓存中已经没有可用文件描述符了（由于统计信息在前面已经清除了，因此可能会存在 5,000 个打开表中只有 195 个打开记录的情况）。如果 Opened_tables 随着重新运行 SHOW STATUS 命令快速增加，就说明缓存命中率不够。如果 Open_tables 比 table_cache 设置小很多，就说明该值太大了（不过有空间可以增长总不是什么坏事）。例如，使用 table_cache = 5000 可以调整表的缓存。</p>
<p>与表的缓存类似，对于线程来说也有一个缓存。 mysqld 在接收连接时会根据需要生成线程。在一个连接变化很快的繁忙服务器上，对线程进行缓存便于以后使用可以加快最初的连接。</p>
<p>清单 5 显示如何确定是否缓存了足够的线程。</p>
<p><strong>清单 5. 显示线程使用统计信息</strong><br />
mysql&gt; SHOW STATUS LIKE ‘threads%’;<br />
<span>+——————-+——–+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;   | Value  |<br />
+——————-+——–+<br />
| Threads_cached&nbsp;&nbsp;&nbsp;   | 27&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Threads_connected | 15&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Threads_created&nbsp;&nbsp;   | 838610 |<br />
| Threads_running&nbsp;&nbsp;   | 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+——————-+——–+<br />
4 rows in set (0.00 sec)</span></p>
<p>此处重要的值是 Threads_created，每次 mysqld 需要创建一个新线程时，这个值都会增加。如果这个数字在连续执行 SHOW STATUS 命令时快速增加，就应该尝试增大线程缓存。例如，可以在 my.cnf 中使用 thread_cache = 40 来实现此目的。</p>
<p>关键字缓冲区保存了 MyISAM 表的索引块。理想情况下，对于这些块的请求应该来自于内存，而不是来自于磁盘。清单 6 显示了如何确定有多少块是从磁盘中读取的，以及有多少块是从内存中读取的。</p>
<p><strong>清单 6. 确定关键字效率</strong><br />
mysql&gt; show status like ‘%key_read%’;<br />
<span>+——————-+———–+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;   | Value&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+——————-+———–+<br />
| Key_read_requests | 163554268 |<br />
| Key_reads&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 98247&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+——————-+———–+<br />
2 rows in set (0.00 sec)</span></p>
<p>Key_reads 代表命中磁盘的请求个数， Key_read_requests 是总数。命中磁盘的读请求数除以读请求总数就是不中比率 —— 在本例中每 1,000 个请求，大约有 0.6 个没有命中内存。如果每 1,000 个请求中命中磁盘的数目超过 1 个，就应该考虑增大关键字缓冲区了。例如，key_buffer = 384M 会将缓冲区设置为 384MB。</p>
<p>临时表可以在更高级的查询中使用，其中数据在进一步进行处理（例如 GROUP BY 字句）之前，都必须先保存到临时表中；理想情况下，在内存中创建临时表。但是如果临时表变得太大，就需要写入磁盘中。清单 7 给出了与临时表创建有关的统计信息。</p>
<p><strong>清单 7. 确定临时表的使用</strong><br />
mysql&gt; SHOW STATUS LIKE ‘created_tmp%’;<br />
<span>+————————-+——-+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | Value |<br />
+————————-+——-+<br />
| Created_tmp_disk_tables | 30660 |<br />
| Created_tmp_files&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 2&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Created_tmp_tables&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 32912 |<br />
+————————-+——-+<br />
3 rows in set (0.00 sec)</span></p>
<p>每次使用临时表都会增大 Created_tmp_tables；基于磁盘的表也会增大 Created_tmp_disk_tables。对于这个比率，并没有什么严格的规则，因为这依赖于所涉及的查询。长时间观察 Created_tmp_disk_tables 会显示所创建的磁盘表的比率，您可以确定设置的效率。 tmp_table_size 和 max_heap_table_size 都可以控制临时表的最大大小，因此请确保在 my.cnf 中对这两个值都进行了设置。</p>
<p>每个会话的设置</p>
<p>下面这些设置针对于每个会话。在设置这些数字时要十分谨慎，因为它们在乘以可能存在的连接数时候，这些选项表示大量的内存！您可以通过代码修改会话中的这些数字，或者在 my.cnf 中为所有会话修改这些设置。</p>
<p>当 MySQL 必须要进行排序时，就会在从磁盘上读取数据时分配一个排序缓冲区来存放这些数据行。如果要排序的数据太大，那么数据就必须保存到磁盘上的临时文件中，并再 次进行排序。如果 sort_merge_passes 状态变量很大，这就指示了磁盘的活动情况。清单 8 给出了一些与排序相关的状态计数器信息。</p>
<p><strong>清单 8. 显示排序统计信息</strong><br />
mysql&gt; SHOW STATUS LIKE “sort%”;<br />
<span>+——————-+———+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;   | Value&nbsp;&nbsp;   |<br />
+——————-+———+<br />
| Sort_merge_passes | 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
| Sort_range&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 79192&nbsp;&nbsp;   |<br />
| Sort_rows&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 2066532 |<br />
| Sort_scan&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | 44006&nbsp;&nbsp;   |<br />
+——————-+———+<br />
4 rows in set (0.00 sec)</span></p>
<p>如果 sort_merge_passes 很大，就表示需要注意 sort_buffer_size。例如， sort_buffer_size = 4M 将排序缓冲区设置为 4MB。</p>
<p>MySQL 也会分配一些内存来读取表。理想情况下，索引提供了足够多的信息，可以只读入所需要的行，但是有时候查询（设计不佳或数据本性使然）需要读取表中大量数 据。要理解这种行为，需要知道运行了多少个 SELECT 语句，以及需要读取表中的下一行数据的次数（而不是通过索引直接访问）。实现这种功能的命令如清单 9 所示。</p>
<p><strong>清单 9. 确定表扫描比率</strong><br />
mysql&gt; SHOW STATUS LIKE “com_select”;<br />
<span>+—————+——–+<br />
| Variable_name | Value  |<br />
+—————+——–+<br />
| Com_select&nbsp;&nbsp;&nbsp;   | 318243 |<br />
+—————+——–+<br />
1 row in set (0.00 sec)</span></p>
<p>mysql&gt; SHOW STATUS LIKE “handler_read_rnd_next”;<br />
<span>+———————–+———–+<br />
| Variable_name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   | Value&nbsp;&nbsp;&nbsp;&nbsp;   |<br />
+———————–+———–+<br />
| Handler_read_rnd_next | 165959471 |<br />
+———————–+———–+<br />
1 row in set (0.00 sec)</span></p>
<p>Handler_read_rnd_next / Com_select 得出了表扫描比率 —— 在本例中是 521:1。如果该值超过 4000，就应该查看 read_buffer_size，例如 read_buffer_size = 4M。如果这个数字超过了 8M，就应该与开发人员讨论一下对这些查询进行调优了！</p>
<p><strong>3 个必不可少的工具</strong></p>
<p>尽管在了解具体设置时，SHOW STATUS 命令会非常有用，但是您还需要一些工具来解释 mysqld 所提供的大量数据。我发现有 3 个工具是必不可少的；在 参考资料 一节中您可以找到相应的链接。</p>
<p>大部分系统管理员都非常熟悉 top 命令，它为任务所消耗的 CPU 和内存提供了一个不断更新的视图。 mytop 对 top 进行了仿真；它为所有连接上的客户机以及它们正在运行的查询提供了一个视图。mytop 还提供了一个有关关键字缓冲区和查询缓存效率的实时数据和历史数据，以及有关正在运行的查询的统计信息。这是一个很有用的工具，可以查看系统中（比如 10 秒钟之内）的状况，您可以获得有关服务器健康信息的视图，并显示导致问题的任何连接。</p>
<p>mysqlard 是一个连接到 MySQL 服务器上的守护程序，负责每 5 分钟搜集一次数据，并将它们存储到后台的一个 Round Robin Database 中。有一个 Web 页面会显示这些数据，例如表缓存的使用情况、关键字效率、连接上的客户机以及临时表的使用情况。尽管 mytop 提供了服务器健康信息的快照，但是 mysqlard 则提供了长期的健康信息。作为奖励，mysqlard 使用自己搜集到的一些信息针对如何对服务器进行调优给出一些建议。</p>
<p>搜集 SHOW STATUS 信息的另外一个工具是 mysqlreport。其报告要远比 mysqlard 更加复杂，因为需要对服务器的每个方面都进行分析。这是对服务器进行调优的一个非常好的工具，因为它对状态变量进行适当计算来帮助确定需要修正哪些问题。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/60.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>JavaScript 的 new， 好久不见 :P</title>
		<link>http://adam.ofeva.com/blog/59.html</link>
		<comments>http://adam.ofeva.com/blog/59.html#comments</comments>
		<pubDate>Fri, 22 Aug 2008 07:32:18 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=59</guid>
		<description><![CDATA[avaScript是一门基于原型的语言，但它却拥有一个 new 操作符使得其看起来象一门经典的面对对象语言。那样也迷惑了程序员们，导致一些有问题的编程模式。
其实你永远不需要在JavaScript使用 new Object()。用字面量的形式{}去取代吧。
同理，不要使用 new Array() ，而代之以字面量[]。JavaScript中的数组并不象Java中的数组那样工作的，使用类似Java的语法只会让你糊涂。
同理不用使用 new Number, new String, 或者 new Boolean。这些的用法只会产生无用的类型封装对象。就直接使用简单的字面量吧。
不要使用 new Function 去创建函数对象。用函数表达式更好。比如：
frames[0].onfocus = new Function(”document.bgColor=’antiquewhite’”)
更好的写法是：
frames[0].onfocus = function () {document.bgColor = ‘antiquewhite’;};
第二种形式让脚本编译器更快的看到函数主体，于是其中的语法错误也会更快被检测出来。有时候程序员使用 new Function 是因为他们没有理解内部函数是如何工作的。
selObj.onchange = new Function(”dynamicOptionListObjects[”+dol.index+”].change(this)”);
如果我们让用字符串做函数体，编译器不能看到它们。如果我们用字符串表达式做函数体，我们同样也看不到它们。更好的方式就是不要盲目编程。通过制造一个返回值为函数的函数调用，我们可以明确的按值传递我们想要绑定的值。这允许我们在循环中初始化一系列 selObj 对象。

selObj.onchange = function (i) {
    return function () {
        dynamicOptionListObjects[i].change(this);
  [...]]]></description>
			<content:encoded><![CDATA[<p>avaScript是一门基于原型的语言，但它却拥有一个 new 操作符使得其看起来象一门经典的面对对象语言。那样也迷惑了程序员们，导致一些有问题的编程模式。</p>
<p>其实你永远不需要在JavaScript使用 new Object()。用字面量的形式{}去取代吧。</p>
<p>同理，不要使用 new Array() ，而代之以字面量[]。JavaScript中的数组并不象Java中的数组那样工作的，使用类似Java的语法只会让你糊涂。</p>
<p>同理不用使用 new Number, new String, 或者 new Boolean。这些的用法只会产生无用的类型封装对象。就直接使用简单的字面量吧。</p>
<p>不要使用 new Function 去创建函数对象。用函数表达式更好。比如：</p>
<p><code>frames[0].onfocus = new Function(”document.bgColor=’antiquewhite’”)</code></p>
<p>更好的写法是：</p>
<p><code>frames[0].onfocus = function () {document.bgColor = ‘antiquewhite’;};</code></p>
<p>第二种形式让脚本编译器更快的看到函数主体，于是其中的语法错误也会更快被检测出来。有时候程序员使用 new Function 是因为他们没有理解内部函数是如何工作的。</p>
<p><code>selObj.onchange = new Function(”dynamicOptionListObjects[”+dol.index+”].change(this)”);</code></p>
<p>如果我们让用字符串做函数体，编译器不能看到它们。如果我们用字符串表达式做函数体，我们同样也看不到它们。更好的方式就是不要盲目编程。通过制造一个返回值为函数的函数调用，我们可以明确的按值传递我们想要绑定的值。这允许我们在循环中初始化一系列 selObj 对象。<br />
<code><br />
selObj.onchange = function (i) {<br />
    return function () {<br />
        dynamicOptionListObjects[i].change(this);<br />
    };<br />
}(dol.index);</code></p>
<p>直接对一个函数使用new永远不是一个好主意。比如， new function 对构造新对象没有提供什么优势。<br />
<code><br />
myObj = new function () {<br />
    this.type = ‘core’;<br />
};</code></p>
<p>更好的方式是使用对象字面量，它更轻巧，更快捷。<br />
<code><br />
myObj = {<br />
    type: ‘core’<br />
};</code></p>
<p>假如我们需要创建的对象包含的方法需要访问私有变量或者函数，更好的方式仍然是避免使用new.<br />
<code><br />
var foo = new function() {<br />
    function processMessages(message) {<br />
        alert(”Message: ” + message.content);<br />
    }<br />
    this.init = function() {<br />
        subscribe(”/mytopic”, this, processMessages);<br />
    }<br />
}</code><br />
通过使用 new 去调用函数，对象会持有一个无意义的原型对象。这只会浪费内存而不会带来任何好处。如果我们不使用new，我们就不用在对象链维护一个无用的prototype对象。所以我们可以用（）来正确的调用工厂函数。<br />
<code>var foo = function () {<br />
    function processMessages(message) {<br />
        alert(”Message: ” + message.content);<br />
    }<br />
    return {<br />
        init: function () {<br />
            subscribe(”/mytopic”, this, processMessages);<br />
        }<br />
    };<br />
}();</code><br />
所以原则很简单： 唯一应该要用到new操作符的地方就是调用一个古老的构造器函数的时候。当调用一个构造器函数的时候，是强制要求使用new的。有时候可以来new一下, 有的时候还是不要了吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/59.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>理解jQuery对象</title>
		<link>http://adam.ofeva.com/blog/58.html</link>
		<comments>http://adam.ofeva.com/blog/58.html#comments</comments>
		<pubDate>Fri, 22 Aug 2008 05:12:14 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=58</guid>
		<description><![CDATA[学习JQuery时对$(&#8230;)操作后返回的jQuery对象具有如此灵活的操作方法感到惊讶，阅读JQuery源码后逐步明白一些道理。
下面仿照JQuery构造一个超简单的框架，以说明对JQuery的理解。

var jQuery = $ = function(selector){
    return new jQuery.fn.init(selector);
};
使用jQuery(&#8230;)和$是一样的，都是返回一个对象，这个对象是由jQuery.fn.init的构造体构造的，这个对象有什么来头呢 ？

jQuery.fn = jQuery.prototype = {
    init:function(selector){
        var elem = document.getElementById(selector);
        this[0] = elem;
        this.length = 1;
    [...]]]></description>
			<content:encoded><![CDATA[<p>学习JQuery时对$(&#8230;)操作后返回的jQuery对象具有如此灵活的操作方法感到惊讶，阅读JQuery源码后逐步明白一些道理。</p>
<p>下面仿照JQuery构造一个超简单的框架，以说明对JQuery的理解。<br />
<code><br />
var jQuery = $ = function(selector){<br />
    return new jQuery.fn.init(selector);<br />
};</code></p>
<p>使用jQuery(&#8230;)和$是一样的，都是返回一个对象，这个对象是由jQuery.fn.init的构造体构造的，这个对象有什么来头呢 ？<br />
<code><br />
jQuery.fn = jQuery.prototype = {<br />
    init:function(selector){<br />
        var elem = document.getElementById(selector);<br />
        this[0] = elem;<br />
        this.length = 1;<br />
        return this;<br />
    },<br />
    each:function(method){<br />
        for(var i=0; i&lt;this.length; i++){<br />
            method.call(this[i],i);<br />
        }<br />
    }<br />
};</code></p>
<p>可见，返回的是一个数组，所以并没有什么神秘的东西。</p>
<p>但这个数组还不能进行each的操作，需要扩展其原型方法，下面的这句很重要：</p>
<p><code> jQuery.fn.init.prototype = jQuery.fn;</code></p>
<p>这样，通过$(&#8230;)得到的对象就能进行each调用了。</p>
<p>下面测试一下：<br />
<code><br />
   &lt;div id=&quot;myid&quot;&gt;测试内容&lt;/div&gt;<br />
   &lt;script&gt;<br />
       $(&quot;myid&quot;).each(function(i){<br />
           alert(i+&quot;:&quot;+this.id+&quot;:&quot;+this.innerHTML);<br />
       });<br />
   &lt;/script&gt; </code></p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/58.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>jquery语法总结和注意事项</title>
		<link>http://adam.ofeva.com/blog/57.html</link>
		<comments>http://adam.ofeva.com/blog/57.html#comments</comments>
		<pubDate>Fri, 22 Aug 2008 04:59:54 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=57</guid>
		<description><![CDATA[1、关于页面元素的引用
通过jquery的$()引用元素包括通过id、class、元素名以及元素的层级关系及dom或者xpath条件等方法，且返回的对象为jquery对象（集合对象），不能直接调用dom定义的方法。

2、jQuery对象与dom对象的转换
只有jquery对象才能使用jquery定义的方法。注意dom对象和jquery对象是有区别的，调用方法时要注意操作的是dom对象还是jquery对象。
普通的dom对象一般可以通过$()转换成jquery对象。
如：$(document.getElementById(&#8221;msg&#8221;))则为jquery对象，可以使用jquery的方法。
由于jquery对象本身是一个集合。所以如果jquery对象要转换为dom对象则必须取出其中的某一项，一般可通过索引取出。
如：$(&#8221;#msg&#8221;)[0]，$(&#8221;div&#8221;).eq(1)[0]，$(&#8221;div&#8221;).get()[1]，$(&#8221;td&#8221;)[5]这些都是dom对象，可以使用dom中的方法，但不能再使用Jquery的方法。
以下几种写法都是正确的：

$("#msg").html();
$("#msg")[0].innerHTML;
$(&#8221;#msg&#8221;).eq(0)[0].innerHTML;
$(&#8221;#msg&#8221;).get(0).innerHTML;
3、如何获取jQuery集合的某一项
对于获取的元素集合，获取其中的某一项（通过索引指定）可以使用eq或get(n)方法或者索引号获取，要注意，eq返回的是jquery对象，而get(n)和索引返回的是dom元素对象。对于jquery对象只能使用jquery的方法，而dom对象只能使用dom的方法，如要获取第三个
元素的内容。有如下两种方法：

$("div").eq(2).html();               //调用jquery对象的方法
$("div").get(2).innerHTML;       //调用dom的方法属性
4、同一函数实现set和get
Jquery中的很多方法都是如此，主要包括如下几个：
$(&#8221;#msg&#8221;).html();               //返回id为msg的元素节点的html内容。
$(&#8221;#msg&#8221;).html(&#8221;new content&#8220;);
//将“new content” 作为html串写入id为msg的元素节点内容中,页面显示粗体的new content
$(&#8221;#msg&#8221;).text();              [...]]]></description>
			<content:encoded><![CDATA[<p>1、关于页面元素的引用<br />
通过jquery的$()引用元素包括通过id、class、元素名以及元素的层级关系及dom或者xpath条件等方法，且返回的对象为jquery对象（集合对象），不能直接调用dom定义的方法。<br />
<span id="more-57"></span><br />
2、jQuery对象与dom对象的转换<br />
只有jquery对象才能使用jquery定义的方法。注意dom对象和jquery对象是有区别的，调用方法时要注意操作的是dom对象还是jquery对象。<br />
普通的dom对象一般可以通过$()转换成jquery对象。<br />
如：$(document.getElementById(&#8221;msg&#8221;))则为jquery对象，可以使用jquery的方法。<br />
由于jquery对象本身是一个集合。所以如果jquery对象要转换为dom对象则必须取出其中的某一项，一般可通过索引取出。<br />
如：$(&#8221;#msg&#8221;)[0]，$(&#8221;div&#8221;).eq(1)[0]，$(&#8221;div&#8221;).get()[1]，$(&#8221;td&#8221;)[5]这些都是dom对象，可以使用dom中的方法，但不能再使用Jquery的方法。<br />
以下几种写法都是正确的：<br />
<code><br />
$("#msg").html();<br />
$("#msg")[0].innerHTML;<br />
$(&#8221;#msg&#8221;).eq(0)[0].innerHTML;<br />
$(&#8221;#msg&#8221;).get(0).innerHTML;</code></p>
<p>3、如何获取jQuery集合的某一项<br />
对于获取的元素集合，获取其中的某一项（通过索引指定）可以使用eq或get(n)方法或者索引号获取，要注意，eq返回的是jquery对象，而get(n)和索引返回的是dom元素对象。对于jquery对象只能使用jquery的方法，而dom对象只能使用dom的方法，如要获取第三个
<div>元素的内容。有如下两种方法：<br />
<code><br />
$("div").eq(2).html();               //调用jquery对象的方法<br />
$("div").get(2).innerHTML;       //调用dom的方法属性</code></p>
<p>4、同一函数实现set和get<br />
Jquery中的很多方法都是如此，主要包括如下几个：<br />
$(&#8221;#msg&#8221;).html();               //返回id为msg的元素节点的html内容。<br />
$(&#8221;#msg&#8221;).html(&#8221;<b>new content</b>&#8220;);<br />
//将“<b>new content</b>” 作为html串写入id为msg的元素节点内容中,页面显示粗体的new content</p>
<p>$(&#8221;#msg&#8221;).text();               //返回id为msg的元素节点的文本内容。<br />
$(&#8221;#msg&#8221;).text(&#8221;<b>new content</b>&#8220;);<br />
//将“<b>new content</b>” 作为普通文本串写入id为msg的元素节点内容中,页面显示<b>new content</b></p>
<p>$(&#8221;#msg&#8221;).height();               //返回id为msg的元素的高度<br />
$(&#8221;#msg&#8221;).height(&#8221;300&#8243;);       //将id为msg的元素的高度设为300<br />
$(&#8221;#msg&#8221;).width();               //返回id为msg的元素的宽度<br />
$(&#8221;#msg&#8221;).width(&#8221;300&#8243;);       //将id为msg的元素的宽度设为300</p>
<p>$(&#8221;input&#8221;).val(&#8221;);       //返回表单输入框的value值<br />
$(&#8221;input&#8221;).val(&#8221;test&#8221;);       //将表单输入框的value值设为test</p>
<p>$(&#8221;#msg&#8221;).click();       //触发id为msg的元素的单击事件<br />
$(&#8221;#msg&#8221;).click(fn);       //为id为msg的元素单击事件添加函数<br />
同样blur,focus,select,submit事件都可以有着两种调用方法</p>
<p>5、集合处理功能<br />
对于jquery返回的集合内容无需我们自己循环遍历并对每个对象分别做处理，jquery已经为我们提供的很方便的方法进行集合的处理。<br />
包括两种形式：<br />
<code><br />
$("p").each(function(i){this.style.color=['#f00','#0f0','#00f'][i]})<br />
//为索引分别为0，1，2的p元素分别设定不同的字体颜色。<br />
$(&#8221;tr&#8221;).each(function(i){this.style.backgroundColor=['#ccc','#fff'][i%2]})<br />
//实现表格的隔行换色效果<br />
$(&#8221;p&#8221;).click(function(){alert($(this).html())})<br />
//为每个p元素增加了click事件，单击某个p元素则弹出其内容<br />
</code><br />
6、扩展我们需要的功能<br />
<code><br />
$.extend({<br />
       min: function(a, b){return a &lt;b&gt; b?a:b; }<br />
});       //为jquery扩展了min,max两个方法<br />
</code></p>
<p>使用扩展的方法（通过“$.方法名”调用）：<br />
<code>alert("a=10,b=20,max="+$.max(10,20)+",min="+$.min(10,20));</code></p>
<p>7、支持方法的连写<br />
所谓连写，即可以对一个jquery对象连续调用各种不同的方法。</code><br />
例如：<br />
<code>$("p").click(function(){alert($(this).html())})<br />
.mouseover(function(){alert('mouse over event')})<br />
.each(function(i){this.style.color=['#f00','#0f0','#00f'][i]});</code></p>
<p>8、操作元素的样式<br />
主要包括以下几种方式：<br />
<code><br />
$("#msg").css("background");               //返回元素的背景颜色<br />
$("#msg").css("background","#ccc")       //设定元素背景为灰色<br />
$("#msg").height(300); $("#msg").width("200");       //设定宽高<br />
$("#msg").css({ color: "red", background: "blue" });//以名值对的形式设定样式<br />
$("#msg").addClass("select");       //为元素增加名称为select的class<br />
$("#msg").removeClass("select");       //删除元素名称为select的class<br />
$("#msg").toggleClass("select");       //如果存在（不存在）就删除（添加）名称为select的class<br />
</code><br />
9、完善的事件处理功能<br />
Jquery已经为我们提供了各种事件处理方法，我们无需在html元素上直接写事件，而可以直接为通过jquery获取的对象添加事件。<br />
如：<br />
<code><br />
$("#msg").click(function(){alert("good")})       //为元素添加了单击事件<br />
$("p").click(function(i){this.style.color=['#f00','#0f0','#00f'][i]})<br />
//为三个不同的p元素单击事件分别设定不同的处理</code><br />
jQuery中几个自定义的事件：<br />
（1）hover(fn1,fn2)：一个模仿悬停事件（鼠标移动到一个对象上面及移出这个对象）的方法。当鼠标移动到一个匹配的元素上面时，会触发指定的第一个函数。当鼠标移出这个元素时，会触发指定的第二个函数。<br />
//当鼠标放在表格的某行上时将class置为over，离开时置为out。<br />
<code><br />
$("tr").hover(function(){<br />
$(this).addClass("over");<br />
},<br />
       function(){<br />
       $(this).addClass("out");<br />
});</code><br />
（2）ready(fn):当DOM载入就绪可以查询及操纵时绑定一个要执行的函数。<br />
<code>$(document).ready(function(){alert("Load Success")})<br />
//页面加载完毕提示“Load Success”,相当于onload事件。与$(fn)等价</code><br />
（3）toggle(evenFn,oddFn): 每次点击时切换要调用的函数。如果点击了一个匹配的元素，则触发指定的第一个函数，当再次点击同一元素时，则触发指定的第二个函数。随后的每次点击都重复对这两个函数的轮番调用。<br />
      <code> //每次点击时轮换添加和删除名为selected的class。<br />
       $("p").toggle(function(){<br />
               $(this).addClass("selected");<br />
       },function(){<br />
               $(this).removeClass("selected");<br />
       });</code><br />
（4）trigger(eventtype): 在每一个匹配的元素上触发某类事件。<br />
例如：<br />
       <code>$("p").trigger("click");               //触发所有p元素的click事件</code><br />
（5）bind(eventtype,fn)，unbind(eventtype): 事件的绑定与反绑定<br />
从每一个匹配的元素中（添加）删除绑定的事件。<br />
例如：<br />
<code>$("p").bind("click", function(){alert($(this).text());});       //为每个p元素添加单击事件<br />
$("p").unbind();       //删除所有p元素上的所有事件<br />
$("p").unbind("click")       //删除所有p元素上的单击事件</code></p>
<p>10、几个实用特效功能<br />
其中toggle()和slidetoggle()方法提供了状态切换功能。<br />
如toggle()方法包括了hide()和show()方法。<br />
slideToggle()方法包括了slideDown()和slideUp方法。</p>
<p>11、几个有用的jQuery方法<br />
<code>$.browser.浏览器类型：检测浏览器类型。有效参数：safari, opera, msie, mozilla。如检测是否ie：$.browser.isie，是ie浏览器则返回true。<br />
$.each(obj, fn)：通用的迭代函数。可用于近似地迭代对象和数组（代替循环）。<br />
如<br />
$.each( [0,1,2], function(i, n){ alert( &#8220;Item #&#8221; + i + &#8220;: &#8221; + n ); });<br />
等价于：<br />
var tempArr=[0,1,2];<br />
for(var i=0;i&lt;tempArr.length;i++){<br />
       alert(&#8221;Item #&#8221;+i+&#8221;: &#8220;+tempArr[i]);<br />
}</code><br />
也可以处理json数据，如<br />
<code>$.each( { name: "John", lang: "JS" }, function(i, n){ alert( "Name: " + i + ", Value: " + n ); });</code><br />
结果为：<br />
Name:name, Value:John<br />
Name:lang, Value:JS<br />
$.extend(target,prop1,propN)：用一个或多个其他对象来扩展一个对象，返回这个被扩展的对象。这是jquery实现的继承方式。<br />
如：<br />
<code><br />
$.extend(settings, options);<br />
//合并settings和options，并将合并结果返回settings中，相当于options继承setting并将继承结果保存在setting中。<br />
var settings = $.extend({}, defaults, options);<br />
//合并defaults和options，并将合并结果返回到setting中而不覆盖default内容。<br />
可以有多个参数（合并多项并返回）<br />
$.map(array, fn)：数组映射。把一个数组中的项目(处理转换后)保存到到另一个新数组中，并返回生成的新数组。<br />
如：<br />
var tempArr=$.map( [0,1,2], function(i){ return i + 4; });<br />
tempArr内容为：[4,5,6]<br />
var tempArr=$.map( [0,1,2], function(i){ return i &gt; 0 ? i + 1 : null; });<br />
tempArr内容为：[2,3]<br />
$.merge(arr1,arr2):合并两个数组并删除其中重复的项目。<br />
如：$.merge( [0,1,2], [2,3,4] )       //返回[0,1,2,3,4]<br />
$.trim(str)：删除字符串两端的空白字符。<br />
如：$.trim(&#8221;   hello, how are you?   &#8220;);         //返回&#8221;hello,how are you? &#8221;<br />
</code><br />
12、解决自定义方法或其他类库与jQuery的冲突<br />
很多时候我们自己定义了$(id)方法来获取一个元素，或者其他的一些js类库如prototype也都定义了$方法，如果同时把这些内容放在一起就会引起变量方法定义冲突，Jquery对此专门提供了方法用于解决此问题。<br />
使用jquery中的jQuery.noConflict();方法即可把变量$的控制权让渡给第一个实现它的那个库或之前自定义的$方法。之后应用 Jquery的时候只要将所有的$换成jQuery即可，如原来引用对象方法$(&#8221;#msg&#8221;)改为jQuery(&#8221;#msg&#8221;)。<br />
如：<br />
jQuery.noConflict();<br />
// 开始使用jQuery<br />
jQuery(&#8221;div   p&#8221;).hide();<br />
// 使用其他库的 $()<br />
$(&#8221;content&#8221;).style.display = &#8216;none&#8217;;</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/57.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>算法，产品经理的必修课</title>
		<link>http://adam.ofeva.com/blog/56.html</link>
		<comments>http://adam.ofeva.com/blog/56.html#comments</comments>
		<pubDate>Fri, 22 Aug 2008 02:39:42 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[产品经理的盒子]]></category>

		<category><![CDATA[pm]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=56</guid>
		<description><![CDATA[你知道IMBD的电影排行算法么？你有兴趣研究一下么？
加权平均分(WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C
在这里：
R = 该电影的平均分
v = 该电影的总投票数
m = 列入前250所需要的最少票数(目前是1300票)
C = 数据库中所有电影的总平均分(目前是6.7)
哈哈，厉害吧，投票数多的话，那么R，也就是每个人的电影评分就起到主要作用；
如果投票数少呢，也不能说电影不好，小众的东西还往往是精品呢，文化的东西，毕竟有可能因为语言等因素，或者曲高和寡变得在IMDB上变得小众，这样如果投票数少，那么也不能一棒子打死，就趋于平均水平。
如果票数相同呢，那么就看R了，平均分越高，那么自然排名就越靠前啦。
好玩吧，再看一个。
很多网站在设计博客的排行时，在时间相关性上很困惑，为了满足访问网站频率不同的用户需求，他们只好按日、周、月来做排行，非常明显的缺陷是，让每周或每月的开始时，周榜和月榜上的精彩文章精彩程度不够，而上周末或月末的精彩文章可能被过早撤出用户视线。但是如果按七天排行或者三十天排行，算法又太复杂。
有没有兼顾的算法呢？答案是有的。

假定用户访问周期介于T1到TN，TN=N*T1，用户访问频率在T1到TN之间线性分布。
设文章在每个时间TX里获得的访问量为TXPV，设计系数A=(N-1)/N
使用计算式
   T1PV*A^(N-1)+T2PV*A^(N-2)+T3PV*A^(N-3)+……+TNPV=∑TXPV*A^(N-X)
来计算随时间衰减的关注度。
太TMD牛了，佩服的五体投地。
如果算周排行榜，一篇文章在第一天的访问量跟第七天的访问量在权重上明显是不同的，到第七天还有人在访问，那就说明这篇文章更热。
通过这件事情我想，作为一个产品经理，其实应该有这样的基本功力。今天大家在研究热文的的出现和排序算法的时候，我为自己是个理科生感到非常惭愧，对于分析一种算法的改变对于效果的影响上，我表现得跟个文科生一样。倒也不是说文科生同学们就干不了这个事儿，只是说我这么多年的专业训练啊，都tmd练到哪儿去啦？？！！
作为一个将致力于成为一个有创意的、脚踏实地的、有执行力的、成熟的、经验丰富的、牛B哄哄的产品经理作为毕生奋斗目标的人，我今天的体会是一定要严于律己，有意识的培养自己对于算法的感觉，积极参与工程师同志们的算法讨论，不断修炼，逐渐成仙。
]]></description>
			<content:encoded><![CDATA[<p>你知道IMBD的电影排行算法么？你有兴趣研究一下么？</p>
<p><code>加权平均分(WR) = (v ÷ (v+m)) × R + (m ÷ (v+m)) × C<br />
在这里：<br />
R = 该电影的平均分<br />
v = 该电影的总投票数<br />
m = 列入前250所需要的最少票数(目前是1300票)<br />
C = 数据库中所有电影的总平均分(目前是6.7)</code></p>
<p>哈哈，厉害吧，投票数多的话，那么R，也就是每个人的电影评分就起到主要作用；<br />
如果投票数少呢，也不能说电影不好，小众的东西还往往是精品呢，文化的东西，毕竟有可能因为语言等因素，或者曲高和寡变得在IMDB上变得小众，这样如果投票数少，那么也不能一棒子打死，就趋于平均水平。<br />
如果票数相同呢，那么就看R了，平均分越高，那么自然排名就越靠前啦。</p>
<p>好玩吧，再看一个。</p>
<p>很多网站在设计博客的排行时，在时间相关性上很困惑，为了满足访问网站频率不同的用户需求，他们只好按日、周、月来做排行，非常明显的缺陷是，让每周或每月的开始时，周榜和月榜上的精彩文章精彩程度不够，而上周末或月末的精彩文章可能被过早撤出用户视线。但是如果按七天排行或者三十天排行，算法又太复杂。<br />
有没有兼顾的算法呢？答案是有的。</p>
<p><code><br />
假定用户访问周期介于T1到TN，TN=N*T1，用户访问频率在T1到TN之间线性分布。<br />
设文章在每个时间TX里获得的访问量为TXPV，设计系数A=(N-1)/N</code></p>
<p>使用计算式<br />
  <code> T1PV*A^(N-1)+T2PV*A^(N-2)+T3PV*A^(N-3)+……+TNPV=∑TXPV*A^(N-X)</code><br />
来计算随时间衰减的关注度。<br />
太TMD牛了，佩服的五体投地。<br />
如果算周排行榜，一篇文章在第一天的访问量跟第七天的访问量在权重上明显是不同的，到第七天还有人在访问，那就说明这篇文章更热。</p>
<p>通过这件事情我想，作为一个产品经理，其实应该有这样的基本功力。今天大家在研究热文的的出现和排序算法的时候，我为自己是个理科生感到非常惭愧，对于分析一种算法的改变对于效果的影响上，我表现得跟个文科生一样。倒也不是说文科生同学们就干不了这个事儿，只是说我这么多年的专业训练啊，都tmd练到哪儿去啦？？！！</p>
<p>作为一个将致力于成为一个有创意的、脚踏实地的、有执行力的、成熟的、经验丰富的、牛B哄哄的产品经理作为毕生奋斗目标的人，我今天的体会是一定要严于律己，有意识的培养自己对于算法的感觉，积极参与工程师同志们的算法讨论，不断修炼，逐渐成仙。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/56.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>使用 jQuery 简化 Ajax 开发</title>
		<link>http://adam.ofeva.com/blog/55.html</link>
		<comments>http://adam.ofeva.com/blog/55.html#comments</comments>
		<pubDate>Thu, 21 Aug 2008 03:52:20 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=55</guid>
		<description><![CDATA[   jQuery 是一个JavaScript 库，它有助于简化 JavaScript? 以及 Asynchronous JavaScript + XML (Ajax) 编程。与类似的 JavaScript 库不同，jQuery 具有独特的基本原理，可以简洁地表示常见的复杂代码。学习 jQuery 基本原理，探索其特性和功能，执行一些常见的 Ajax 任务并掌握如何使用插件扩展 jQuery。

jQuery 是什么？
jQuery 由 John Resig 创建于 2006 年初，对于任何使用 JavaScript 代码的程序员来说，它是一个非常有用的 JavaScript 库。无论您是刚刚接触 JavaScript 语言，并且希望获得一个能解决文档对象模型（Document Object Model，DOM）脚本和 Ajax 开发中一些复杂问题的库，还是作为一个厌倦了 DOM 脚本和 Ajax 开发中无聊的重复工作的资深 JavaScript 专家，jQuery 都会是您的首选。
jQuery 能帮助您保证代码简洁易读。您再也不必编写大堆重复的循环代码和 DOM 脚本库调用了。使用 jQuery，您可以把握问题的要点，并使用尽可能最少的代码实现您想要的功能。
毫无疑问，jQuery 的原理是独一无二的：它的目的就是保证代码简洁并可重用。当您理解并体会这一原理后，便可以开始学习本教程了，看看 jQuery 对我们的编程方式有多少改进吧。
一些简单的代码简化
下面是一个简单示例，它说明了 jQuery 对代码的影响。要执行一些真正简单和常见的任务，比方说为页面的某一区域中的每个链接附加一个单击（click）事件，您可以使用纯 [...]]]></description>
			<content:encoded><![CDATA[<p>   jQuery 是一个JavaScript 库，它有助于简化 JavaScript? 以及 Asynchronous JavaScript + XML (Ajax) 编程。与类似的 JavaScript 库不同，jQuery 具有独特的基本原理，可以简洁地表示常见的复杂代码。学习 jQuery 基本原理，探索其特性和功能，执行一些常见的 Ajax 任务并掌握如何使用插件扩展 jQuery。<br />
<span id="more-55"></span><br />
jQuery 是什么？</p>
<p>jQuery 由 John Resig 创建于 2006 年初，对于任何使用 JavaScript 代码的程序员来说，它是一个非常有用的 JavaScript 库。无论您是刚刚接触 JavaScript 语言，并且希望获得一个能解决文档对象模型（Document Object Model，DOM）脚本和 Ajax 开发中一些复杂问题的库，还是作为一个厌倦了 DOM 脚本和 Ajax 开发中无聊的重复工作的资深 JavaScript 专家，jQuery 都会是您的首选。</p>
<p>jQuery 能帮助您保证代码简洁易读。您再也不必编写大堆重复的循环代码和 DOM 脚本库调用了。使用 jQuery，您可以把握问题的要点，并使用尽可能最少的代码实现您想要的功能。</p>
<p>毫无疑问，jQuery 的原理是独一无二的：它的目的就是保证代码简洁并可重用。当您理解并体会这一原理后，便可以开始学习本教程了，看看 jQuery 对我们的编程方式有多少改进吧。</p>
<p>一些简单的代码简化</p>
<p>下面是一个简单示例，它说明了 jQuery 对代码的影响。要执行一些真正简单和常见的任务，比方说为页面的某一区域中的每个链接附加一个单击（click）事件，您可以使用纯 JavaScript 代码和 DOM 脚本来实现，如 清单 1 所示。</p>
<p>清单 1. 没有使用 jQuery 的 DOM 脚本</p>
<p><code>var external_links = document.getElementById('external_links');<br />
var links = external_links.getElementsByTagName('a');<br />
for (var i=0;i &lt; links.length;i++) {<br />
    var link = links.item(i);<br />
    link.onclick = function() {<br />
        return confirm('You are going to visit: ' + this.href);<br />
    };<br />
}</code></p>
<p>清单 2 显示了使用 jQuery 实现的相同的功能。</p>
<p>清单 2. 使用了 jQuery 的 DOM 脚本</p>
<p><code>$('#external_links a').click(function() {<br />
    return confirm('You are going to visit: ' + this.href);<br />
});<br />
</code></p>
<p>是不是很神奇？ 使用 jQuery，您可以把握问题的要点，只让代码实现您想要的功能，而省去了一些繁琐的过程。无需对元素进行循环，click() 函数将完成这些操作。同样也不需要进行多个 DOM 脚本调用。您只需要使用一个简短的字符串对所需的元素进行定义即可。</p>
<p>理解这一代码的工作原理可能会有一点复杂。首先，我们使用了 $() 函数 —— jQuery 中功能最强大的函数。通常，我们都是使用这个函数从文档中选择元素。在本例中，一个包含有一些层叠样式表（Cascading Style Sheet，CSS）语法的字符串被传递给函数，然后 jQuery 尽可能高效地把这些元素找出来。</p>
<p>如果您具备 CSS 选择器的基本知识，那么应该很熟悉这些语法。在 清单 2 中，#external_links 用于检索 id 为 external_links 的元素。a 后的空格表示 jQuery 需要检索 external_links 元素中的所有 <a> 元素。用英语说起来非常绕口，甚至在 DOM 脚本中也是这样，但是在 CSS 中这再简单不过了</p>
<p>$() 函数返回一个含有所有与 CSS 选择器匹配的元素的 jQuery 对象。jQuery 对象 类似于数组，但是它附带有大量特殊的 jQuery 函数。比方说，您可以通过调用 click 函数把 click 处理函数指定给 jQuery 对象中的所有元素。</p>
<p>还可以向 $() 函数传递一个元素或者一个元素数组，该函数将把这些元素封装在一个 jQuery 对象中。您可能会想要使用这个功能将 jQuery 函数用于一些对象，比方说 window 对象。例如，我们通常会像下面这样把函数分配给加载事件：<br />
<code>window.onload = function() {<br />
    // do this stuff when the page is done loading<br />
};</code></p>
<p>使用 jQuery 编写的功能相同的代码：<br />
<code>$(window).load(function() {<br />
    // run this when the whole page has been downloaded<br />
});</code></p>
<p>您可能有所体会，等待窗口加载的过程是非常缓慢而且令人痛苦的，这是因为必须等整个页面加载完所有的内容，包括页面上所有的的图片。有的时候，您希望首先完成图片加载，但是在大多数情况下，您只需加载超文本标志语言（Hypertext Markup Language，HTML）就可以了。通过在文档中创建特殊的 ready 事件，jQuery 解决了这个问题，方法如下：</p>
<p><code>$(document).ready(function() {<br />
    // do this stuff when the HTML is all ready<br />
});<br />
</code></p>
<p>这个代码围绕 document 元素创建了一个 jQuery 对象，然后建立一个函数，用于在 HTML DOM 文档就绪的时候调用实例。可以根据需要任意地调用这个函数。并且能够以真正的 jQuery 格式，使用快捷方式调用这个函数。这很简单，只需向 $() 函数传递一个函数就可以了：</p>
<p><code>$(function() {<br />
    // run this when the HTML is done downloading<br />
});</code></p>
<p>到目前以止，我已经向大家介绍了 $() 函数的三种用法。第四种方法可以使用字符串来创建元素。结果会产生一个包含该元素的 jQuery 对象。清单 3 显示的示例在页面中添加了一个段落。</p>
<p>清单 3. 创建和附加一个简单的段落<br />
<code>$('
</p>
<p>&#8216;)<br />
    .html(&#8217;Hey World!&#8217;)<br />
    .css(&#8217;background&#8217;, &#8216;yellow&#8217;)<br />
    .appendTo(&#8221;body&#8221;);<br />
</code></p>
<p>在前一个例子中您可能已经注意到，jQuery 中的另一个功能强大的特性就是方法链接（method chaining）。每次对 jQuery 对象调用方法时，方法都会返回相同的 jQuery 对象。这意味着如果您需要对 jQuery 对象调用多个方法，那么您不必重新键入选择器就可以实现这一目的：</p>
<p><code>$('#message').css('background', 'yellow').html('Hello!').show();</code></p>
<p>使 Ajax 变得简单</p>
<p>使用 jQuery 将使 Ajax 变得及其简单。jQuery 提供有一些函数，可以使简单的工作变得更加简单，复杂的工作变得不再复杂。</p>
<p>Ajax 最常见的用法就是把一块 HTML 代码加载到页面的某个区域中去。为此，只需简单地选择所需的元素，然后使用 load() 函数即可。下面是一个用于更新统计信息的示例：</p>
<p><code>$('#stats').load('stats.html');</code></p>
<p>通常，我们只需简单地把一些参数传递给服务器中的某个页面。正如您所预料的，使用 jQuery 实现这一操作非常地简单。您可以使用 $.post() 或者 $.get()，这由所需的方法决定。如果需要的话，您还可以传递一个可选的数据对象和回调函数。清单 4 显示了一个发送数据和使用回调的简单示例。</p>
<p>清单 4. 使用 Ajax 向页面发送数据</p>
<p><code>$.post('save.cgi', {<br />
    text: 'my string',<br />
    number: 23<br />
}, function() {<br />
    alert('Your data has been saved.');<br />
});<br />
</code></p>
<p>如果您确实需要编写一些复杂的 Ajax 脚本，那么需要用到 $.ajax() 函数。您可以指定 xml、script、html 或者 json，jQuery 将自动为回调函数准备合适的结果，这样您便可以立即使用该结果。还可以指定 beforeSend、error、success 或者 complete 回调函数，向用户提供更多有关 Ajax 体验的反馈。此外，还有一些其它的参数可供使用，您可以使用它们设置 Ajax 请求的超时，也可以设置页面 “最近一次修改” 的状态。清单 5 显示了一个使用一些我所提到的参数检索 XML 文档的示例。</p>
<p>清单 5. $.ajax() 使 Ajax 由复杂变简单</p>
<p><code>$.ajax({<br />
    url: 'document.xml',<br />
    type: 'GET',<br />
    dataType: 'xml',<br />
    timeout: 1000,<br />
    error: function(){<br />
        alert('Error loading XML document');<br />
    },<br />
    success: function(xml){<br />
        // do something with xml<br />
    }<br />
});</code></p>
<p>当 success 回调函数返回 XML 文档后，您可以使用 jQuery 检索这个 XML 文档，其方式与检索 HTML 文档是一样的。这样使得处理 XML 文档变得相当地容易，并且把内容和数据集成到了您的 Web 站点里面。清单 6 显示了 success 函数的一个扩展，它为 XML 中的每个  元素都添加了一个列表项到 Web 页面中。</p>
<p>清单 6. 使用 jQuery 处理 XML 文档</p>
<p><code>success: function(xml){<br />
    $(xml).find('item').each(function(){<br />
        var item_text = $(this).text();<br />
        $('
<li></li>
<p>&#8216;)<br />
            .html(item_text)<br />
            .appendTo(&#8217;ol&#8217;);<br />
    });<br />
}</code></p>
<p>为 HTML 添加动画</p>
<p>可以使用 jQuery 处理基本的动画和显示效果。animate() 函数是动画代码的核心，它用于更改任何随时间变化的数值型的 CSS 样式值。比方说，您可以变化高度、宽度、不透明度和位置。还可以指定动画的速度，定为毫秒或者预定义的速度：慢速，中速或快速。</p>
<p>下面是一个同时变化某个元素高度和宽度的示例。请注意，这些参数没有开始值，只有最终值。开始值取自元素的当前尺寸。同时我也附加了一个回调函数。</p>
<p><code>$('#grow').animate({ height: 500, width: 500 }, "slow", function(){<br />
    alert('The element is done growing!');<br />
});</code></p>
<p>jQuery 的内置函数使更多常见的动画更容易完成。可以使用 show() 和 hide() 元素，立即显示或者以特定的速度显示。还可以通过使用 fadeIn() 和 fadeOut()，或者 slideDown() 和 slideUp() 显示和隐藏元素，这取决于您所需要的显示效果。下面的示例定义了一个下滑的导航菜单。</p>
<p><code>$('#nav').slideDown('slow');</code></p>
<p>DOM 脚本和事件处理</p>
<p>或许 jQuery 最擅长的就是简化 DOM 脚本和事件处理。遍历和处理 DOM 非常简单，同时附加、移除和调用事件也十分容易，且不像手动操作那样容易出错。</p>
<p>从本质上说，jQuery 可以使 DOM 脚本中的常用操作变得更加容易。您可以创建元素并且使用 append() 函数把它们与其它的一些元素链接到一起，使用 clone() 复制元素，使用 html() 设置内容，使用 empty() 函数删除内容，使用 remove() 函数删除所有的元素，即便是使用 wrap() 函数，用其他元素将这些元素包装起来。</p>
<p>通过遍历 DOM，一些函数可以用于更改 jQuery 对象本身的内容。可以获得元素所有的 siblings()、parents() 和 children()。还可以选择 next() 和 prev() 兄弟元素。find() 函数或许是功能最强大的函数，它允许使用 jQuery 选择器搜索 jQuery 对象中元素的后代元素。</p>
<p>如果结合使用 end() 函数，那么这些函数将变得更加强大。这个函数的功能类似于 undo 函数，用于返回到调用 find() 或 parents() 函数（或者其它遍历函数）之前的 jQuery 对象。</p>
<p>如果配合方法链接（method chaining）一起使用，这些函数可以使复杂的操作看上去非常简单。清单 7 显示了一个示例，其中包含有一个登录表单并处理了一些与之有关的元素。</p>
<p>清单 7. 轻松地遍历和处理 DOM</p>
<p><code>$('form#login')<br />
    // hide all the labels inside the form with the 'optional' class<br />
    .find('label.optional').hide().end()</p>
<p>    // add a red border to any password fields in the form<br />
    .find('input:password').css('border', '1px solid red').end()</p>
<p>    // add a submit handler to the form<br />
    .submit(function(){<br />
        return confirm('Are you sure you want to submit?');<br />
    });</code></p>
<p>不管您是否相信，这个示例只是一行满是空白的被链接的代码。首先，选择登录表单。然后，发现其中含有可选标签，隐藏它们，并调用 end() 返回表单。然后，我创建了密码字段，将其边界变为红色，再次调用 end() 返回表单。最后，我在表单中添加了一个提交事件处理程序。其中尤为有趣的就是（除了其简洁性以外），jQuery 完全优化了所有的查询操作，确保将所有内容很好地链接在一起后，不需要对一个元素执行两次查询。</p>
<p>处理常见事件就像调用函数（比方说 click()、submit() 或 mouseover()）和为其传递事件处理函数一样简单。此外，还可以使用 bind(&#8217;eventname&#8217;, function(){}) 指定自定义的事件处理程序。可以使用 unbind(&#8217;eventname&#8217;) 删除某些事件或者使用 unbind() 删除所有的事件。有关这些函数的使用方法的完整列表，请参阅 参考资料 中的 jQuery 应用程序编程接口（Application Program Interface，API）文档。</p>
<p>释放 jQuery 选择器的强大能量</p>
<p>我们经常会使用 ID 来选择元素，比如 #myid，或者通过类名，比如 div.myclass 来选择元素。然而，jQuery 提供了更为复杂和完整的选择器语法，允许我们在单个选择器中选择几乎所有的元素组合。</p>
<p>jQuery 的选择器语法主要是基于 CSS3 和 XPath 的。对 CSS3 和 XPath 了解的越多，使用 jQuery 时就越加得心应手。有关 jQuery 选择器的完整列表，包括 CSS 和 XPath，请参阅 参考资料 中的链接。</p>
<p>CSS3 包含一些并不是所有浏览器都支持的语法，因此我们很少使用它。然而，我们仍然可以在 jQuery 中使用 CSS3 选择元素，因为 jQuery 具备自己的自定义选择器引擎。比方说，要在表格中的每一个空列中都添加一个横杠，可以使用：:empty 伪选择器（pseudo-selector）：<br />
<code>$('td:empty').html('-');</code></p>
<p>如果需要找出所有不含特定类的元素呢？ CSS3 同样提供了一个语法可以完成这个目的，使用 :not 伪选择器： 如下代码显示了如何隐藏所有不含 required 类的输入内容：</p>
<p><code>$('input:not(.required)').hide();</code></p>
<p>与在 CSS 中一样，可以使用逗号将多个选择器连接成一个。下面是一个同时隐藏页面上所有类型列表的简单示例：</p>
<p><code>$('ul, ol, dl').hide();</code></p>
<p>XPath 是一种功能强大的语法，用于在文档中搜寻元素。它与 CSS 稍有区别，不过它能实现的功能略多于 CSS。要在所有复选框的父元素中添加一个边框，可以使用 XPath 的 /.. 语法：</p>
<p><code>$("input:checkbox/..").css('border', '1px solid #777');</code></p>
<p>jQuery 中也加入了一些 CSS 和 XPath 中没有的选择器。比方说，要使一个表更具可读性，通常可以在表格的奇数行或偶数行中附加一个不同的类名 —— 也可以称作把表分段（striping）。使用 jQuery 不费吹灰之力就可以做到这点，这需要归功于 odd 伪选择器。下面这个例子使用 striped 类改变了表格中所有奇数行的背景颜色：</p>
<p><code>$('table.striped &gt; tr:odd').css('background', '#999999');</code></p>
<p>我们可以看到强大的 jQuery 选择器是如何简化代码的。不论您想处理什么样的元素，不管这个元素是具体的还是模糊的，都有可能找到一种方法使用一个 jQuery选择器对它们进行定义。</p>
<p>使用插件扩展 jQuery</p>
<p>与大多数软件不同，使用一个复杂的 API 为 jQuery 编写插件并不是非常困难。事实上，jQuery 插件非常易于编写，您甚至希望编写一些插件来使代码更加简单。下面是可以编写的最基本的 jQuery 插件：</p>
<p><code>$.fn.donothing = function(){<br />
    return this;<br />
};</code></p>
<p>虽然非常简单，但是还是需要对这个插件进行一些解释。首先，如果要为每一个 jQuery 对象添加一个函数，必须把该函数指派给 $.fn。第二，这个函数必须要返回一个 this（jQuery 对象），这样才不至于打断 方法链接（method chaining）。</p>
<p>可以轻松地在这个示例之上构建。要编写一个更换背景颜色的插件，以替代使用 css(&#8217;background&#8217;)，可以使用下面的代码：</p>
<p><code>$.fn.background = function(bg){<br />
    return this.css('background', bg);<br />
};</code></p>
<p>清注意，可以只从 css() 返回值，因为已经返回了 jQuery 对象。因此，方法链接（method chaining）仍然运作良好。</p>
<p>我建议在需要重复工作的时候使用 jQuery 插件。比方说，如果您需要使用 each() 函数反复执行相同的操作，那么可以使用一个插件来完成。</p>
<p>由于 jQuery 插件相当易于编写，所以有上百种可供你选择使用。jQuery 提供的插件可用于制表、圆角、滑动显示、工具提示、日期选择器，以及我们可以想到的一切效果。有关插件的完整列表，请参阅 参考资料。</p>
<p>最为复杂、使用最为广泛的插件要属界面（Interface），它是一种动画插件，用于处理排序、拖放功能、复杂效果、以及其它有趣和复杂的用户界面（User Interface，UI）。界面对于 jQuery 来说就如 Scriptaculous 对于Prototype 一样。</p>
<p>表单插件也同样流行且非常有用，通过它可以使用 Ajax 在后台中轻松地提交表单。这个插件用于处理一些常见的情况：您需要截获某个表单的提交事件，找出所有不同的输入字段，并使用这些字段构造一个 Ajax 调用。</p>
<p>我只是简要地介绍了使用 jQuery 可能完成的任务。jQuery 使用起来非常有趣，因此我们总是能学到看上去很简单的新技巧和新特性。从刚开始使用 jQuery 的那一刻起，jQuery 便可以完全简化您的 JavaScript 和 Ajax 编程；每学会一点新知识，您的代码就会更简单一点。</p>
<p>学习了 jQuery 之后，我在使用 JavaScript 语言进行编程的同时也获得了许多的乐趣。不用操心所有无聊的内容，我可以专注地编写有趣的内容。使用 jQuery 后，我几乎就告别了编写 for 循环代码的时代。甚至在想到要使用其它 JavaScript 库时，不禁会有所畏缩不前。jQuery 确确实实改变了我对 JavaScript 编程的看法。</p>
<ul>
<li><a href="http://jquery.com/">jQuery</a>：访问 jQuery 主页并下载源代码。</li>
<li><a href="http://docs.jquery.com/DOM/Traversing/Selectors">选择器</a>：获取在 jQuery 中可以使用的选择器的完整列表，包括 CSS3 和 XPath 选择器。</li>
<li><a href="http://docs.jquery.com/Plugins">jQuery 插件</a>：获取可以使用的 jQuery 插件的完整列表。</li>
<li><a href="http://interface.eyecon.ro/">Interface</a>：尝试使用 jQuery 最基本的插件，可用于动画、显示效果、拖放功能和用户界面（UI）。</li>
<li><a href="http://jquery.com/dev/svn/trunk/plugins/form/form.js?format=txt">Form 插件</a>：获取 jQuery 插件，它可用于使用 Ajax 提交表单。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/55.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>如何提高页面响应速度</title>
		<link>http://adam.ofeva.com/blog/54.html</link>
		<comments>http://adam.ofeva.com/blog/54.html#comments</comments>
		<pubDate>Thu, 21 Aug 2008 03:10:50 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<category><![CDATA[xhtml+css]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=54</guid>
		<description><![CDATA[访问速度缓慢的互联网已经成为过去,但页面能瞬时呈现也只是未来才会发生的事情. Christianheilmann的一些技巧，现在就可以令你的网站访问起来更为流畅。
页面首次访问时的延时是网站和Web应用设计中遇到的一个很重要的问题。用户总是感觉页面相应的不够快。
为什么用户会有这样的感觉？也许用户还保留多年前那种按分钟计费的接入网方式的使用习惯（现在的饭店或机场还保持那种接入方式）；也许是因为用户觉得页面要有足够快的响应才能称得上所谓的信息高速路。但在我看来这是好莱坞的责任。在每部好莱坞的动作大片中：敲击一下键盘的同时，电脑屏幕上就会出现超高分辨率，有着密密麻麻数据显示的精美网站操作界面；而且网站上读取一部百科全书也不过短短几毫秒就可以完成。
但在现实生活中却完全不是这么回事,因为无论你如何尽量简化你的页面,延迟还是存在的。而且为了使页面更绚丽，通常会使用flash，但如果滥用flash会严重影响页面的响应速度。作为网络应用，还必须保证页面元素的加载顺序，不会因为页面上未完全加载的元素被用户访问而造成异常。
哪些因素造成网站响应缓慢？
当谈到提高网站响应速度，最通常的做法就是尽可能的减少网站文件的尺寸。(这也导致针对JavaScript库文件大小的无休止的讨论，但最终也没什么结果。）实际上,有许多因素会影响到网页初次访问的响应速度:
    * HTML文档的大小。
    * 页面中嵌入的脚本、图像、多媒体元素文档的大小。
    * HTML页面的复杂程度。(浏览器可以很快的展现简单的页面)
    * 用户的接入速度
    * 会被页面访问的第三方内容所在服务器的访问速度。
    * 网站域名及其页面包含的外部域名的ＤＮＳ解析速度。
    * 用户计算机的性能。(浏览器会因为系统消耗过多的资源在其他任务上而变得响应缓慢)。
    * 服务器的相应速度。
除了以上的技术上的因素会导致网站响应变慢以外，还有一些人为设计上的因素。例如：为了避免页面加载过程中出现的页面区域错乱和无图像显示；页面被设计为需要页面内容完全加载完毕后才一起显示。
让网站响应便快的方法
 经过实践，以下经验对于解决由于技术和人为因素造成网站响应变慢的问题会有所帮助。
    * 在不影响页面显示质量的前提下，尽可能的优化HTML代码。（这包括在发布页面时，去掉HTML文档中的注释以及冗余的换行标记。但为了保证页面的可读性，这些代码还应当保留在源代码中）
    * 页面中尽可能少的包含其他外部引用，减少文档之间的依赖。（可以将多个脚本放入一个脚本文件，用CSS的sprite技巧将多个小图片合并为一个大图，这样就只需要加载一次）
   [...]]]></description>
			<content:encoded><![CDATA[<p>访问速度缓慢的互联网已经成为过去,但页面能瞬时呈现也只是未来才会发生的事情. Christianheilmann的一些技巧，现在就可以令你的网站访问起来更为流畅。</p>
<p>页面首次访问时的延时是网站和Web应用设计中遇到的一个很重要的问题。用户总是感觉页面相应的不够快。<br />
为什么用户会有这样的感觉？也许用户还保留多年前那种按分钟计费的接入网方式的使用习惯（现在的饭店或机场还保持那种接入方式）；也许是因为用户觉得页面要有足够快的响应才能称得上所谓的信息高速路。但在我看来这是好莱坞的责任。在每部好莱坞的动作大片中：敲击一下键盘的同时，电脑屏幕上就会出现超高分辨率，有着密密麻麻数据显示的精美网站操作界面；而且网站上读取一部百科全书也不过短短几毫秒就可以完成。<br />
但在现实生活中却完全不是这么回事,因为无论你如何尽量简化你的页面,延迟还是存在的。而且为了使页面更绚丽，通常会使用flash，但如果滥用flash会严重影响页面的响应速度。作为网络应用，还必须保证页面元素的加载顺序，不会因为页面上未完全加载的元素被用户访问而造成异常。</p>
<p>哪些因素造成网站响应缓慢？</p>
<p>当谈到提高网站响应速度，最通常的做法就是尽可能的减少网站文件的尺寸。(这也导致针对JavaScript库文件大小的无休止的讨论，但最终也没什么结果。）实际上,有许多因素会影响到网页初次访问的响应速度:</p>
<p>    * HTML文档的大小。<br />
    * 页面中嵌入的脚本、图像、多媒体元素文档的大小。<br />
    * HTML页面的复杂程度。(浏览器可以很快的展现简单的页面)<br />
    * 用户的接入速度<br />
    * 会被页面访问的第三方内容所在服务器的访问速度。<br />
    * 网站域名及其页面包含的外部域名的ＤＮＳ解析速度。<br />
    * 用户计算机的性能。(浏览器会因为系统消耗过多的资源在其他任务上而变得响应缓慢)。<br />
    * 服务器的相应速度。</p>
<p>除了以上的技术上的因素会导致网站响应变慢以外，还有一些人为设计上的因素。例如：为了避免页面加载过程中出现的页面区域错乱和无图像显示；页面被设计为需要页面内容完全加载完毕后才一起显示。<br />
让网站响应便快的方法</p>
<p> 经过实践，以下经验对于解决由于技术和人为因素造成网站响应变慢的问题会有所帮助。</p>
<p>    * 在不影响页面显示质量的前提下，尽可能的优化HTML代码。（这包括在发布页面时，去掉HTML文档中的注释以及冗余的换行标记。但为了保证页面的可读性，这些代码还应当保留在源代码中）<br />
    * 页面中尽可能少的包含其他外部引用，减少文档之间的依赖。（可以将多个脚本放入一个脚本文件，用CSS的sprite技巧将多个小图片合并为一个大图，这样就只需要加载一次）<br />
    * 确保你没有从外部服务器上引用第三方的内容：用一个脚本将远程的RSS源缓存在本地。这样不仅可以避免DNS解析所造成的延时，而且也不会因为外部服务器的宕机影响你的服务。<br />
    * 尽可能的制定图片及包含图片的元素的尺寸。这样可以避免页面展现时由于图片陆续加载而造成页面元素跳动的现象。<br />
    * 在页面的末端加载大的脚本，这样页面的可以在大的脚本加载完成前展示出来。如果把大的脚本在页面头元素中加载，则浏览器会等到脚本完全加载完成后才显示页面内容。</p>
<p>web开发准则与提高响应速度</p>
<p>可惜上文提到的这些计巧与我们通常认为的web开发的准则有冲突。例如减少页面包含文件数量会造成产品的可维护性变差。为了使网站的不用页面（首页，文章页，存档页）保持不同的页面风格最简单的方法是不同类型的页面的特殊的样式存放在他们各自的样式文件中。一个页面可以有一个最基本的样式文件，然后根据页面的不同类型再包含该类型页面的指定的样式文件。<br />
 脚本的存放也可以用相同的方法，将功能相近的脚本放到一个文件中。这样有助于代码的维护。你不用察看所有的脚本代码就可以很快的找到你需要的函数。此外，将脚本加入到页面的主体部分通常被认为是不良的编码习惯，因为他将用户的行为控制逻辑嵌入的页面的结构中。</p>
<p>幸好有技术方案可以解决这些问题。</p>
<p>用一个包含来引用多个样式或脚本。</p>
<p> 爱德华艾略特提出的解决方法是用一个PHP的脚本将多个CSS样式或脚本整理成单一的档案。这个脚本对于javascript还可以调用DouglasCrockford’s的JSmin进行压缩。这个脚本使用很简单，而且可以缓存归并后的文件，直到这些被归并的文件被修改。这就意味着当你修改被归并的某个文件后，脚本会自动重新打包缓存。这样就很简单的解决了代码维护和页面响应速度间的矛盾。<br />
解决页面加载的问题</p>
<p> 另一个棘手的问题是，嵌入在页面头元素的脚本，必要要等页面加载完成后才能被调用。这样就会有些延时 ，而且还会产生问题。</p>
<p>延时是由于浏览器加载，解析和展现文档的方式造成的。当你用window的onload事件加载脚本时，浏览器的处理顺序是这样的：</p>
<p>  * 解析HTML代码装载外部脚本和样式表<br />
  * 执行被解析后的脚本<br />
  * 建立HTML的DOM树<br />
  * 装载图片和其它外部引用内容<br />
  * 页面装载完毕</p>
<p> 在大多数情况下这样的加载会比较慢，而有些步骤需要提前。许多聪明的程序员致力于解决这个问题，不时的会有新的解决方案出现。大多数的javascript脚本都会有针对onAvailable或onDocumentReady的事件处理。这类事件会在部分文档装载完成后就会被触发，而不用等到大量图片被加载。但通过实践和反复测试，针对旧的浏览器和操作系统并没有无懈可击的解决方案。但我相信只要我们继续努力，再加上那么点运气一定会找到最终的解决方案的。</p>
<p>对于web应用由于调用未加载完成的元素而导致异常是很致命的问题。如果这类问题时发生在页面美化部分，则会有一些解决方法。</p>
<p>为了解决一次加载过多内容的问题，可以采按需分别加载内容。</p>
<p> 为了更好的装饰页面一次载入大量的内容，往往会产生问题。大量的内容有可能是每个标签中都包含过多的文字或者是一个有四级的导航栏。运用javacript脚本可以很轻松的动态展示这些内容。但是如果脚本被禁用，则这些动态内容就会失去样式而被打乱，无法正确地展示，这当然不是一个好主意。页面也没有必要一次将所有的动态展示内容都一次加载，这样会增加页面载入的负载。</p>
<p> 解决方法是当用户触发标签时再用javascript动态的加载显示的内容。当用户关闭脚本后也会显示一个基本的静态文本。</p>
<p> 用什么方法来加载额外的内容取决于你需要引用的是什么。最简单的方法是动态的生成脚本标签。这是一个很早就有的方法，被用来引入大量的javascript数据集或在页面加载后再引入脚本。</p>
<p><code><br />
function pull(){<br />
var s = document.createElement('script');<br />
s.type = 'text/javascript';<br />
s.src = 'largeJavaScriptBlock.js';<br />
 document.getElementsByTagName('head')[0].appendChild(s);<br />
}<br />
window.onload = pull;<br />
</code></p>
<p>del.icio.us页面就到这种方法来引入由json返回的数据。由于json返回的不过是一堆javascript代码，你可以在页面装载完成后，生成javascript脚本标签包含这些代码；然后执行这些代码原来替换页面中某个元素的内容。Dishy作为封装了json的对象可以让你很轻松的完成这些。另一个列子是不太显眼的Flickr头像，Flickr用json输出显示你最新相片，当用户禁用脚本，哪个位置显示的只是一个链接。</p>
<p>如果你要引入的是非javascript的内容，你可以使用Ajax或者AHAH或者Hijax或者其他不包含xml的ajax（你愿意把称作什么名称都可以）。例如，一个用ajax实现的导航，它甚至可以根据用户需要可选择的加载更为复杂的界面。</p>
<p>Imaging trickery 图像显示技巧<br />
 最后一个方法的渊源会追溯到可能你还没开始接触网站开发时。那时浏览器大战中最为ie的竞争对手苦命的Netscape（但在我看来那时还是不错的）浏览器支持一个自定义的HTML属性‘lowsrc’，这个属性可以指定一个小图片提前加载作为大图载入时的替代显示图片。这样即使用户的接入速度很慢，也可以看到即将呈现图片的一个预览。<br />
 你可以重用这一想法，当页面加载时不要嵌入过大的图片而是载入更为规范化的小图片；等页面加载完成后再用大图片进行替换。你甚至可以简化到开始只载入背景色，然后等页面载入完成再用javascript或者DOM加载原图进行覆盖。<br />
这种方法还适用于你需要从多个服务器取得许多不能被缓存的图片。（例如gravatars）通常可以先载入一个占位的图片，等页面加载完成后再动态取得分散在其他服务器上的小图片。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/54.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>CSS 清除浮动的三种方式</title>
		<link>http://adam.ofeva.com/blog/53.html</link>
		<comments>http://adam.ofeva.com/blog/53.html#comments</comments>
		<pubDate>Tue, 19 Aug 2008 08:39:45 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[xhtml+css]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=53</guid>
		<description><![CDATA[用空标签清除

.clr {clear: both;}
&#60;div id=&#34;layout&#34;&#62;
    &#60;div id=&#34;left&#34;&#62;Left&#60;/div&#62;
    &#60;div id=&#34;right&#34;&#62;Right&#60;/div&#62;
    &#60;p class=&#34;clr&#34;&#62;&#60;/p&#62;
&#60;/div&#62;

使用 overflow 属性

#layout {overflow:auto; zoom:1;}
&#60;div id=&#34;layout&#34;&#62;
    &#60;div id=&#34;left&#34;&#62;Left&#60;/div&#62;
    &#60;div id=&#34;right&#34;&#62;Right&#60;/div&#62;
&#60;/div&#62;

使用 :after （非 IE 浏览器）

#layout:after{
    display: block;
    clear: both; content: &#34;&#34;;
    visibility:hidden; height: [...]]]></description>
			<content:encoded><![CDATA[<p>用空标签清除<br />
<code><br />
.clr {clear: both;}<br />
&lt;div id=&quot;layout&quot;&gt;<br />
    &lt;div id=&quot;left&quot;&gt;Left&lt;/div&gt;<br />
    &lt;div id=&quot;right&quot;&gt;Right&lt;/div&gt;<br />
    &lt;p class=&quot;clr&quot;&gt;&lt;/p&gt;<br />
&lt;/div&gt;<br />
</code><br />
使用 overflow 属性</p>
<p><code><br />
#layout {overflow:auto; zoom:1;}<br />
&lt;div id=&quot;layout&quot;&gt;<br />
    &lt;div id=&quot;left&quot;&gt;Left&lt;/div&gt;<br />
    &lt;div id=&quot;right&quot;&gt;Right&lt;/div&gt;<br />
&lt;/div&gt;<br />
</code><br />
使用 :after （非 IE 浏览器）<br />
<code><br />
#layout:after{<br />
    display: block;<br />
    clear: both; content: &quot;&quot;;<br />
    visibility:hidden; height: 0;<br />
}<br />
&lt;div id=&quot;layout&quot;&gt;<br />
    &lt;div id=&quot;left&quot;&gt;Left&lt;/div&gt;<br />
    &lt;div id=&quot;right&quot;&gt;Right&lt;/div&gt;<br />
&lt;/div&gt;<br />
</code><br />
注：使用 :after 需要注意几点，设置高度为零（height: 0;）；content 是必须的，但其值可以为空。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/53.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>用户是一个绝顶聪明的傻子！</title>
		<link>http://adam.ofeva.com/blog/52.html</link>
		<comments>http://adam.ofeva.com/blog/52.html#comments</comments>
		<pubDate>Tue, 19 Aug 2008 01:06:19 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[UI/UE]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=52</guid>
		<description><![CDATA[在写这篇文章之前，我一直困惑于如何表达自己的思想和如何让看到这篇文章的读者完全理解我要表达的含义？于是写了又删，删了又写，最后是在一次与天下网产品总监李天锋先生进行用户体验交流时获得了灵感（李天锋先生是无线互联网的前辈，有着多年的互联网从业经验和多年的无线职业经历，对无线互联网有独到的理解，并长期对用户体验进行研究；也是我职业生涯的老师；他的设计理念：把用户当成一个绝顶聪明的傻子。）正是他的这句话让我对用户体验进行重新思考和诠释。
我不想从物理学角度对产品结构元素进行用户体验分析，因为那种分析过于技术化，而是从用户能够感受得到的角度进行分析（做用户体验的原则：坚决做用户感受得到，绝不做用户感受不到的——控制成本的有效办法），把用户体验划分为四步（用户体验四步曲）：
第一步视觉体验。视觉体验是用户对界面设计的第一感官体验。它是完全是用户几乎没有经过思考前的一种视觉感受，如何给用户提供一种近于完美的视觉体验，需要考虑到用户看到界面时可能出现的任何一种感受，这就提出UI设计师需要对目标用户偏爱的准确了解和把握，精确传达需要传达的含义，才会获得预期的效果；视觉体验直接影响到用户是否停留在此页面进行一下步的表达理解。注意：任何一种让用户感官视觉不适的界面都可能导致用户产生怨言和流失。
第二步表达体验。表达体验是用户在视觉体验的基础上对界面内容的理解，界面内容可能是文字，也可能是图案，这些内容是引导用户进行操作的“提示或说明”，是需要用户进行理解的内容，如何给用户提供一种简单直白有趣易懂的表达体验，需要产品设计人员考虑到用户对需要理解的内容可能出现的任何一种理解进行预估，消除一些传达出错误信息的内容，因为这些内容都是单向的表达，没有解释和补充的机会来纠正用户瞬间的理解；表达体验直接影响到用户下一步的操作行为是否合理。注意：任何一种让用户产生误解的表达都可能导致用户产生怨言和流失。
第三步操作体验。操作体验是用户通过对表达内容的理解后做出的行为动作的体验过程。功能逻辑是操作体验的直接影响因素，如何优化用户的操作过程是产品设计人员需要思考的核心问题之一，既需要考虑正常的逻辑，又需要考虑非正常的逻辑形式，尽可能考虑到用户可能出现的任何一种行为方式，才能保证用户进行正确的愉悦的操作过程；操作体验直接影响到用户下一步的内容体验。注意：任何一种繁琐和复杂的操作逻辑都可能导致用户产生怨言和流失。
第四步结果体验。结果体验是用户通过操作行为获得的行为结果的一种体验过程。用户的任何一种操作可能出现的任何一个行为结果都直接影响到用户结果体验。如果通过用户的任何行为来预估用户的准确需求是产品设计人员需要思考的核心问题之一，这就要求涉及好每一种用户行为可能出现的任何一种结果，并预测每一种结果是否能够满足用户的需求，如果不能，如何采用其他方式来满足用户的行为需求。注意：任何一种不能满足用户需求的操作结果都可能导致用户产生怨言和流失。
总结：用户是绝顶聪明的天才，因为他可能发现任何一个细微的不足；用户是傻子，因为任何一个微不足道的细节失误都可能导致用户出现挫败感；每一个细节看起来都微不足道，但是每一个细节的综合就会促使整个产品趋于完美，也许用户只是感动于某个细节，但他接受你一定是认同你的全部！
原文：http://column.iresearch.cn/u/yuxuejun/archives/2008/32363.shtml
]]></description>
			<content:encoded><![CDATA[<p>在写这篇文章之前，我一直困惑于如何表达自己的思想和如何让看到这篇文章的读者完全理解我要表达的含义？于是写了又删，删了又写，最后是在一次与天下网产品总监李天锋先生进行用户体验交流时获得了灵感（李天锋先生是无线互联网的前辈，有着多年的互联网从业经验和多年的无线职业经历，对无线互联网有独到的理解，并长期对用户体验进行研究；也是我职业生涯的老师；他的设计理念：把用户当成一个绝顶聪明的傻子。）正是他的这句话让我对用户体验进行重新思考和诠释。</p>
<p>我不想从物理学角度对产品结构元素进行用户体验分析，因为那种分析过于技术化，而是从用户能够感受得到的角度进行分析（做用户体验的原则：坚决做用户感受得到，绝不做用户感受不到的——控制成本的有效办法），把用户体验划分为四步（用户体验四步曲）：</p>
<p><strong>第一步视觉体验</strong>。视觉体验是用户对界面设计的第一感官体验。它是完全是用户几乎没有经过思考前的一种视觉感受，如何给用户提供一种近于完美的视觉体验，需要考虑到用户看到界面时可能出现的任何一种感受，这就提出UI设计师需要对目标用户偏爱的准确了解和把握，精确传达需要传达的含义，才会获得预期的效果；视觉体验直接影响到用户是否停留在此页面进行一下步的表达理解。注意：任何一种让用户感官视觉不适的界面都可能导致用户产生怨言和流失。</p>
<p><strong>第二步表达体验</strong>。表达体验是用户在视觉体验的基础上对界面内容的理解，界面内容可能是文字，也可能是图案，这些内容是引导用户进行操作的“提示或说明”，是需要用户进行理解的内容，如何给用户提供一种简单直白有趣易懂的表达体验，需要产品设计人员考虑到用户对需要理解的内容可能出现的任何一种理解进行预估，消除一些传达出错误信息的内容，因为这些内容都是单向的表达，没有解释和补充的机会来纠正用户瞬间的理解；表达体验直接影响到用户下一步的操作行为是否合理。注意：任何一种让用户产生误解的表达都可能导致用户产生怨言和流失。</p>
<p><strong>第三步操作体验</strong>。操作体验是用户通过对表达内容的理解后做出的行为动作的体验过程。功能逻辑是操作体验的直接影响因素，如何优化用户的操作过程是产品设计人员需要思考的核心问题之一，既需要考虑正常的逻辑，又需要考虑非正常的逻辑形式，尽可能考虑到用户可能出现的任何一种行为方式，才能保证用户进行正确的愉悦的操作过程；操作体验直接影响到用户下一步的内容体验。注意：任何一种繁琐和复杂的操作逻辑都可能导致用户产生怨言和流失。</p>
<p><strong>第四步结果体验</strong>。结果体验是用户通过操作行为获得的行为结果的一种体验过程。用户的任何一种操作可能出现的任何一个行为结果都直接影响到用户结果体验。如果通过用户的任何行为来预估用户的准确需求是产品设计人员需要思考的核心问题之一，这就要求涉及好每一种用户行为可能出现的任何一种结果，并预测每一种结果是否能够满足用户的需求，如果不能，如何采用其他方式来满足用户的行为需求。注意：任何一种不能满足用户需求的操作结果都可能导致用户产生怨言和流失。</p>
<p>总结：用户是绝顶聪明的天才，因为他可能发现任何一个细微的不足；用户是傻子，因为任何一个微不足道的细节失误都可能导致用户出现挫败感；每一个细节看起来都微不足道，但是每一个细节的综合就会促使整个产品趋于完美，也许用户只是感动于某个细节，但他接受你一定是认同你的全部！</p>
<p>原文：http://column.iresearch.cn/u/yuxuejun/archives/2008/32363.shtml</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/52.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>段正淳的css笔记</title>
		<link>http://adam.ofeva.com/blog/51.html</link>
		<comments>http://adam.ofeva.com/blog/51.html#comments</comments>
		<pubDate>Mon, 18 Aug 2008 15:35:48 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[xhtml+css]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=51</guid>
		<description><![CDATA[试想过总结出这几年来写css与xhtml的经验 ，汇总成一片”旷世奇文”分享给大家。无奈寡人年世已高，真是有点力不从心了。于是转念一想，可以用笔记的形式展现，这样就不用担心写不出来了。
现在就来说个淘宝首页上的一个小技巧。
类目之间的横竖线

从很久很久以前开始，类目间的竖线无非都只有三种。

背景图在a标签设置一个padding 用宽1px高不等的背景图来position到右侧。缺点：最后一个还是要用class来隐藏掉背景。
符号在每个a标签之间用”&#124;”符号来填充。缺点：html文件变大，文件维护变得很麻烦，而且在html中毫无意义。
a标签右侧的boder。同背景图一样，只不过使用border-right来代替。缺点也同上。

看到这里，可能已经有人打开淘宝首页用firebug查看源码来看是怎么做了。
其实现有是利用ul的overflow:hidden 再将li的margin-left:-1px的做法做出来的。这样的做法就可以同时避免以上的缺点了。为什么之前都没有那么做的，寡人也不知道了。难道寡人是第一个发现这样的做法？不管是谁先此之前利用了这样的方法实现类目间竖线。不过在淘宝首页上线后不久就有同行的网站在首页改版中也用了这样的方法。那个网站不看也罢。class实在是写的有点多。加载html会变得多得多。反正一个首页需要加载1.17m的网页我的大脑会自动屏蔽。
圆角的做法.
为了这个圆角,前段开发们付出的努力是在是太多了.又要考虑http连接数,又要考虑css与html的代码量与语义.贴出的是最近考虑替换现有圆角做法的方案,可能还有许多未考虑的状况.但是大体的编写方式便是如下.好处是便于维护,只有一个图片.还可以某种程度上的任意缩放.缺点是多了无意义的html代码.

css：.c,.c i,.c i i,.c b,.c b b,.c p{background-image:url(http://pics.taobao.com/bao/album/promotion/uiblog/purple.png);/*背景图片*/background-repeat:no-repeat;}.c{width:200px;/*临时定的宽度*/background-position:0 -4px;}.c i{display:block;height:4px;}.c i i{margin:0 0 0 4px;background-position:right 0;}.c b{display:block;height:4px;background-position:0 bottom;}.c b b{margin:0 0 0 4px;background-position:right bottom;}.c p{margin:0 0 0 4px;padding:0 4px 0 0;background-position:right -4px;}
html：&#60; div class=&#8221;c&#8221;&#62;&#60; i&#62;&#60; i&#62;&#60; /i&#62;&#60; /i&#62;&#60; p&#62;按钮按钮按钮按钮按钮按钮按按按按按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮&#60; /p&#62;&#60; b&#62;&#60; b&#62;&#60; /b&#62;&#60; /b&#62;&#60; /div&#62;
table的全局定义

caption这个标签在firefox下会有左边有1px空隙的bug,很讨厌.能想到的简单的方法只有-1px的margin了.
css：table{border-collapse:collapse;}table caption,table td,table th{border:1px solid #a2bbdd;/*边框颜色*/background:#c3d9ff;/*背景颜色*/}table caption{text-align:left;border-bottom:none;margin-left:-1px;}
html：&#60; table&#62;&#60; [...]]]></description>
			<content:encoded><![CDATA[<p>试想过总结出这几年来写css与xhtml的经验 ，汇总成一片”旷世奇文”分享给大家。无奈寡人年世已高，真是有点力不从心了。于是转念一想，可以用笔记的形式展现，这样就不用担心写不出来了。</p>
<p>现在就来说个淘宝首页上的一个小技巧。</p>
<p><strong>类目之间的横竖线</strong></p>
<p align="center"><img src="http://www.blueidea.com/articleimg/2007/10/5008/01.jpg" border="0" width="300" height="150"></p>
<p>从很久很久以前开始，类目间的竖线无非都只有三种。</p>
<ol>
<li>背景图<br />在a标签设置一个padding 用宽1px高不等的背景图来position到右侧。<br />缺点：最后一个还是要用class来隐藏掉背景。</li>
<li>符号<br />在每个a标签之间用”|”符号来填充。<br />缺点：html文件变大，文件维护变得很麻烦，而且在html中毫无意义。</li>
<li>a标签右侧的boder。<br />同背景图一样，只不过使用border-right来代替。缺点也同上。</li>
</ol>
<p>看到这里，可能已经有人打开淘宝首页用firebug查看源码来看是怎么做了。</p>
<p>其实现有是利用ul的overflow:hidden 再将li的margin-left:-1px的做法做出来的。这样的做法就可以同时避免以上的缺点了。<br />为什么之前都没有那么做的，寡人也不知道了。难道寡人是第一个发现这样的做法？<br />不管是谁先此之前利用了这样的方法实现类目间竖线。<br />不过在淘宝首页上线后不久就有同行的网站在首页改版中也用了这样的方法。<br />那个网站不看也罢。class实在是写的有点多。加载html会变得多得多。<br />反正一个首页需要加载1.17m的网页我的大脑会自动屏蔽。</p>
<p><strong>圆角的做法.</strong></p>
<p>为了这个圆角,前段开发们付出的努力是在是太多了.又要考虑http连接数,又要考虑css与html的代码量与语义.<br />贴出的是最近考虑替换现有圆角做法的方案,可能还有许多未考虑的状况.但是大体的编写方式便是如下.<br />好处是便于维护,只有一个图片.还可以某种程度上的任意缩放.缺点是多了无意义的html代码.</p>
<p><code>
<p>css：<br /><span class="code">.c,.c i,.c i i,.c b,.c b b,.c p{<br />background-image:url(http://pics.taobao.com/bao/album/promotion/uiblog/purple.png);/*背景图片*/<br />background-repeat:no-repeat;<br />}<br />.c{<br />width:200px;/*临时定的宽度*/<br />background-position:0 -4px;<br />}<br />.c i{<br />display:block;<br />height:4px;<br />}<br />.c i i{<br />margin:0 0 0 4px;<br />background-position:right 0;<br />}<br />.c b{<br />display:block;<br />height:4px;<br />background-position:0 bottom;<br />}<br />.c b b{<br />margin:0 0 0 4px;<br />background-position:right bottom;<br />}<br />.c p{<br />margin:0 0 0 4px;<br />padding:0 4px 0 0;<br />background-position:right -4px;<br />}</span></p>
<p>html：<br /><span class="code">&lt; div class=&#8221;c&#8221;&gt;<br />&lt; i&gt;&lt; i&gt;&lt; /i&gt;&lt; /i&gt;<br />&lt; p&gt;<br />按钮按钮按钮按钮按钮按钮<br />按按按按按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮按钮<br />&lt; /p&gt;<br />&lt; b&gt;&lt; b&gt;&lt; /b&gt;&lt; /b&gt;<br />&lt; /div&gt;</span></p>
<p><strong>table的全局定义</strong></p>
<p></code></p>
<p>caption这个标签在firefox下会有左边有1px空隙的bug,很讨厌.能想到的简单的方法只有-1px的margin了.</p>
<p>css：<br /><span class="code">table{<br />border-collapse:collapse;<br />}<br />table caption,table td,table th{<br />border:1px solid #a2bbdd;/*边框颜色*/<br />background:#c3d9ff;/*背景颜色*/<br />}<br />table caption{<br />text-align:left;<br />border-bottom:none;<br />margin-left:-1px;<br />}</span></p>
<p>html：<br /><span class="code">&lt; table&gt;<br />&lt; caption&gt;表格标题&lt; /caption&gt;<br />&lt; tr&gt;<br />&lt; th&gt;标题&lt; /th&gt;<br />&lt; th&gt;标题&lt; /th&gt;<br />&lt; th&gt;标题&lt; /th&gt;<br />&lt; th&gt;标题&lt; /th&gt;<br />&lt; /tr&gt;<br />&lt; tr&gt;<br />&lt; td&gt; 内容&lt; /td&gt;<br />&lt; td&gt; 内容&lt; /td&gt;<br />&lt; td&gt; 内容&lt; /td&gt;<br />&lt; td&gt; 内容&lt; /td&gt;<br />&lt; /tr&gt;<br />&lt; /table&gt;</span></p>
<p><strong>需要正视的二个标签</strong></p>
<ol>
<li>acronym这个标签用来解释名词很爽,但是用得太少.(我也一直想用来着,所以记下了.) <br />css：<br /><span class="code" style="width: 442px;height: 30px">acronym{cursor:help}</span><br />html：<br /><span class="code" style="width: 441px;height: 84px">&lt; acronym title=&#8221;段正淳又是金庸笔下一个十分奇特的人物。他奇特在到处留情，情人极多，见一个爱一个，而又绝不是徒然风流薄幸，当他是单独对着一个情人的时候，他真是真心真意爱这个情人的，只好说这个人的感情特别丰富，别无其他解释。&#8221; &gt;文字&lt; /acronym&gt;</span></li>
<li>ins这个标签忘记是在哪个网站上看到过用来在h2里显示更多的链接,后来查了书,大家都觉得有点欠妥,有点争议.<br />css：<br />还未写入css组件…欠奉上了<br />html：<br />
<code><br />
<h2>标题<ins><a>更多&gt;&gt;</a></ins></h2>
<p></code></p>
<p><strong>标题右侧“更多”的实现</strong></p>
<p align="center"><img src="/articleimg/2007/10/5008/02.gif" border="0" width="236" height="100"></p>
<p align="left">曾经做上图所示的效果,会使用到position来相对定位到h2标签的右侧.这样的做法,代码确实会多好几行. 其实可以用个笨一点的办法来实现的：</p>
<p>譬如html代码如下：</p>
<p><span class="code">&lt; h2&gt;&lt; a h ref=&#8221;#&#8221; &gt;标题&lt; /a&gt; &lt; span&gt;更多…&lt; /span&gt; &lt; /h2&gt;</span></p>
<p>使用potsition的css差不多如下：</p>
<p><span class="code">h2{<br />position:relative;<br />height:20px;<br />}<br />span{<br />position:absolute;<br />right:0;<br />top:0;<br />display:block;<br />height:20px;<br />}</span></p>
<p>这样才能实现更多在右侧.其实真的还可以更简单:</p>
<p><code>
<p><span class="code">h2{<br />height:20px;<br />}<br />span{<br />float:right;<br />display:block;<br />margin:-10px 0 0 0;<br />height:20px;<br />}</span></p>
<p></code></p>
<p>其实只是利用了margin-top 的负数来实现,因为默认的float会换行到h2标签下面去，所以让它自个跳上去。大致代码就是如此了,是不是很简单?我说很简单嘛！由于很简单,所以就不放出单独的测试页面了.</p>
<p>ps:我说咱们啥时候也得搞个和蓝色理想一样的编辑器吧…</p>
<p><strong>淘宝的css属性顺序书写规范</strong></p>
<p>以前部门的同事们，每个人都有一套书写的规范，导致看对方的css代码非常吃力，所以就推行了一套书写标准 ，或许对您也有帮助。</p>
<p><code>*{<br />
/*显示属性*/<br />
display<br />
position<br />
float<br />
clear<br />
cursor<br />
/*盒模型*/<br />
margin<br />
padding<br />
width<br />
height<br />
/*排版*/<br />
vertical-align<br />
white-space<br />
text-decoration<br />
text-align</p>
<p>/*文字*/<br />
color<br />
font<br />
content</p>
<p>/*边框背景 为什么要把 boder和background放在最后的原因是修改的频率会较之前的频繁，放在最后查看起来方便，哈哈。*/<br />
border<br />
background<br />
}</code></p>
<p>说到底其实属性的书写顺序规范就是：神仙?妖怪? - 身材怎么样！- 服装类型(比基尼?棉袄?) - 服装款式(黑色?白色?纽扣?拉链?) - 用了啥化妆品和发型.<br />这个书写标准小部分并不是浏览器厂商推行的书写规范，所以可能被广大标准推广者所不认同 。但这些个都是弟兄几个实践出来认为最符合现有淘宝环境的。</p>
<p><strong>css代码的简写</strong></p>
<p>css缩写的语法，对新手有一定帮助,老鸟就不用看了.</p>
<ol>
<li>0px不需要单位，直接:margin:0</li>
<li>盒模型的缩写，语法是margin:上 右 下 左;.甚至可以简写成margin:上 (右左) 下,当然右左的值应该是一样的</li>
<li>css属性的最后一项”;”号省略。（不建议 ^_^）</li>
<li>字体宽度normal用400代替,bold用700代替。</li>
<li>16进制的色彩值，如果每两位的值相同，可以缩写一半，例如：#000000可以缩写为#000;#0044DD可以缩写为#04D;</li>
<li>border边框的缩写，语法是border:width style color,类似boder:1px solid red;</li>
<li>背景background的缩写,语法是color image repeat attachment position.类似:background:#f00 url(background.gif) no-repeat fixed 0 0( 为什么我从不写fixed呢?)</li>
<li>字体的缩写,类似font:italic small-caps bold 1em/140% “SimSun”,sans-serif,可以省略到最简单font:12px “SimSun”.</li>
<li>list的属性缩写,语法list-style:square inside url(image.gif) ,不过一般咱们都不用.</li>
<li>想凑10条, 还真难.就把删除无用换行符和空格算一个吧</li>
</ol>
<p>一天大家在团队中讨论“未知图片垂直居中”的问题，突发奇想用vertical-align:middle这个属性来实现，于是抽了时间做了下面这个不成熟的例子：</p>
<p><code>
<p>CSS:</p>
<p><span class="code">&nbsp;div{<br />&nbsp; width:140px;<br />&nbsp; height:140px;<br />&nbsp; text-indent:-8px;<br />&nbsp; text-align:center;<br />&nbsp; line-height:138px;<br />&nbsp; background:red;<br />&nbsp; font-size:12px;<br />&nbsp; *font-size:120px;<br />&nbsp; *text-indent:-60px;<br />}<br />img{<br />&nbsp; width:100px;<br />&nbsp; height:100px;<br />&nbsp; vertical-align:middle;<br />} </span></p>
<p>HTML:</p>
<p><span class="code">&lt; div&gt;&amp; nbsp;&lt;img src=&#8221;ipodclassics.jpg&#8221; alt=&#8221;iPod classic&#8221; /&gt;</span></p>
<p></code></p>
<p>初衷是不想用position来做,毕竟 大量的图片显示浏览器在渲染的时候会消耗 较多的资源。</p>
<p>缺点是 输出了 无意义的nbsp;, 而且font-size和font-indentd的计算公式不是很简单(所以以上的数字都是凑的^_^).</p>
<p>后来小马见了这个思路，用了点时间升级了代码,用:after输出代替了无趣nbsp ,代码见下。</p>
<p><code>
<p>CSS:</p>
<p><span class="code">&nbsp;.tb-p-c{<br />&nbsp; display: block;<br />&nbsp; width:140px;<br />&nbsp; height:140px;<br />&nbsp; line-height:140px;<br />&nbsp; text-align:center;<br />&nbsp; *font-size:123px;<br />}<br />.tb-p-c img{<br />&nbsp; vertical-align:middle;<br />}<br />.tb-p-c:after {<br />&nbsp; content: &#8220;.&#8221;;<br />&nbsp; visibility: hidden;<br />&nbsp; font-size: 12px;<br />&nbsp; margin-left: -5px;<br />} </span></p>
<p>HTML:</p>
<p><span class="code">&lt;a class=&#8221;tb-p-c&#8221;&gt;&lt;img src=&#8221;jishi070912_2.jpg&#8221; /&gt;&lt;/a&gt; </span></p>
<p></code></p>
<p>这样子，恼人的nbsp消失了。大家对vertical-align:middle的渲染方式有了更进一步的了解了。还让很多同志发现了after这个伪类还可以用来hack.</p>
<p>结果圆心又给CSS升了次级：</p>
<p><code>
<p>CSS:</p>
<p><span class="code">&nbsp;.tb-p-c{<br />&nbsp; display: table-cell;<br />&nbsp; vertical-align:middle;<br />&nbsp; width:140px;<br />&nbsp; height:140px;<br />&nbsp; text-align:center;<br />&nbsp; *display: block;<br />&nbsp; *font-size: 122px;<br />&nbsp; background:red;<br />}<br />.tb-p-c img {<br />&nbsp; vertical-align:middle;<br />} </span></p>
<p></code></p>
<p>这是第三次的升级，由于时间关系，没有测试上面的代码，原因是利用了display来渲染，感觉上还是会让浏览器多次渲染，所以偶没测试 。<br />这次探讨给了我们很多很多的收获，相信如果有大家的参与，会有更多方式和我们没发现的观点。大伙别小气，多发表回复，一起提高。</p>
]]></content:encoded>
			<wfw:commentRss>http://adam.ofeva.com/blog/51.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Web标准的web UI</title>
		<link>http://adam.ofeva.com/blog/50.html</link>
		<comments>http://adam.ofeva.com/blog/50.html#comments</comments>
		<pubDate>Mon, 18 Aug 2008 15:26:27 +0000</pubDate>
		<dc:creator>阿当</dc:creator>
		
		<category><![CDATA[UI/UE]]></category>

		<category><![CDATA[xhtml+css]]></category>

		<guid isPermaLink="false">http://adam.ofeva.com/?p=50</guid>
		<description><![CDATA[Web标准的web UI——来源、谬误与个人理解
序
我从2004年末开始接触web标准，2005年5月正式采取完全的web标准方式的网页制作，2005年8月，第一个符合web标准的网站UI开发工作完成。直至今日，经历了无数的艰辛，也有过许多的困惑。所幸，我的瑞典籍的Project Leader是一个很有经验的人，他告诉了我很多关于web标准国内并不了解的东西，我这几年技术方面的成长离不开他的支持和引导，感谢Andreas Liljefilt！在这里，我把它们告诉大家，也希望能有更多的人来讨论。
Chaper 1 什么是web标准？Div+css的谬误。
提到web标准，就不得不先说一说国内业界非常流行的一个词——Div+css。这个词在国内简直是一个潮流，不仅互联网上一直在提，大量的教程中使用这个词，就连一些出版的书籍也是用了这个概念。然而，甚少人知道的是，这个概念本身是错误的。有好事的朋友不妨去google搜索一下（先调整到英文界面，这样可以强制让它搜索google.com而不是google.cn），&#8221;div+css&#8221;这样一个关键字是根本找不到任何一个英文网页，全部都是中文的。没错，其实所谓的div+css就是一个中国特有的理解和概念。我甚至不知道这个词是谁先提出来的，然而，它对web标准中xhtml/css的网页构建方法的理解几乎是完全错误的。
回归正题，web标准究竟是什么？Web标准是w3c组织规定的各种web上所使用的语言的标准和规范的集合。
我们目前究竟接触到了web标准的多少？打开 w3c的官方网站，我们在左侧可以看到如下列表：

# Accessibility
# Amaya
# CC/PP
# Compound Document Formats
(CDF)
# CSS
# CSS
Validator
# Databinding
# DOM
# Efficient XML
Interchange
# eGovernment
# GRDDL
# Health Care and Life
Sciences
# HTML
# HTML Tidy
# HTML Validator
# HTTP
# Incubator
# InkML
# Internationalization
# Jigsaw
# Libwww
# MathML
# Mobile Web Initiative
(W3C-MWI)
# Multimodal
Interaction
# OWL
# Patent Policy
# PICS
# PNG
# POWDER
# Privacy and P3P
# RDF
# Rich Web Clients
# Rules
# [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Web标准的web UI——来源、谬误与个人理解</strong></p>
<p><strong>序</strong></p>
<p>我从2004年末开始接触web标准，2005年5月正式采取完全的web标准方式的网页制作，2005年8月，第一个符合web标准的网站UI开发工作完成。直至今日，经历了无数的艰辛，也有过许多的困惑。所幸，我的瑞典籍的Project Leader是一个很有经验的人，他告诉了我很多关于web标准国内并不了解的东西，我这几年技术方面的成长离不开他的支持和引导，感谢Andreas Liljefilt！在这里，我把它们告诉大家，也希望能有更多的人来讨论。</p>
<p><strong>Chaper 1 什么是web标准？Div+css的谬误。</strong></p>
<p>提到web标准，就不得不先说一说国内业界非常流行的一个词——Div+css。这个词在国内简直是一个潮流，不仅互联网上一直在提，大量的教程中使用这个词，就连一些出版的书籍也是用了这个概念。然而，甚少人知道的是，这个概念本身是错误的。有好事的朋友不妨去google搜索一下（先调整到英文界面，这样可以强制让它搜索google.com而不是google.cn），&#8221;div+css&#8221;这样一个关键字是根本找不到任何一个英文网页，全部都是中文的。没错，其实所谓的div+css就是一个中国特有的理解和概念。我甚至不知道这个词是谁先提出来的，然而，它对web标准中xhtml/css的网页构建方法的理解几乎是完全错误的。</p>
<p>回归正题，web标准究竟是什么？Web标准是w3c组织规定的各种web上所使用的语言的标准和规范的集合。</p>
<p>我们目前究竟接触到了web标准的多少？打开 w3c的官方网站，我们在左侧可以看到如下列表：</p>
<p><code><br />
# Accessibility<br />
# Amaya<br />
# CC/PP<br />
# Compound Document Formats<br />
(CDF)<br />
# CSS<br />
# CSS<br />
Validator<br />
# Databinding<br />
# DOM<br />
# Efficient XML<br />
Interchange<br />
# eGovernment<br />
# GRDDL<br />
# Health Care and Life<br />
Sciences<br />
# HTML<br />
# HTML Tidy<br />
# HTML Validator<br />
# HTTP<br />
# Incubator<br />
# InkML<br />
# Internationalization<br />
# Jigsaw<br />
# Libwww<br />
# MathML<br />
# Mobile Web Initiative<br />
(W3C-MWI)<br />
# Multimodal<br />
Interaction<br />
# OWL<br />
# Patent Policy<br />
# PICS<br />
# PNG<br />
# POWDER<br />
# Privacy and P3P<br />
# RDF<br />
# Rich Web Clients<br />
# Rules<br />
# Security<br />
# Semantic Web<br />
# Service Modeling Language<br />
(SML)<br />
# SMIL<br />
# SOAP/XMLP<br />
# SPARQL<br />
# Style<br />
# SVG<br />
# Timed Text<br />
# URI/URL<br />
# Validators<br />
# Voice<br />
# Ubiquitous Web<br />
Applications<br />
# WAI<br />
# Web API<br />
# Web Application<br />
Formats<br />
# Web Architecture<br />
(TAG)<br />
# WebCGM<br />
# Web Services<br />
# WS-Addressing<br />
# WS-CDL<br />
# WSDL<br />
# WS-Policy<br />
# XForms<br />
# XHTML<br />
# XHTML2<br />
# XLink<br />
# XML<br />
# XML Base<br />
# XML Encryption<br />
# XML Key Management<br />
# XML Processing<br />
# XML Query<br />
# XML Schema<br />
# XML Signature<br />
# XPath<br />
# XPointer<br />
# XSL and XSLT<br />
</code></p>
<p>全看下来后是不是觉得很晕？没错，这个就是web标准目前的全部技术规范。web标准包含了这么多的内容，而我们目前所说的div+css只是其中xhtml/css实现方式的不完整的一部分而已。</p>
<p><strong>* 为什么是xhtml/css？</strong></p>
<p>其他的部分，我不想说的太多，第一是因为我也没办法全都弄懂，第二是其中有一大半浏览器支持不完全甚至根本就不支持。XML是web标准中对网页实现的最终目标。也就是web页面数据化和语义化，然而由于浏览器的支持不完善和兼容问题，目前优秀、兼容性强的纯xml网站只是停留在幻想里而已。因此，现在主流的网页实现方式就是xhtml/css。首先，xhtml与html大部分兼容，并且可以让目前大多数的浏览器直接阅读。css主流的几大浏览器也支持的非常完善。再加上ECMAScript(不说Javascript的原因是Javascript的概念中包含了很多与标准不同的浏览器私有定义)，已经足够实现web UI布局的大部分需要了。</p>
<p align="left"><strong>Chapter 2 web标准真的是要完全不用表格？</strong></p>
<p>好像是在2005年的时候，一篇叫做《把表格从你的网页中扔出去》（找不到文章的链接了，但确实有这篇文章）的在线文章，似乎给了人们一个错觉，要符合标准，那么表格在网页中就完全不能使用了。必须用div来代替。也许div+css这个概念就是这样被想当然的创造出来的（源自表格布局）。但事实上，web标准并不是完全不允许使用表格。而是要求摒弃使用表格来布局的做法。同时，也不再使用布局这个概念。而是提倡结构与表现分离。这时，就有一些人会产生一个疑惑，如果说xhtml代表结构，css用来控制表现，那么，布局该如何解决？相信现在接触web标准的朋友不会再有这个疑惑了吧？结构和表现结合起来就形成了布局。既然不能用表格来做布局了，那么表格还有什么用呢？似乎很多人忘了表格在html中的原始定义——展现结构化数据表格。举个例子，某学校班级的期中考试成绩表，这种数据，就是一个非常明显的表格。web标准中绝对没有要求你用div来模拟表格，那是非常蠢的做法。这几天在经典论坛上还看到有人产生这样的疑惑，表格形式的格式化数据，用表格比用div要方便的多，他们搞不懂为什么一定要用div来表现表格，现在我告诉你答案了，该用表格展现数据的时候就要用表格。</p>
<p><strong>Chapter 3 为什么要用web标准？怎么样才算是符合web标准？</strong></p>
<p>很多人会说例如兼容性好、代码易懂、代码量小、结构合理、甚至有人说使用标准可以实现比表格更丰富的样式等各种理由来支持web标准，而web标准也的确具有这些优点，然而，这些却并非web标准真正要做的。</p>
<p>并非把表格换成div就是符合web标准了。也并非使用xhtml和css就是符合web标准。甚至就算你的代码能够通过w3c的验证，也很难说它就完全符合web标准。事实上，web标准的最终目标不是为了让人容易看懂网页如果仅仅是为了让人容易看懂，那么表格布局已经足够了。它的最终目标是为了让计算机能够读懂网页。看下面几个例子：</p>
<p><strong>表格布局的一段代码：</strong></p>
<p><span class="code">&lt;table width=&#8221;50%&#8221;&gt;<br />&lt;tr&gt;<br />&lt;td width=&#8221;30%&#8221;&gt;&lt;/td&gt;<br />&lt;td width=&#8221;30%&#8221;&gt;&lt;font size=&#8221;3&#8243;&gt;web&lt;/font&gt;标准的概念&lt;/td&gt;<br />&lt;td width=&#8221;40%&#8221;&gt;如何实现&lt;b&gt;标准化制作&lt;/b&gt;&lt;/td&gt;<br />&lt;/tr&gt;<br />&lt;tr&gt;<br />&lt;td colspan=&#8221;3&#8243;&gt;&lt;font color=&#8221;red&#8221;&gt;&lt;font size=&#8221;3&#8243;&gt;web&lt;/font&gt;标准在网页中的使用&lt;/font&gt;&lt;/td&gt;<br />&lt;/table&gt;</span></p>
<p><strong>web标准（XHTML/CSS）实现的一段代码：</strong></p>
<p><span class="code">&lt;h3&gt;&lt;span&gt;web&lt;/span&gt;标准的概念&lt;/h3&gt;<br />&lt;h3&gt;如何实现&lt;em&gt;标准化制作&lt;/em&gt;&lt;/h3&gt;<br />&lt;h3 class=&#8221;important&#8221;&gt;&lt;span&gt;web&lt;/span&gt;标准在网页中的使用&lt;/td&gt;</span></p>
<p><strong>web标准(XML)实现的另一段代码：</strong></p>
<p><span class="code">&lt;articles&gt;<br />&nbsp;&nbsp;&nbsp; &lt;articletitle&gt;web标准的概念&lt;/articletitle&gt;<br />&nbsp;&nbsp;&nbsp; &lt;articletitle em=&#8221;4&#8243; emlegth=&#8221;3&#8243;&gt;如何实现标准化制作&lt;/articletitle&gt;<br />&nbsp;&nbsp;&nbsp; &lt;articletitle level=&#8221;important&#8221;&gt;web标准在网页中的使用&lt;/articletitle&gt;<br />&lt;articles&gt;</span></p>
<p>看过以上几段代码后，我们先来分析一下。第一段是表格布局的代码，它把整块分成了两行，第一行用了三列，第一列是空的用于缩进，后面两列分别放了两篇文章的标题。其中的英文文字采用了不同于中文的字号。第二篇文章的标题上还有一部分是加粗强调的。第二行则是一篇文章的标题占用了整行，并且以红色显示文章标题。在页面展现出来之后，我们能够明白下面的信息：第一篇文章是普通文章，第二篇文章中有一个概念是很重要的。而第三篇文章则非常重要。然而，在代码中我们却很难看出这一点。因为没有人说过加粗就一定是强调。也没有人告诉我们红色就一定表