<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Der&#039;s Blog</title>
	<atom:link href="http://www.ueder.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ueder.net</link>
	<description>学无止境－专注于html、css、js等前端技术</description>
	<lastBuildDate>Wed, 22 Feb 2012 03:46:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>javascript模版引擎-tmpl 的精简及bug修正</title>
		<link>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/</link>
		<comments>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 11:50:29 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=760</guid>
		<description><![CDATA[在基于MVC框架开发的web app中，js模板引擎显得特别重要，只需一个模板文本加一段json数据，mix一下，内容就出来了，以往都是用mustache.js， 这里记录一下项目同事介绍一个超精简的模板引擎-tmpl ，对对于mustache.js的单独的模板语法，这个引擎亲切许多，因为可以直接使用js原生的语法，像for switch if，之类。原作为jquery的作者John Resig 开发，详细博客地址, 另有国内某牛人性能改进版，详细见 博文 ，但使用之后，发现还是有点问题，先贴下完整代码： /** * 微型模板引擎 tmpl 0.2 * 0.2 更新: * 1. 修复转义字符与id判断的BUG * 2. 放弃低效的 with 语句从而最高提升3.5倍的执行效率 * 3. 使用随机内部变量防止与模板变量产生冲突 * @example * 方式一：在页面嵌入模板 * &#60;scriptt type="text/tmpl" id="tmpl-demo"&#62; * &#60;ol &#8230; <a href="http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在基于MVC框架开发的web app中，js模板引擎显得特别重要，只需一个模板文本加一段json数据，mix一下，内容就出来了，以往都是用mustache.js， 这里记录一下项目同事介绍一个超精简的模板引擎-tmpl ，对对于mustache.js的单独的模板语法，这个引擎亲切许多，因为可以直接使用js原生的语法，像for switch if，之类。原作为jquery的作者John Resig  开发，<a href="http://ejohn.org/blog/javascript-micro-templating/"  target="_blank">详细博客地址</a>, 另有国内某牛人性能改进版，详细见<a href="http://www.planeart.cn/?p=1594" target="_blank"> 博文 </a>，但使用之后，发现还是有点问题，先贴下完整代码：</p>
<pre class="prettyprint">
/**
 * 微型模板引擎 tmpl 0.2
 * 0.2 更新:
 * 1. 修复转义字符与id判断的BUG
 * 2. 放弃低效的 with 语句从而最高提升3.5倍的执行效率
 * 3. 使用随机内部变量防止与模板变量产生冲突
 * @example
 * 方式一：在页面嵌入模板
 * &lt;scriptt type="text/tmpl" id="tmpl-demo"&gt;
 * &lt;ol title="&lt;%=name%&gt;"&gt;
 *  &lt;% for (var i = 0, l = list.length; i &lt; length; i ++) { %&gt;
 *      &lt;li&gt;&lt;%=list[i]%&gt;&lt;/li&gt;
 *  &lt;% } %&gt;
 * &lt;/ol&gt;
 * &lt;/scriptt&gt;
 * tmpl('tmpl-demo', {name: 'demo data', list: [202, 96, 133, 134]})
 *
 * 方式二：直接传入模板：
 * var demoTmpl =
 * '&lt;ol title="&lt;%=name%&gt;"&gt;'
 * + '&lt;% for (var i = 0, l = list.length; i &lt; length; i ++) { %&gt;'
 * +    '&lt;li&gt;&lt;%=list[i]%&gt;&lt;/li&gt;'
 * + '&lt;% } %&gt;'
 * +'&lt;/ol&gt;';
 * var render = tmpl(demoTmpl);
 * render({name: 'demo data', list: [202, 96, 133, 134]});
 *
 * 这两种方式区别在于第一个会自动缓存编译好的模板，
 * 而第二种缓存交给外部对象控制，如例二中的 render 变量。
 * @blog http://www.planeart.cn/?p=1594
 * @see		http://ejohn.org/blog/javascript-micro-templating/
 * @param	{String}	模板内容或者装有模板内容的元素ID
 * @param	{Object}	附加的数据
 * @return	{String}	解析好的模板
 */
var tmpl = (function (cache, $) {
return function (str, data) {
	var fn = !/W/.test(str)
	? cache[str] = cache[str]
		|| tmpl(document.getElementById(str).innerHTML)

	: function (data) {
		var i, variable = [$], value = [[]];
		for (i in data) {
			variable.push(i);
			value.push(data[i]);
		};
		return (new Function(variable, fn.$))
		.apply(data, value).join("");
	};

	fn.$ = fn.$ || $ + ".push('"
	+ str.replace(/\/g, "\\")
		 .replace(/[rtn]/g, " ")
		 .split("&lt;%").join("t")
		 .replace(/((^|%&gt;)[^t]*)'/g, "$1r")
		 .replace(/t=(.*?)%&gt;/g, "',$1,'")
		 .split("t").join("');")
		 .split("%&gt;").join($ + ".push('")
		 .split("r").join("\'")
	+ "');return " + $;

	return data ? fn(data) : fn;
}})({}, '$' + (+ new Date));
</pre>
<p>此代码预设了两种模板使用环境，一种是用script标签，另一种直接传入string，是由代码的这个部分：</p>
<pre class="prettyprint">
var fn = !/W/.test(str)
</pre>
<p>来判断是script标签还是直接string的，\W是代表非单词字符，这种判断预设了用户的script 的 id 一定为单词字符，如果是连字符&#8221;-&#8221;即会被当成string，出现错误，不是特别完美，<br />
暂时也没找到什么好的判断方式，况且通常应用场都是用string, 索性直接去掉script的判断，只支持string的模板，如果硬要script，可以自行获取 script的innerHTML然后再以string的方式传给tmpl函数，另外模板里的语法是通过<%%>包裹的，容易与其他后端语言的模板冲突，故改成<##>.<br />
以下是修正后的完整代码：</p>
<pre class="prettyprint">
/**
 * 微型模板引擎 tmpl
 * 方式：直接传入模板：(可以随心所欲的使用js原生语法)
 * var demoTmpl =
 * '&lt;ol title="&lt;%=name%&gt;"&gt;'
 * + '&lt;% for (var i = 0, l = list.length; i &lt; length; i ++) { %&gt;'
 * +    '&lt;li&gt;&lt;%=list[i]%&gt;&lt;/li&gt;'
 * + '&lt;% } %&gt;'
 * +'&lt;/ol&gt;';
 * var render = tmpl(demoTmpl);
 * render({name: 'demo data', list: [202, 96, 133, 134]});
 *
 * 缓存交给外部对象控制，如例二中的 render 变量。
 * @blog http://www.planeart.cn/?p=1594
 * @see		http://ejohn.org/blog/javascript-micro-templating/
 * @param	{String}	模板内容或者装有模板内容的元素ID
 * @param	{Object}	附加的数据
 * @return	{String}	解析好的模板
 */
var tmpl = (function (cache, $) {
return function (str, data) {
	var fn = function (data) {
		var i, variable = [$], value = [[]];
		for (i in data) {
			variable.push(i);
			value.push(data[i]);
		};
		return (new Function(variable, fn.$))
		.apply(data, value).join("");
	};

	fn.$ = fn.$ || $ + ".push('"
	+ str.replace(/\/g, "\\")
		 .replace(/[rtn]/g, " ")
		 .split("&lt;#").join("t")
		 .replace(/((^|#&gt;)[^t]*)'/g, "$1r")
		 .replace(/t=(.*?)#&gt;/g, "',$1,'")
		 .split("t").join("');")
		 .split("#&gt;").join($ + ".push('")
		 .split("r").join("\'")
	+ "');return " + $;

	return data ? fn(data) : fn;
}})({}, '$' + (+ new Date));
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2012/02/21/javascript%e6%a8%a1%e7%89%88%e5%bc%95%e6%93%8e-tmpl-%e7%9a%84%e7%b2%be%e7%ae%80%e5%8f%8abug%e4%bf%ae%e6%ad%a3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个简单的中文字符转unicode的chrome插件</title>
		<link>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/</link>
		<comments>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 10:58:53 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[chrome插件]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=744</guid>
		<description><![CDATA[插件安装地址(请用chrome打开)： toUnicode.crx 12-7 更新增加了从unicode转字符，以及encode，decode等方便的功能 在通常的JS或CSS文件里，汉字等字符是以unicode的16进制形式存在的， 如果直接输入汉字，在英文或其他语种的系统上，容易造成乱码无法识别的状况，如果把所有汉字转成unicode形式就没有问题了，所以就想到做一个chrome小插件，随时查看汉字的unicode编码， 直接看下主转换代码： /** * 中文转unicode字符工具 */ function toUnicode(str, cssType) { var i = 0, l = str.length, result = [], //转换后的结果数组 unicodePrefix, //unicode前缀 (example:&#x5C;1234&#124;&#124;&#x5C;u1234) unicode16; //转换成16进制后的unicode //如果是css中使用格式为&#x5C;1234之类 unicodePrefix = (cssType &#038;&#038; cssType.toLowerCase() === 'css') ? &#8230; <a href="http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>插件安装地址(请用chrome打开)： <a href="http://www.ueder.net/chrome_expansion/toUnicode.crx">toUnicode.crx</a><br />
<span style="color:red">12-7 更新增加了从unicode转字符，以及encode，decode等方便的功能</span></p>
<p>在通常的JS或CSS文件里，汉字等字符是以unicode的16进制形式存在的， 如果直接输入汉字，在英文或其他语种的系统上，容易造成乱码无法识别的状况，如果把所有汉字转成unicode形式就没有问题了，所以就想到做一个chrome小插件，随时查看汉字的unicode编码，<br />
直接看下主转换代码：</p>
<pre class="prettyprint">
/**
 * 中文转unicode字符工具
 */
function toUnicode(str, cssType) {
    var i = 0,
        l = str.length,
        result = [], //转换后的结果数组
        unicodePrefix, //unicode前缀 (example:&#x5C;1234||&#x5C;u1234)
        unicode16; //转换成16进制后的unicode

    //如果是css中使用格式为&#x5C;1234之类
    unicodePrefix = (cssType &#038;&#038; cssType.toLowerCase() === 'css') ? '&#x5C;&#x5C;' : '&#x5C;&#x5C;u';

    for (; i &lt; l; i++) {
        //转为16进制的unicode, js及css里须转成16进制
        unicode16 = str.charCodeAt(i).toString(16);
        result.push( unicodePrefix + unicode16 );
    }

    return result.join(' ');
}
</pre>
<p>字符串的charCodeAt方法返回的是10进制的unicode，所以我们需要用toString(16)将其转为16进制的，才能在JS及CSS中使用，而CSS中跟JS不同的是少了个U。</p>
<p>再来看下页面上的调用 ：</p>
<pre class="prettyprint">
/**
 * excute
 */
var input = document.getElementById('input'),
    convert = document.getElementById('convert'),
    CSSResult = document.getElementById('resultCSSType'),
    JSResult = document.getElementById('resultJSType'),
    msg = document.getElementById('msg');

//事件处理
function convertStr(e) {
    var v = input.value;

    //管理事件
    switch (e.type) {
        case 'click':
            if (checkInput(v)) {
                renderResult(v);
            }
            break;

        case 'keydown':
            if (e.keyCode === 13 &#038;&#038; checkInput(v)) {
                renderResult(v);
            }
            break;
    }

    //检测英文等字符排除
    function checkInput(str) {
        var charReg = /[^u0391-uFFE5]/g; //匹配英文等无需转换的字符

        if (charReg.test(str)) {
            msg.innerHTML = '输入字符格式有误，请输入中文等字符';
            input.select();
            input.focus();
            renderResult('');
            return false;
        } else {
            msg.innerHTML = '';
            return true;
        }

    }

    //渲染结果
    function renderResult(str) {
        JSResult.innerHTML = toUnicode(str);
        CSSResult.innerHTML = toUnicode(str, 'css');
    }

} 

//bind事件
convert.addEventListener('click', convertStr, false);
input.addEventListener('keydown', convertStr, false);
input.addEventListener('blur', convertStr, false);
</pre>
<p>正则/[\u0391-\uFFE5]/是用来匹配中文字符，包括标点，繁体什么的。</p>
<p>再来就是生成chrome插件，chrome插件制作很简单，只需在chrome的扩展程序里导入你的项目文件 ，通常就是html+css+js文件即可，然后就可打包生成crx文件，可以在chrome上安装的插件了，（PS:具体的插件制作GG搜索下就有了）</p>
<p>本来想发布至chrome的webstore里，结果发布竟然还要收费 ，所以还是作罢，直接贴一下插件安装地址吧，请用chrome打开 <a href="http://www.ueder.net/chrome_expansion/toUnicode.crx">toUnicode.crx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/10/%e4%b8%80%e4%b8%aa%e7%ae%80%e5%8d%95%e7%9a%84%e4%b8%ad%e6%96%87%e5%ad%97%e7%ac%a6%e8%bd%acunicode%e7%9a%84chrome%e6%8f%92%e4%bb%b6/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>关于递归在项目中的几种常用应用</title>
		<link>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/</link>
		<comments>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 04:04:35 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[递归]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=732</guid>
		<description><![CDATA[项目中常常会对开发返回的json数据进行遍历，然后更新页面，如果数据只是简单的一层结构，只需一个for循环即可搞定，但如果数据存在较深且不确定的层次，此时就需要使用递归配合循环来搞定，先看下模拟的数据格式： //json数据 var json = { status: 'success', data: [ { status: 0, title: '文件夹1', data: [ { status: 0, title: '文件夹2', data: [ { status: 0, title: '文件夹3', data: [ { status: 0, title: '文件夹4', data: [] }, { &#8230; <a href="http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>项目中常常会对开发返回的json数据进行遍历，然后更新页面，如果数据只是简单的一层结构，只需一个for循环即可搞定，但如果数据存在较深且不确定的层次，此时就需要使用递归配合循环来搞定，先看下模拟的数据格式：</p>
<pre class="prettyprint">
//json数据
var json = {
    status: 'success',
    data: [
        {
            status: 0,
            title: '文件夹1',
            data: [
                {
                    status: 0,
                    title: '文件夹2',
                    data: [
                        {
                            status: 0,
                            title: '文件夹3',
                            data: [
                                {
                                    status: 0,
                                    title: '文件夹4',
                                    data: []
                                },
                                {
                                    status: 0,
                                    title: '文件夹4',
                                    data: []
                                }
                            ]
                        },
                        {
                            status: 0,
                            title: '文件夹3',
                            data: []
                        }
                    ]
                },
                {
                    status: 0,
                    title: '文件夹2',
                    data: []
                }
            ]
        },
        {
            status: 1,
            title: '文件1',
        }
    ]
};
</pre>
<p>对于上面这种深层次的数据结构，普通的循环是无法搞定的，此时可以提取重复处理的代码片段，然后使用递归 即可搞定，直接看代码：</p>
<pre class="prettyprint">
/**
 * 递归遍历数据
 */
function recursion(data) {
    var i = 0,
        len = data.length,
        j, item, current, flag;

    for (; i &lt; len; i++) {
        item = data[i];

        for (j in item) {
            current = item[j];
            //是否数组判断
            flag = (Object.prototype.toString.call(current) === '[object Array]') ? true : false;

            if (flag) {
                recursion(current);
            } else {
                //这里执行对数据的相应操作
                console.log(current);
            }
        }
    }
}

//调用
recursion(json.data);
</pre>
<p>一个类似的应用是DOM节点的游走，可以遍历整个文档所有节点，包括子节点，看如下代码：</p>
<pre class="prettyprint">
/**
 * 节点遍历
 */
function nodeWalk(node, fn) {
    var re = arguments.callee; //引用函数本身

    if (node.nodeType === 1) {
        //处理节点
        fn.call(node, node);
    }

    node = node.firstChild;

    while (node) {
        re(node, fn);
        node = node.nextSibling;
    }

}

//调用
nodeWalk(document.body, function(n){
    console.log(this.nodeName);
});
</pre>
<p>还有一种典型用例是，对于多行的input需要往后端ajax实时验证输入内容的时候，普通的for循环已不能解决问题，需要在ajax请求成功的回调函数里进行递归调用，直接看示例代码：</p>
<pre class="prettyprint">
//初始化
var nodeList = $('#test input:text'),
    n = 0;

/**
 * 递归验证
 */
(function recursionCheck(node) {

    var v = node.value,
        nextNode = nodeList[++n];

    //ajax请求服务端验证
    $.ajax({
        'url': 'xxxxx.do',
        'data': 'xxxxxx',
        'dataType': 'json',
        'success': function(data){

            //验证成功，递归调用代码验证下一个node
            if (data.value === v) {

                //判断节点是否存在
                if (nextNode) {
                    recursionCheck(nextNode);
                } else {
                    alert('验证通过');
                }
            } 

            //验证不成功，结束执行，给出错误提示
            else {
                alert('数据验证不正确');
            }
        }
    });

})(nodeList[n]);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/04/%e5%85%b3%e4%ba%8e%e9%80%92%e5%bd%92%e5%9c%a8%e9%a1%b9%e7%9b%ae%e4%b8%ad%e7%9a%84%e5%87%a0%e7%a7%8d%e5%b8%b8%e7%94%a8%e5%ba%94%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>模拟AJAX无刷新的文件上传功能</title>
		<link>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/</link>
		<comments>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 07:42:59 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[无刷新上传]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=720</guid>
		<description><![CDATA[传统的文件上传功能一般是用form包一个input:file直接提交到后端进行处理，form须指定enctype=&#8221;multipart/form-data&#8221;，代码如下： &#60;form action="test.php" target="" method="post" enctype="multipart/form-data"&#62; &#60;input type="file" name="file" id="file" /&#62; &#60;input type="submit" id="J_submit" value="submit" /&#62; &#60;/form&#62; 在ajax盛行的现时，提交form再刷新整个页面，显得用户体验不佳，然而ajax与后端通信 只能传送字符串，是无法传递实体文件的，所以用ajax是无法实现直接文件上传的，这里提供一个解决方案就是用一个实时创建的隐藏iframe来完成上传功能， 具体的原理是，在点击提交按钮时，动态的生成一个隐藏iframe加入到页面上，并且 将form 的 target指向该隐藏iframe，服务端就接收到上传的file文件，并进行相应的操作，然后将返回结果返回到隐藏的iframe里面，这时我们可以与后端开发约定返回结果的格式，可以是json格式，便于我们前端操作，然后前端部分就可以用iframe.contentWindow.document.body.innerHTML来获取后端返回的结果，进行相应的parseJSON处理，即可像处理ajax返回的json一样，处理数据。。。直接贴源代码了(ps:代码是基于jQuery库的)： /** * 模拟ajax无刷新文件上传 */ var fileUpLoad = function(config) { var ifr = null, fm = null, defConfig &#8230; <a href="http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>传统的文件上传功能一般是用form包一个input:file直接提交到后端进行处理，form须指定enctype=&#8221;multipart/form-data&#8221;，代码如下：</p>
<pre class="prettyprint">
&lt;form action="test.php" target="" method="post" enctype="multipart/form-data"&gt;
    &lt;input type="file" name="file" id="file" /&gt;
    &lt;input type="submit" id="J_submit"  value="submit" /&gt;
&lt;/form&gt;
</pre>
<p>在ajax盛行的现时，提交form再刷新整个页面，显得用户体验不佳，然而ajax与后端通信 只能传送字符串，是无法传递实体文件的，所以用ajax是无法实现直接文件上传的，这里提供一个解决方案就是用一个实时创建的隐藏iframe来完成上传功能， 具体的原理是，在点击提交按钮时，动态的生成一个隐藏iframe加入到页面上，并且 将form 的 target指向该隐藏iframe，服务端就接收到上传的file文件，并进行相应的操作，然后将返回结果返回到隐藏的iframe里面，这时我们可以与后端开发约定返回结果的格式，可以是json格式，便于我们前端操作，然后前端部分就可以用iframe.contentWindow.document.body.innerHTML来获取后端返回的结果，进行相应的parseJSON处理，即可像处理ajax返回的json一样，处理数据。。。直接贴源代码了(ps:代码是基于jQuery库的)：</p>
<pre class="prettyprint">
/**
 * 模拟ajax无刷新文件上传
 */
var fileUpLoad = function(config) {

    var ifr = null,
        fm = null,
        defConfig = {
            submitBtn: $('#J_submit'), //提交按钮
            complete: function(response) {}, //上传成功后回调
            beforeUpLoad: function() {}, //点击提交未上传时回调
            afterUpLoad: function() {} //点击提交上传后回调
        };

    //静态变量
    var IFRAME_NAME = 'fileUpLoadIframe';

    //配置
    config = $.extend(defConfig, config);

    //绑定submit事件
    config.submitBtn.bind('click', function(e){
        e.preventDefault();

        //点击提交前触发事件, 函数返回false可阻止提交表单，用于file为空判断
        if (config.beforeUpLoad.call(this) === false) {
            return;
        }

        //生成一个隐藏iframe，并设置form的target为该iframe，模拟ajax效果
        ifr = $('&lt;iframe name="'+ IFRAME_NAME +'" id="'+ IFRAME_NAME +'" style="display:none;"&gt;&lt;/iframe&gt;');
        fm = this.form;

        ifr.appendTo($('body'));
        fm.target = IFRAME_NAME; //target目标设为ifr

        //上传完毕iframe onload事件
        ifr.load(function(){
            var response = this.contentWindow.document.body.innerHTML;

            config.complete.call(this, response);
            ifr.remove();
            ifr = null; //清除引用
        });

        fm.submit(); //提交表单

        //点击提交后触发事件
        config.afterUpLoad.call(this);

    });

};
</pre>
<p>页面调用是：</p>
<pre class="prettyprint">
fileUpLoad({
    submitBtn: $('#J_submit'),
    complete: function(response){ //上传成功后处理回调
        var d = $.parseJSON(response);

        alert('返回成功')
        console.log(d);
    },
    beforeUpLoad: function() {
        alert('上传前');
    },
    afterUpLoad: function() {
        alert('上传后');
    }
});
</pre>
<p>而对于需要实时显示上传进度条的应用，则可以考虑form提交后用ajax实时轮询的方式向后端取文件上传的进度，来进行前端页面进度渲染，另一种方式则是基于flash上传，这里就不详细展开了。。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/11/02/%e6%a8%a1%e6%8b%9fajax%e6%97%a0%e5%88%b7%e6%96%b0%e7%9a%84%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8a%9f%e8%83%bd/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>正则表达式的技巧总结</title>
		<link>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/</link>
		<comments>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 07:02:19 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=688</guid>
		<description><![CDATA[正则表达式在现在web的应用当中，如表单验证，url解析等，应用非常方便，比起普通的字符串解析性能上也高出不少。 这里就做一些关于正则表达式通用技巧的个人小总结，正则的入门可以参考以下网址内容 http://www.regexlab.com/zh/regref.htm http://w3school.com.cn/js/jsref_obj_regexp.asp 1. 一些常用的元字符. \w : 查找单词字符，包含字母数字及下划线，相当于[A-Za-z0-9_]; \d : 查找数字，相当于[0-9] \s : 查找空白字符 \n : 查找换行符 . : 点号代表除换行符及行结束符外所有字符 2. 验证完整字符串，这在表单验证中常用到，例子如下: var str = '18636200607'; var str2 = '10010'; var reg = /^\d{11}$/; console.log(reg.test(str)); // return true; console.log(reg.test(str2)); &#8230; <a href="http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>正则表达式在现在web的应用当中，如表单验证，url解析等，应用非常方便，比起普通的字符串解析性能上也高出不少。<br />
这里就做一些关于正则表达式通用技巧的个人小总结，正则的入门可以参考以下网址内容<br />
<a target="_blank" href="http://www.regexlab.com/zh/regref.htm">http://www.regexlab.com/zh/regref.htm</a><br />
<a target="_blank"  href="http://w3school.com.cn/js/jsref_obj_regexp.asp">http://w3school.com.cn/js/jsref_obj_regexp.asp</a></p>
<p><strong>1. 一些常用的元字符.</strong><br />
\w : 查找单词字符，包含字母数字及下划线，相当于<span class="code">[A-Za-z0-9_]</span>;<br />
\d : 查找数字，相当于<span class="code">[0-9]</span><br />
\s : 查找空白字符<br />
\n : 查找换行符<br />
.  : 点号代表除换行符及行结束符外所有字符</p>
<p><strong>2. 验证完整字符串，这在表单验证中常用到，例子如下:</strong></p>
<pre class="prettyprint">
var str = '18636200607';
var str2 = '10010';
var reg = /^\d{11}$/;
console.log(reg.test(str)); // return true;
console.log(reg.test(str2)); // return false;
</pre>
<p>这里的头尾的^$即是限定匹配的必须是整个字符串，而不是其中一部分，这对于表单验证里验证完整的合法输入很有用。<br />
<span id="more-688"></span><br />
<strong>3. 验证一个完整的单词，可以用到\b，例子如下：</strong></p>
<pre class="prettyprint">
var str = 'hello world!';
var str2 = 'helloworld!';
var reg = /\bhello\b/;
console.log(reg.test(str)); //return true
console.log(reg.test(str2)); //return false
</pre>
<p>这里\b作为单词的边界条件进行判断，与^$夹着字符串相似，但\b夹的是单个单词</p>
<p><strong>4. 捕获型分组与非捕获型分组</strong><br />
捕获型分组是小括号包围起来的一个分组表达式，里面匹配到的内容可以在之后调用，例子如下:</p>
<pre class="prettyprint">
var str = '1234haha';
var reg = /(\d+)\w+/;
var result = reg.exec(str);
console.log(result[0]); //return '1234haha'
console.log(result[1]); //return '1234'
</pre>
<p>正则对象的exec方法与test不同，它如果匹配不成功返回null,成功则返回一个数组对象，[0]包含匹配到的完整字符串，[1][2]&#8230;等等则保存着各个子表达式里所捕获的内容（即小括号里获取的字符串）;<br />
小括号在正则里还有一个用处则是起到分组的作用<br />
如： <span class="code">(abcd){4}</span><br />
此表达式表示abcd整个字符串重复4次才能匹配成功<br />
但小括号同时也影响了exec方法返回的捕获数组内容，<br />
此时如果不希望捕获内容影响，可以使用非捕获分组，非捕获分组格式是(?:&#8230;..);<br />
如： <span class="code">(?:abcd){4}</span><br />
此时小括号里的内容只会起到分组的作用，并不会捕获内容。</p>
<p><strong>5. 方括号与分组表达式的或结构</strong><br />
方括号里的内容只会匹配单个字符，<br />
例如 <span class="code">[1234]</span> 只会匹配1234里的一个字符，如果希望匹配的是一个字符串可以使用非捕获型分组来达成目的<br />
而或结构的分组表达式 <span class="code">(?:12|34)</span> 会匹配12 或 34这两个字符里的其中一组。<br />
示例代码：</p>
<pre class="prettyprint">
var str = '1234';
var reg = /[1234]/;
var reg2 = /(?:12|34)/;
console.log(reg.exec(str)[0]); //retrun '1'
console.log(reg2.exec(str)[0]); //return '12'
</pre>
<p><strong>6. 贪婪模式与非贪婪模式</strong><br />
<span class="code">\w+</span> 在匹配字符串 &#8216;hello&#8217; 时会匹配整个字符串，此时为贪婪模式<br />
但 <span class="code">\w+?</span> 在匹配时 则只匹配 &#8216;h&#8217;单个字符串，此时为非贪婪模式<br />
也就是说在量词(*, +, ?, {5, })后面加个?即形成非贪婪模式，会尽可能在不影响匹配成功的情况下，少匹配字符<br />
示例代码：</p>
<pre class="prettyprint">
var str = 'hello';
var reg = /\w+/;
var reg2 = /\w+?/;
console.log(reg.exec(str)[0]); //retrun 'hello'
console.log(reg2.exec(str)[0]); //return 'h'
</pre>
<p><strong>7. 反向引用</strong><br />
捕获型分组里捕获的内容在三种情况下可以被引用<br />
第一是exec方法回复的数组里，从[1]开始<br />
第二是test或exec方法执行后，RegExp.$1开始之后存储捕获内容<br />
第三则是在正则表达式里的反向引用，如\1 \2这种形式<br />
看下例子：</p>
<pre class="prettyprint">
var str = '&lt;td&gt;这里是td&lt;/td&gt;';
var reg = /&lt;(\w+)&gt;.*&lt;\/\1&gt;/;
console.log(reg.test(str)); // return true
</pre>
<p>此处正则表达式里\1则是引用了前面的捕获型分级(\w+)的内容</p>
<p><strong>8. 正向预搜索及不匹配</strong><br />
预搜索与^$\b一样本身不匹配内容，只是提供一个判断<br />
看下例子：</p>
<pre class="prettyprint">
var str = 'HelloWorld';
var reg = /Hello(?=World)/;
var reg2 = /Hello(?!World)/;
console.log(reg.test(str)); // return true
console.log(reg2.test(str)); //return false
</pre>
<p><span class="code">(?=&#8230;)</span>代表前面要匹配的字符后面必须带有指定的字符才能匹配成功<br />
<span class="code">(?!&#8230;)</span>则相反，代表不包含指定的字符<br />
javascript不支持反向预搜索，这里就不介绍了</p>
<p><strong>9. 正则对象的方法</strong><br />
RegExpObject.test 方法：<br />
这是表单验证中常用到的方法，如果匹配成功返回true,反之false</p>
<p>RegExpObject.exec 方法：<br />
exec方法很强大，它基本提供了所有所需要的信息<br />
返回的是一个数组，数组的[0]存放的是匹配到的完整字符串，[1][2]开始存放的是捕获型分组（也就是正则里的小括号包围的内容）捕获到的字符串,<br />
该数组还包含额外两个属性index及input; index标识的是匹配结果的字符串位置，input标识的是正则表达式<br />
其实exec最强大的地方是在于，对于带g全局标识的正则表达式(如<span class="code">/\w+/g</span>)，在每次执行exec的时候，都会将正则对象的lastIndex设置为前一个匹配到的字符串的最后一个位置<br />
换句话说，你就可以利用这个特性进行整个字符串的遍历，并配合捕获型分组，就可以得到你想要的字串内容<br />
看如下例子</p>
<pre class="prettyprint">
//解析url
var url = 'http://www.taobao.com/?ver=1.0&#038;q=search';
var reg = /(\w+)=([^&#038;]*)/g;
var obj = {};
var result;
while(result = reg.exec(url)){
    obj[result[1]] = result[2];
}
console.log(obj); //return {ver:'1.0', q:'search'}
</pre>
<p>以上就可以遍历正则匹配整个字符串，配合捕获分组就可以得到你想要的字串了</p>
<p>String.match 方法 ：<br />
如果正则表达式不带g全局标识，字符串的match方法与正则对象的exec对象相似，只进行一次匹配，返回一个数组，[0]存放的是完整匹配字串，[1]以后存放捕获分组的内容<br />
如果正则表达式带g全局标识，则match方法回返的内容大不一样，也是一个数组，但是是从[0]开始各个存放匹配到的完整匹配字串，就不会再存放捕获分组的内容了<br />
有时这在简单匹配整个字串的时候比起exec简便些<br />
看下例子：</p>
<pre class="prettyprint">
var str = '1: 哈哈，2: 呵呵， 3: 嘿嘿';
var reg = /\d:/g;
console.log(str.match(reg)); //return ['1:', '2:', '3:']
</pre>
<p>以上直接回返匹配到的结果数组</p>
<p>String.replace 方法：<br />
字符串的replace方法带两个参数，第一个参数是查找匹配的字符串，第二个参数是要替换成的内容，也可以是个function匿名函数<br />
如果是正则替换方式，则第二个参数里的$有特殊的含义，$1 $1&#8230;代表的是之前正则表达式里的捕获分组得到的字串，$&#038;代表的是匹配得到的完整字串，$`代表匹配字串左侧的文本，$&#8217;代表匹配字串右侧的文本</p>
<p>看下面个例子：</p>
<pre class="prettyprint">
var str = 'hello world!';
var reg = /(\w+)\s(\w+)/;
str = str.replace(reg, '$2 $1');
console.log(str); //return 'world hello!'
</pre>
<p>这里利用到$1 $2的捕获分组的内容。</p>
<p>再看个例子：</p>
<pre class="prettyprint">
var str = 'background-color';
var reg = /-(\w)/g;
str = str.replace(reg, function(w, s){
    return s.toUpperCase();
});
console.log(str); // return 'backgroundColor'
</pre>
<p>对于加g的正则表达式，replace方法会循环执行替换操作，replace方法里的第二个参数如果是function，则function的第一个参数是完整的正则匹配字串，第二个参数开始则是捕获分组得到的字串。</p>
<p>String.split方法及String.search方法较为简单，可参考相关资料</p>
<p>参考资料：<br />
<a href="http://www.regexlab.com/zh/regref.htm">http://www.regexlab.com/zh/regref.htm</a><br />
<a href="http://w3school.com.cn/js/jsref_obj_regexp.asp">http://w3school.com.cn/js/jsref_obj_regexp.asp</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/07/07/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e7%9a%84%e6%8a%80%e5%b7%a7%e6%80%bb%e7%bb%93/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>浮动元素的水平居中</title>
		<link>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/</link>
		<comments>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 06:07:33 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[html/css]]></category>
		<category><![CDATA[浮动元素水平居中]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=680</guid>
		<description><![CDATA[对于页面上的块级元素，只须定宽及设置margin:0 auto;即可在水平上居中，但对于浮动的元素水平居中是无效的，一个典型的应用就是页面的分页效果了，看如下图： 这种分页效果，在以往可能会采取设置inline-block，然后父容器设置text-align:center方式来实现内容居中，像如下代码： &#60;!DOCTYPE html&#62; &#60;html xmlns=&#34;http://www.w3.org/1999/xhtml&#34;&#62; &#60;head&#62; &#60;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=utf-8&#34; /&#62; &#60;title&#62;页面元素的水平居中&#60;/title&#62; &#60;style type=&#34;text/css&#34;&#62; * { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; } .clearfix:after { content:&#34;&#34;; height:0; visibility:hidden; display:block; clear:both; } .clearfix { zoom:1; } a{ text-decoration:none;} &#8230; <a href="http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>对于页面上的块级元素，只须定宽及设置margin:0 auto;即可在水平上居中，但对于浮动的元素水平居中是无效的，一个典型的应用就是页面的分页效果了，看如下图：<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2011/03/1.jpg"><img src="http://www.ueder.net/wp-content/uploads/2011/03/1.jpg" alt="" title="1" width="643" height="85" class="alignnone size-full wp-image-681" /></a><br />
这种分页效果，在以往可能会采取设置inline-block，然后父容器设置text-align:center方式来实现内容居中，像如下代码：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_YcMf6s">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.page2{ text-align:center;}
.page2 a{ display:inline-block;padding:2px 9px; background:white; border:1px solid red; vertical-align:middle;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;inline-block方式：&lt;/h2&gt;
&lt;div class=&quot;wrap page2&quot;&gt;
	&lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_YcMf6s").style.height = document.getElementById("runcode_YcMf6s").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_YcMf6s');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_YcMf6s');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_YcMf6s','runcode_YcMf6s');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p><span id="more-680"></span><br />
这种设置inline-block的缺点是，元素需要设置vertical-align:middle，并且ie下不能完美对齐，以及元素间有空白符等。。<br />
所以可以考虑用float方式代替inline-block，优点是float的元素盒模型好控制 ，无空白符等等。<br />
代码如下：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_e6eCpv">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; font-family:Tahoma, Geneva, sans-serif; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.page { float:left; position:relative; left:50%; }
.page li { float:left; position:relative; right:50%; overflow:hidden; margin:0 5px; }
.page li a { display:block; padding:2px 9px; background:white; border:1px solid red; }
.page2{ text-align:center;}
.page2 a{ display:inline-block;padding:2px 9px; background:white; border:1px solid red; vertical-align:middle;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;浮动方式：&lt;/h2&gt;
&lt;div class=&quot;wrap clearfix&quot;&gt;
	&lt;ul class=&quot;page&quot;&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;5&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;6&lt;/a&gt; &lt;/li&gt;
		&lt;li&gt; &lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt; &lt;/li&gt;
	&lt;/ul&gt;
&lt;/div&gt;
&lt;h2&gt;inline-block方式：&lt;/h2&gt;
&lt;div class=&quot;wrap page2&quot;&gt;
	&lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;1&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;2&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;3&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;4&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;5&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;6&lt;/a&gt;
	&lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_e6eCpv").style.height = document.getElementById("runcode_e6eCpv").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_e6eCpv');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_e6eCpv');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_e6eCpv','runcode_e6eCpv');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>这里主要用到position:relative配合left:50%的技巧，兼容各浏览器，需要注意的是IE7下需要设置overflow:hidden;来解决无法设置子元素宽度的BUG。</p>
<p>这里也可以多套一层的方式设置left:-50%，更合理，也可以避免一些不必要的IE BUG，如下代码：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_YUpLym">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面元素的水平居中&lt;/title&gt;
&lt;style type=&quot;text/css&quot;&gt;
* { margin:0; padding:0; list-style:none; font-size:14px; }
.clearfix:after { content:&quot;&quot;; height:0; visibility:hidden; display:block; clear:both; }
.clearfix { zoom:1; }
a{ text-decoration:none;}
h1{ text-align:center; padding:10px; font-size:20px; margin:30px 0;}
.wrap { margin:20px auto; padding:10px 0; background:orange; overflow:hidden; position:relative; }
.inwrap{ float:left; position:relative; left:50%;}
.page { float:left; position:relative; left:-50%; }
.page li { float:left;margin:0 5px;  }
.page li a { display:block; padding:2px 9px; background:white; border:1px solid red; float:left;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h1&gt;页面元素的水平居中&lt;/h1&gt;
&lt;h2&gt;浮动方式：&lt;/h2&gt;
&lt;div class=&quot;wrap clearfix&quot;&gt;
	&lt;div class=&quot;inwrap&quot;&gt;
		&lt;ul class=&quot;page&quot;&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;上一页&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;1&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;2&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;3&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;4&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;5&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;6&lt;/a&gt; &lt;/li&gt;
			&lt;li&gt; &lt;a href=&quot;#&quot;&gt;下一页&lt;/a&gt; &lt;/li&gt;
		&lt;/ul&gt;
	&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_YUpLym").style.height = document.getElementById("runcode_YUpLym").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_YUpLym');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_YUpLym');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_YUpLym','runcode_YUpLym');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>举一反三，这种float元素居中的方式其实可以延展应用到很多需要浮动元素又居中的情况。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/03/15/%e6%b5%ae%e5%8a%a8%e5%85%83%e7%b4%a0%e7%9a%84%e6%b0%b4%e5%b9%b3%e5%b1%85%e4%b8%ad/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>HTML5的本地存储 LocalStorage</title>
		<link>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/</link>
		<comments>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 03:51:59 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[localStorage]]></category>
		<category><![CDATA[本地存储]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=666</guid>
		<description><![CDATA[localStorage顾名思义，就是本地存储的意思，在以前很长一段时间，要想在客户端存储一些配置及登录信息等数据都只能通过COOKIE或flash的方式，如今html5来临，也带来了更强大的本地存储，最多可存储大小5M的字符串，足可以满足大部分的web应用，比cookie的4K要大出不少，还有一个sessionStorage，功能基本与localStorage相同，看名字便知与sesstion一样，关闭浏览器即失效。 以前有用过cookie的都了解cookie的存储读取方式都不太优雅，需要自己封装set get方法，而localStorage则方便许多，localStorage 是作為window的一个属性存在的，拥有setItem,getItem,removeItem,clear等方法，相当方便。 浏览器的支持除了IE７及以下不支持外，其他标准浏览器都完全支持(ie及FF需在web服务器里运行)，支持情况如下图： 如下代码即可判断浏览器是否支持 if(window.localStorage){ alert("浏览支持localStorage") }else{ alert("浏览暂不支持localStorage") } localStorage不但可以用自身的setItem,getItem等方便存取，也可以像普通对象一样用点操作符，及[]的方式进行数据存储，像如下的例子 var storage = window.localStorage; storage.a = "haha"; storage["b"] = "hehe"; var a = storage.a; var b = storage["b"]; 另外，localStorage还提供了一个key()方法，配合localStorage的length属性，可以在不知道有哪些键值的时候使用，如下： var storage = window.localStorage; function showStorage(){ for(var i=0;i&#60;storage.length;i++){ //key(i)获得相应的键，再用getItem()方法获得对应的值 &#8230; <a href="http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>localStorage顾名思义，就是本地存储的意思，在以前很长一段时间，要想在客户端存储一些配置及登录信息等数据都只能通过COOKIE或flash的方式，如今html5来临，也带来了更强大的本地存储，最多可存储大小5M的字符串，足可以满足大部分的web应用，比cookie的4K要大出不少，还有一个sessionStorage，功能基本与localStorage相同，看名字便知与sesstion一样，关闭浏览器即失效。</p>
<p>以前有用过cookie的都了解cookie的存储读取方式都不太优雅，需要自己封装set get方法，而localStorage则方便许多，localStorage 是作為window的一个属性存在的，拥有setItem,getItem,removeItem,clear等方法，相当方便。</p>
<p>浏览器的支持除了IE７及以下不支持外，其他标准浏览器都完全支持(ie及FF需在web服务器里运行)，支持情况如下图：<br />
<a class="noeffect" href="http://www.ueder.net/wp-content/uploads/2011/03/1375849686163397167.jpg"><img src="http://www.ueder.net/wp-content/uploads/2011/03/1375849686163397167.jpg" alt="" title="1375849686163397167" width="637" height="152" class="alignnone size-full wp-image-667" /></a></p>
<p>如下代码即可判断浏览器是否支持</p>
<pre class="prettyprint">
if(window.localStorage){
    alert("浏览支持localStorage")
}else{
   alert("浏览暂不支持localStorage")
}
</pre>
<p><span id="more-666"></span><br />
localStorage不但可以用自身的setItem,getItem等方便存取，也可以像普通对象一样用点操作符，及[]的方式进行数据存储，像如下的例子</p>
<pre class="prettyprint">
var storage = window.localStorage;
storage.a = "haha";
storage["b"] = "hehe";
var a = storage.a;
var b = storage["b"];
</pre>
<p>另外，localStorage还提供了一个key()方法，配合localStorage的length属性，可以在不知道有哪些键值的时候使用，如下：</p>
<pre class="prettyprint">
var storage = window.localStorage;
function showStorage(){
 for(var i=0;i&lt;storage.length;i++){
  //key(i)获得相应的键，再用getItem()方法获得对应的值
  document.write(storage.key(i)+ " : " + storage.getItem(storage.key(i)) + "&lt;br&gt;");
 }
}
</pre>
<p>FF里storage.key(i) == storage[i], 算个BUG吧</p>
<p>HTML5的本地存储，还提供了一个storage事件，可以对键值对的改变进行监听，使用方法如下：</p>
<pre class="prettyprint">
if(window.addEventListener){
 window.addEventListener("storage",handle_storage,false);
}else if(window.attachEvent){
 window.attachEvent("onstorage",handle_storage);
}
function handle_storage(e){
 if(!e){e=window.event;}
 //showStorage();
}
</pre>
<p>对于事件变量e，是一个StorageEvent对象，提供了一些实用的属性，可以很好的观察键值对的变化，如下表：</p>
<table width="100%" border="1">
<tr>
<td> Property
  </td>
<td> Type
  </td>
<td> Description
  </td>
</tr>
<tr>
<td>key
  </td>
<td>String
  </td>
<td> The named key that was added, removed, or moddified
  </td>
</tr>
<tr>
<td>oldValue
  </td>
<td>	 Any
  </td>
<td> The previous value(now overwritten), or null if a new item was added
  </td>
</tr>
<tr>
<td>newValue
  </td>
<td>	 Any
  </td>
<td>	 The new value, or null if an item was added
  </td>
</tr>
<tr>
<td> url/uri
  </td>
<td>String
  </td>
<td>The page that called the method that triggered this change
  </td>
</tr>
</table>
<p>写一个最简单的，利用本地存储的计数器，有一个需要注意的地方是不管setItem里传什么类型，最终都会被转成string，所以getItem的时候需要转类型：</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_bUYvAa">
&lt;!doctype HTML&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body &gt;
&lt;div id=&quot;c&quot;&gt;&lt;/div&gt;
 &lt;script&gt;
var storage = window.localStorage;
if(!storage.getItem(&quot;num&quot;)){
	storage.setItem(&quot;num&quot;,0);
}
var n = parseInt(storage.getItem(&quot;num&quot;))+1;
storage.setItem(&quot;num&quot;,n);
document.getElementById(&quot;c&quot;).innerHTML = &quot;这里显示的是计数结果：&quot; + n;
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_bUYvAa").style.height = document.getElementById("runcode_bUYvAa").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_bUYvAa');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_bUYvAa');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_bUYvAa','runcode_bUYvAa');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/03/05/html5%e7%9a%84%e6%9c%ac%e5%9c%b0%e5%ad%98%e5%82%a8-localstorage/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>页面性能优化之内容加载优化</title>
		<link>http://www.ueder.net/2011/01/23/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e6%8c%89%e9%9c%80%e5%8a%a0%e8%bd%bd%e5%8f%8a%e6%8c%89%e9%9c%80%e6%b8%b2%e6%9f%93/</link>
		<comments>http://www.ueder.net/2011/01/23/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e6%8c%89%e9%9c%80%e5%8a%a0%e8%bd%bd%e5%8f%8a%e6%8c%89%e9%9c%80%e6%b8%b2%e6%9f%93/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 15:02:28 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[按需加载]]></category>
		<category><![CDATA[按需渲染]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=626</guid>
		<description><![CDATA[图片按需加载 现在大部分门户或电子商务网站的产品列表页,都比较长,且图片较多,如果全部加载,通常会耗费较多时间,而且有数据表明长时间的等待页面响应会流失大部分的用户, 所以此时我们就可以考虑只加载第一屏的内容,第一屏内容以外的图片按需加载,用户滚动到该屏时再加载(包括tab切换也可以考虑未显示的区域图片不加载),这样用户在不进行任何操作时,加载页面会很快. 看下面的简单demo: &#60;!DOCTYPE html&#62; &#60;head&#62; &#60;meta http-equiv=&#34;Content-Type&#34; content=&#34;text/html; charset=utf-8&#34; /&#62; &#60;title&#62;按需加载的图片&#60;/title&#62; &#60;/head&#62; &#60;body&#62; &#60;script type=&#34;text/javascript&#34;&#62; for(var i=0; i&#60;60; i++){ document.write(&#34;这里是正文内容 &#60;span style='color:#999;font-size:12px;'&#62;[往下拉动滚动条]&#60;/span&#62;&#60;br /&#62;&#34;); } &#60;/script&#62; &#60;p style=&#34;color:red&#34;&#62;这是按需加载的图片&#60;/p&#62; &#60;p&#62;&#60;img data_src=&#34;http://www.ueder.net/testhtml/picshow/datapic/0e0c883622903fb1a61e12be.jpg&#34; width=&#34;400&#34; height=&#34;600&#34; src=&#34;&#34; alt=&#34;&#34; /&#62;&#60;/p&#62; &#60;script type=&#34;text/javascript&#34; src=&#34;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&#34;&#62;&#60;/script&#62; &#60;script &#8230; <a href="http://www.ueder.net/2011/01/23/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e6%8c%89%e9%9c%80%e5%8a%a0%e8%bd%bd%e5%8f%8a%e6%8c%89%e9%9c%80%e6%b8%b2%e6%9f%93/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>图片按需加载</strong><br />
现在大部分门户或电子商务网站的产品列表页,都比较长,且图片较多,如果全部加载,通常会耗费较多时间,而且有数据表明长时间的等待页面响应会流失大部分的用户,<br />
所以此时我们就可以考虑只加载第一屏的内容,第一屏内容以外的图片按需加载,用户滚动到该屏时再加载(包括tab切换也可以考虑未显示的区域图片不加载),这样用户在不进行任何操作时,加载页面会很快.<br />
看下面的简单demo:</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_QzSdko">
&lt;!DOCTYPE html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;按需加载的图片&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
for(var i=0; i&lt;60; i++){
	document.write(&quot;这里是正文内容 &lt;span style='color:#999;font-size:12px;'&gt;[往下拉动滚动条]&lt;/span&gt;&lt;br /&gt;&quot;);
}
&lt;/script&gt;
&lt;p style=&quot;color:red&quot;&gt;这是按需加载的图片&lt;/p&gt;
&lt;p&gt;&lt;img data_src=&quot;http://www.ueder.net/testhtml/picshow/datapic/0e0c883622903fb1a61e12be.jpg&quot; width=&quot;400&quot; height=&quot;600&quot; src=&quot;&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(window).scroll(function(){
	setTimeout(function(){
		var winHeight = $(window).height();
		var scrolltop = $(window).scrollTop();
		var oTop = $(&quot;img&quot;).offset().top;
		if((oTop-scrolltop)&gt;0 &amp;&amp; (oTop-scrolltop)&lt;winHeight){
			var src = $(&quot;img&quot;).attr(&quot;data_src&quot;);
			$(&quot;img&quot;).attr(&quot;src&quot;,src)
		}
	},500);
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_QzSdko").style.height = document.getElementById("runcode_QzSdko").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_QzSdko');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_QzSdko');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_QzSdko','runcode_QzSdko');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>点运行可查看结果,这里测试代码略显粗糙,其实可以利用JQuery好好的用插件形式封装一下,比如可以判断img是否有src属性,没有再执行赋值操作,避免重要赋值,以及setTimeout的使用可以避免滚动过程中大量scroll事件引起性能损耗.</p>
<p><span id="more-626"></span></p>
<p><strong>页面DOM结构按需渲染</strong><br />
按需渲染与按需加载不同, 按需渲染是指DOM结构在浏览器的呈现过程, 这无关网络, 是浏览器构建盒模型,渲染页面的过程,<br />
一个页面通常内容有轻有重,有时候我们会希望最先呈现给用户的是一些重要信息, 这个一方面可以在页面结构上做一些小技巧, 像经典的<a href="http://www.ueder.net/2010/11/03/%e6%b5%81%e4%bd%93%e5%b8%83%e5%b1%80%e7%9a%84%e5%87%a0%e7%a7%8d%e6%96%b9%e5%bc%8f/">负边距三列布局</a>,就可以让中间重要内容列,在代码上首先呈现,<br />
另一方面则可以通过把次要内容放置于textarea中并且隐藏它,此时页面会加载相关文本,但不会渲染页面DOM结构,等到需要呈现的时候,再把textarea中的内容赋给相应的容器,再进行渲染..<br />
看下面的代码:</p>
<div class="runcode">
<p><textarea name="runcode" style="overflow-y:visible;width:500pxpx;font-size:12px" class="runcode_text" id="runcode_AvPAtJ">
&lt;!DOCTYPE html&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;页面DOM按需渲染&lt;/title&gt;
&lt;style&gt;
.unimportant { float:left; width:300px; height:200px; background:red; color:#fff; }
.important { float:left; margin-left:20px; width:400px; height:300px; background:blue; color:#fff; }
.undis { display:none; }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div&gt;
&lt;textarea id=&quot;txtarea1&quot; name=&quot;&quot; cols=&quot;&quot; class=&quot;undis&quot; rows=&quot;&quot;&gt;
&lt;div class=&quot;unimportant&quot;&gt; 这里的是先加载后渲染的次要内容 &lt;/div&gt;
&lt;/textarea&gt;
&lt;/div&gt;
&lt;div class=&quot;important&quot;&gt; 这里显示的是重要内容 &lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	var txtarea1 = document.getElementById(&quot;txtarea1&quot;),
		parentnode = txtarea1.parentNode;
	parentnode.innerHTML += txtarea1.value;
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</textarea></p>
<script type="text/javascript">function changeTsize(){document.getElementById("runcode_AvPAtJ").style.height = document.getElementById("runcode_AvPAtJ").scrollHeight + "px";}window.setTimeout(changeTsize,0);</script><p><input type="button" value="运行" class="runcode_button" onclick="runcode_open_new('runcode_AvPAtJ');"/> <input type="button" value="复制" class="runcode_button" onclick="runcode_copy('runcode_AvPAtJ');"/> <input type="button" value="另存代码" class="runcode_button" onclick="saveCode('runcode_AvPAtJ','runcode_AvPAtJ');"/> 提示：你可以先修改部分代码再运行。</p>
</div>
<p>以上代码可以看到实现原理很简单,次要内容在代码上置前,如果不做处理,是会比重要内容先呈现的,此时就先放置于textarea中,需要时再加入到页面渲染.</p>
<p><strong>sprites图片预加载</strong><br />
现在大部分页面上都会使用sprites图片技术, 因sprites图片一般较小, 且对页面显示完整较重要, 可考虑在页面开始时就预加载进sprites图片, 像下面这段代码即可:</p>
<pre class="prettyprint">
var img = new Image();
img.src = "sprites.png";
</pre>
<p>这样即可达到预加载的效果,也可以在任何你认为需要的地方进行预加载.</p>
<p><strong>script及css的预加载</strong><br />
因为浏览器会缓存外部JS及CSS文件 ，所以script与css文件同样可以进行预加载,<br />
很多门户首页或流量大的页面,为了节省http请求数,常常会把JS及css直接写在页面上, 但子页一般是使用外调的CSS及JS文件,此时就可以考虑在首页加载完毕时, 在用户空闲时,在后台加载子页所需要的CSS及JS文件即可,同时又不影响用户操作，可以使用setTimeout动态加载外部JS及CSS.<br />
动态加载外调 js及CSS可参考 这个<a href="http://www.ueder.net/derjs/Der.js">Der微型库</a>,提供的方法，用法也很简单:</p>
<pre class="prettyprint">
//加载js带回调
Der.loadScript("http://www.ueder.net/derjs/Der.js",function(){
    //这里是加载完毕的回调函数
});
//加载CSS
Der.loadCss("http://www.ueder.net/wp-content/themes/DerStyle/style.css");
</pre>
<p>预加载与按需加载(或延迟加载)似乎听起来矛盾, 事实上并不冲突, 根据用户体验可以适当的选择预加载或按需加载.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/01/23/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e6%8c%89%e9%9c%80%e5%8a%a0%e8%bd%bd%e5%8f%8a%e6%8c%89%e9%9c%80%e6%b8%b2%e6%9f%93/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>原生JS底层微型库研究</title>
		<link>http://www.ueder.net/2011/01/23/%e5%8e%9f%e7%94%9fjs%e5%ba%95%e5%b1%82%e5%be%ae%e5%9e%8b%e5%ba%93%e7%a0%94%e7%a9%b6/</link>
		<comments>http://www.ueder.net/2011/01/23/%e5%8e%9f%e7%94%9fjs%e5%ba%95%e5%b1%82%e5%be%ae%e5%9e%8b%e5%ba%93%e7%a0%94%e7%a9%b6/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 12:41:20 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[原生js]]></category>
		<category><![CDATA[微型库]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=620</guid>
		<description><![CDATA[最近基于原生JS的研究，尝试封装了一个原生JS底层功能的实现，主要是进行了兼容性处理(众所周知IE在JS方面的很多独特性),以及一些通用方法封装，现在只做了一小部分，只包括节点的获取，事件相关，以及cookie操作等，后续再慢慢添加一些常用的，例如AJAX，CSS样式等,在写这些方法的同时就会查阅相关文档，所以也是一个不错的自我学习的过程&#8230; 以下是下载： 压缩版:http://www.ueder.net/derjs/Der.min.js 未压版:http://www.ueder.net/derjs/Der.js 以下是源码: /** * name:微型库Der.js * Author:Der(www.ueder.net) * Date:2011/01/01 * Update:2011/01/23 * Description:以方法集的方式整合兼容性的底层JS功能,可按需取用 */ //声明Der命名空间,并防止覆盖页面开发者定义的重名变量 var Der = Der &#124;&#124; {}; /************************** *DOM节点元素创建及获取的相关方法 **************************/ //通过id获取节点元素 Der.getById = Der.g = function(id){ if(typeof id === "string" &#038;&#038; !!id){ return &#8230; <a href="http://www.ueder.net/2011/01/23/%e5%8e%9f%e7%94%9fjs%e5%ba%95%e5%b1%82%e5%be%ae%e5%9e%8b%e5%ba%93%e7%a0%94%e7%a9%b6/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>最近基于原生JS的研究，尝试封装了一个原生JS底层功能的实现，主要是进行了兼容性处理(众所周知IE在JS方面的很多独特性),以及一些通用方法封装，现在只做了一小部分，只包括节点的获取，事件相关，以及cookie操作等，后续再慢慢添加一些常用的，例如AJAX，CSS样式等,在写这些方法的同时就会查阅相关文档，所以也是一个不错的自我学习的过程&#8230;</p>
<p><strong>以下是下载：</strong><br />
压缩版:<a href="http://www.ueder.net/derjs/Der.min.js">http://www.ueder.net/derjs/Der.min.js</a><br />
未压版:<a href="http://www.ueder.net/derjs/Der.js">http://www.ueder.net/derjs/Der.js</a></p>
<p><strong>以下是源码:</strong><br />
<span id="more-620"></span></p>
<pre class="prettyprint">
/**
 * name:微型库Der.js
 * Author:Der(www.ueder.net)
 * Date:2011/01/01
 * Update:2011/01/23
 * Description:以方法集的方式整合兼容性的底层JS功能,可按需取用
 */

//声明Der命名空间,并防止覆盖页面开发者定义的重名变量
var Der = Der || {}; 

/**************************
 *DOM节点元素创建及获取的相关方法
 **************************/

//通过id获取节点元素
Der.getById = Der.g = function(id){
	if(typeof id === "string" &#038;&#038; !!id){
		return document.getElementById(id);
	}
};

//通过节点属性attribute获取节点元素集合[返回节点数组]
Der.getByAttribute = function(attribute,value,nodeRefer){
	/**参数解释
	 * attribute:属性名,
	 * value:属性值,
	 * nodeRefer:参照节点 [可选]
	 */

	var nodesResult = [], //结果数组
		nodeRefer = (nodeRefer) ? nodeRefer : document, //无参照节点则设参照节点为document
		nodesCollection = nodeRefer.getElementsByTagName("*"); //获取参照节点下所有节点

	//通过attribute筛选进数组
	for(var i=nodesCollection.length-1; i&gt;=0; i--){
		var node = nodesCollection[i];
		if(attribute === "className" || attribute === "class"){ //当属性为class样式时，因IE支持不一样的字符，不用getAttribute方法，直接用点符号取className属性值
			if(node.className === value){
				nodesResult.push(node);
			}
		}else{ //为其他属性时,正常getAttribute取值
			if(node.getAttribute(attribute) === value){
				nodesResult.push(node);
			}
		}
	}

	//返回节点数组
	return nodesResult;
};

//通过class获取节点元素集合[返回节点数组]
Der.getByClass = function(cssName,nodeRefer){
	/** 参数解释
	 * cssName:样式名,
	 * nodeRefer:参照节点[可选]
	 */

	if(typeof document.getElementsByClassName === "function"){ //判断是否原生支持getElementsByClassName
		nodeRefer = (nodeRefer) ? nodeRefer : document; //无参照节点则设参照节点为document
		return Array.prototype.slice.call(nodeRefer.getElementsByClassName(cssName)); //返回转化为数组的节点集合
	}else{
		return Der.getByAttribute("className",cssName,nodeRefer);
	}
};

//创建标签[返回节点]
Der.createElement = function(tagName,attributes){
	/**参数解释
	 * tagName:元素标签名
	 * attributes:元素的属性,对象形式(范例:{"id":"myid","style":"background:red; color:blue;"})
	 */

	//创建DOM标签
	var element = document.createElement(tagName); 

	//遍历设置属性
	if(attributes){
		for(var name in attributes){
			if (attributes.hasOwnProperty(name)) { //过滤掉prototype继承的属性
				if(name === "class" || name === "className"){ //如果为样式名则直接指定className
					element.className = attributes[name];
				}else if(name === "style"){ //如果为内联样式则调用style.cssText;
					element.style.cssText = attributes[name];
				}else{ //正常设置属性
					element.setAttribute(name,attributes[name]);
				}
			}
		}
	}

	return element;
};

/**************************
 *与event事件相关的方法
 **************************/

//添加事件
Der.addEvent = function(element, type, handle){
	/**参数解释
	 * element:元素对象,
	 * type:事件类型,
	 * handle:事件处理函数
	 */

	if(element.addEventListener){
		element.addEventListener(type, handle, false);
	}else if(element.attachEvent){ //for ie
		element.attachEvent("on" + type, handle);
	}else{
		element["on" + type] = handle;
	}
};

//移除事件
Der.removeEvent = function(element, type, handle){
	/**参数解释
	 * element:元素对象,
	 * type:事件类型,
	 * handle:事件处理函数
	 */

	if(element.removeEventListener){
		element.removeEventListener(type, handle, false);
	}else if(element.detachEvent){ //for ie
		element.detachEvent("on" + type, handle);
	}else{
		element["on" + type] = null;
	}
};

//获取event对象
Der.getEvent = function(e){
	return e || event;
};

//获取target对象(须先获取event对象)
Der.getEventTarget = function(e){
	return e.target || e.srcElement;
};

//获取相关元素,在mouseover,mouseout时使用(须先获取event对象)
Der.getRelatedTarget = function(e){
	if(e.relatedTarget){
		return e.relatedTarget;
	}else if(e.toElement){ //for ie
		return e.toElement;
	}else if(e.fromElement){ //for ie
		return e.fromElement;
	}else{
		return null;
	}
};

//阻止冒泡(须先获取event对象)
Der.stopPropagation = function(e){
	if(e.stopPropagation){
		e.stopPropagation();
	}else{
		e.cancelBubble = true; //for ie
	}
};

//阻止默认行为(须先获取event对象)
Der.preventDefault = function(e){
	if(e.preventDefault){
		e.preventDefault();
	}else{
		e.returnValue = false; //for ie
	}
};

//window加载完毕
Der.windowLoad = function(handle){
	/**参数解释
	 * handle:事件处理函数
	 */

	var win = window;
	Der.addEvent(win,"load",function(){
		Der.removeEvent(win, "load", arguments.callee); //移除事件,释放内存
		handle();
	});
};

//DOM文档树加载完毕
Der.DOMReady = function(handle){
	/**参数解释
	 * handle:事件处理函数
	 */

	var doc = document;
	if(doc.addEventListener){ // 支持标准DOM事件的浏览器使用DOMContentLoaded即可判断页面DOM文档树加载完毕
		doc.addEventListener("DOMContentLoaded",function(){
			doc.removeEventListener("DOMContentLoaded", arguments.callee, false); //移除事件,释放内存
			handle();
		},false);
	}else if(doc.attachEvent){ //ie下则使用document的readystatechange事件来模拟判断文档树加载完毕
		doc.attachEvent("onreadystatechange", function(){
			if(doc.readyState === "interactive" || doc.readyState === "complete"){ //ie下可能发生两种情况中的一种
				doc.detachEvent("onreadystatechange", arguments.callee);//移除事件，防止执行两次
				handle();
			}
		});
	}
};

/**********************
 *获取、设置、删除cookie等相关方法
 *********************/

//设置cookie
Der.setCookie = function(name,value,days,path,domain,secure){
	/**参数解释
	 * name:cookie名,
	 * value:cookie值,
	 * days:失效天数,[可选]
	 * path:路径,[可选]
	 * domain:域,[可选]
	 * secure:安全标志(可选值true/false)[可选]
	 */

	//name value 编码
	var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); 

	if (days) { //cookie保存天数
		var _exp = new Date();
		_exp.setTime(_exp.getTime() + days * 24 * 60 * 60 * 1000);
		cookieText += "; expires=" + _exp.toGMTString();
	}
	if(path){ //路径
		cookieText += "; path=" + path;
	}
	if(domain){ //域
		cookieText += "; domain=" + domain;
	}
	if(secure){ //安全标志
		cookieText += "; secure";
	}

	//写入cookie
	document.cookie = cookieText;
};

//获取cookie
Der.getCookie = function(name){
	/**参数解释
	 * name:cookie名
	 */

	var cookieName = encodeURIComponent(name) + "=",
		cookieStart = document.cookie.indexOf(cookieName), //获取cookieName在cookie中的字符位置
		cookieValue = ""; //cookie值

	if(cookieStart &gt; -1){	//如果存在cookieName
		var cookieEnd = document.cookie.indexOf(";",cookieStart); //获取所需cookie末位置
		if(cookieEnd === -1){
			cookieEnd = document.cookie.length; //cookie在最后一条时
		}
		cookieValue = decodeURIComponent(document.cookie.slice(cookieStart + cookieName.length, cookieEnd)); //截取cookie
	}

	//返回cookie值
	return cookieValue;
};

//删除cookie
Der.deleteCookie = function(name){
	/**参数解释
	 * name:cookie名
	 */

	Der.setCookie(name,"",-1); //通过设置cookie过期来删除相应cookie
};	

/**********************
 *ajax以及加载外部js,css文件
 *********************/

 //ajax异步请求
 Der.ajax = function(settings){
	/**参数解释
	 * settings:对象形式的参数,
	 * 范例:{
	 *			url:"json.php", //ajax请求地址
	 *			type:"get", //请求类型,可为get或post
	 *			data:"name=Der&#038;value=frontEngineer", //请求类型为post时,传递的数据
	 *			isJson:false, //对返回数据是否进行json格式转换
	 *			success:function(response){ //返回数据成功时的回调函数
	 *				alert(response);
	 *			}
	 *		}
	 */ 

	//参数默认值扩展
	settings = Der.extend({
		url:"",
		type:"get",
		data:"",
		isJson:false
	},settings);

	//参数
	var url = Der.trim(settings.url),
		type = settings.type.toLowerCase(),
		data = settings.data,
		isJson = settings.isJson,
		success = settings.success,
		response;

	//url合法性筛选
	if(typeof url !== "string" || url === "") return;

	//创建XMLHttpRequest对象
	function createXHR(){
		if(typeof XMLHttpRequest === "function"){ //支持XMLHttpRequest的浏览器
			return new XMLHttpRequest();
		}else if(typeof ActiveXObject === "function"){ //IE6等支持ActiveXObject
			return new ActiveXObject("Microsoft.XMLHTTP");
		}
	}

	//发送http请求
	var xhr = createXHR();
	xhr.onreadystatechange = function(){
		if(xhr.readyState === 4){
			if((xhr.status&gt;=200 &#038;&#038; xhr.status&lt;300) ||
				xhr.status === 304 ||
				xhr.status === 1223){
				if(isJson){
					response = eval("("+xhr.responseText+")"); //json格式解析
				}else{
					response = xhr.responseText;
				}
				if(success){
					success(response);
				}
			}
		}
	}
	xhr.open(type,url,true);
	if(type === "get"){
		xhr.send(null);
	}else if(type === "post"){
		xhr.send(data);
	}
 };

//动态加载外部js文件
Der.loadScript = function(url, callback) {
	/**参数解释
	 * url:需要加载的外部JS路径,
	 * callback:加载完毕回调函数[可选]
	 */

	setTimeout(function(){ //setTimeout将加载js彻底移出文档加载流，实现异步，不阻塞页面其他内容
		//创建script
		var script = Der.createElement("script",{
			"src":url,
			"type":"text/javascript"
		});

		//为script添加加载完毕判断事件
		if(script.readyState) { //ie不支持DOM标签的onload事件,支持readystatechange事件
			Der.addEvent(script,"readystatechange",function(){
				if(script.readyState === "loaded" || script.readyState === "complete") {
					//加载完执行回调函数
					if(callback){callback();}
					//此处销毁事件引用，防止IE下执行两次
					Der.removeEvent(script,"readystatechange",arguments.callee);
				}
			});
		}else{ //DOM标签的onload事件
			Der.addEvent(script,"load",function(){
				//加载完执行回调函数
				if(callback){callback();}
				//此处销毁事件引用
				Der.removeEvent(script,"load",arguments.callee)
			});
		}

		//加入head
		document.getElementsByTagName("head")[0].appendChild(script);
	},0);
};

//动态加载外部css文件,无回调
Der.loadCss = function(url) {
	/**参数解释
	 * url:需要加载的外部CSS路径
	 */

	//创建引用外部CSS的link标签
	var css = Der.createElement("link",{
		"href":url,
		"rel":"stylesheet",
		"type":"text/css"
	});

	//加入head
	document.getElementsByTagName("head")[0].appendChild(css);
};

/**********************
 *工具类方法
 *********************/

//去除字符串的左右空格
Der.trim = function(str,pos){
	/**参数解释
	 * str:需要去除空格的字符串
	 * pos:去除空格的位置,可选值为"left","right"[可选]
	 */

	var trimLeft = /^[sxA0]+/,
		trimRight = /[sxA0]+$/;
	if(!pos || (pos!=="left" &#038;&#038; pos!=="right")){ //默认去除字符串两边空格
		return str.replace(trimLeft,"").replace(trimRight,"");
	}else if(pos === "left"){ //去除字符串左空格
		return str.replace(trimLeft,"");
	}else if(pos === "right"){ //去除字符串右空格
		return str.replace(trimRight,"");
	}
};

 //扩展对象(默认值替换)
Der.extend = function(target,obj){
	/**参数解释
	 * target:默认值对象
	 * obj:待扩展的对象
	 */

	if(obj){
		for (var i in target){
			if((typeof obj[i]) === "undefined"){
				obj[i] = target[i];
			}
		}
		return obj;
	}else{
		return target;
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/01/23/%e5%8e%9f%e7%94%9fjs%e5%ba%95%e5%b1%82%e5%be%ae%e5%9e%8b%e5%ba%93%e7%a0%94%e7%a9%b6/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>页面性能优化之事件委托</title>
		<link>http://www.ueder.net/2011/01/09/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e4%b9%8b%e4%ba%8b%e4%bb%b6%e5%a7%94%e6%89%98/</link>
		<comments>http://www.ueder.net/2011/01/09/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e4%b9%8b%e4%ba%8b%e4%bb%b6%e5%a7%94%e6%89%98/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 07:30:37 +0000</pubDate>
		<dc:creator>Der</dc:creator>
				<category><![CDATA[js/as]]></category>
		<category><![CDATA[事件委托]]></category>
		<category><![CDATA[性能优化]]></category>

		<guid isPermaLink="false">http://www.ueder.net/?p=605</guid>
		<description><![CDATA[在现代web追求富媒体应用(RIA)的时代，为页面添加事件成为实现复杂交互行为的很重要的一部分，然而在javascript中为页面添加很多的事件是会造成性能问题的，特别是在IE中，原因可能有很多方面，首先，每个事件都会绑定一个函数function，而每个function都会占内存，其次，页面加载时必须事先指定所有页面事件处理程序，会延迟整个页面的交互就绪时间。 所谓事件委托就是利用事件的冒泡特性，只需为所有需要添加事件的子元素的父元素添加一个事件处理程序就可以满足应用。在DOM标准中，事件支持捕获及冒泡过程，但IE中只支持冒泡过程，所以我们只需要关注冒泡过程。看下面一段代码 &#60;ul id=&#34;list&#34;&#62; &#60;li id=&#34;list1&#34;&#62;列表1&#60;/li&#62; &#60;li id=&#34;list2&#34;&#62;列表1&#60;/li&#62; &#60;li id=&#34;list3&#34;&#62;列表1&#60;/li&#62; &#60;/ul&#62; 在上面这段代码中，如果我们需要alert出每个li的innerHTML，传统方法是: var items = document.getElementById(&#34;list&#34;).getElementsByTagName(&#34;li&#34;); for(var i=0,len=items.length; i&#60;len; i++){ items[i].onclick = function(){ alert(this.innerHTML); }; } 这样我们就为页面添加了三个事件处理程序，如果在更复杂的更多的li元素的页面，那么事件处理程序就会更多，会影响到页面性能，此时我们可以利用事件冒泡优化性能，如下面代码: //事件封装 var EventUtil = { getEvent:function(e){ return e &#124;&#124; event; }, getTarget:function(e){ return &#8230; <a href="http://www.ueder.net/2011/01/09/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e4%b9%8b%e4%ba%8b%e4%bb%b6%e5%a7%94%e6%89%98/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在现代web追求富媒体应用(RIA)的时代，为页面添加事件成为实现复杂交互行为的很重要的一部分，然而在javascript中为页面添加很多的事件是会造成性能问题的，特别是在IE中，原因可能有很多方面，首先，每个事件都会绑定一个函数function，而每个function都会占内存，其次，页面加载时必须事先指定所有页面事件处理程序，会延迟整个页面的交互就绪时间。</p>
<p>所谓事件委托就是利用事件的冒泡特性，只需为所有需要添加事件的子元素的父元素添加一个事件处理程序就可以满足应用。在DOM标准中，事件支持捕获及冒泡过程，但IE中只支持冒泡过程，所以我们只需要关注冒泡过程。看下面一段代码</p>
<pre class="prettyprint">
&lt;ul id=&quot;list&quot;&gt;
	&lt;li id=&quot;list1&quot;&gt;列表1&lt;/li&gt;
	&lt;li id=&quot;list2&quot;&gt;列表1&lt;/li&gt;
	&lt;li id=&quot;list3&quot;&gt;列表1&lt;/li&gt;
&lt;/ul&gt;
</pre>
<p>在上面这段代码中，如果我们需要alert出每个li的innerHTML，传统方法是:</p>
<pre class="prettyprint">
var items = document.getElementById(&quot;list&quot;).getElementsByTagName(&quot;li&quot;);
for(var i=0,len=items.length; i&lt;len; i++){
	items[i].onclick = function(){
		alert(this.innerHTML);
	};
}
</pre>
<p><span id="more-605"></span><br />
这样我们就为页面添加了三个事件处理程序，如果在更复杂的更多的li元素的页面，那么事件处理程序就会更多，会影响到页面性能，此时我们可以利用事件冒泡优化性能，如下面代码:</p>
<pre class="prettyprint">
//事件封装
var EventUtil = {
		getEvent:function(e){
			return e || event;
		},
		getTarget:function(e){
			return e.target || e.srcElement;
		}
	};
//
var list = document.getElementById(&quot;list&quot;);
list.onclick = function(e){
	//获取事件目标
	var evt = EventUtil.getEvent(e);
	var target = EventUtil.getTarget(evt);
	//
	alert(target.innerHTML);
};
</pre>
<p>在这段代码里，我们只为父级元素添加了一个onclick事件，然后根据target获取事件实际的作用对象，然后执行我们需要的代码，这样我们只创建了一个事件处理程序，相较前面的传统代码得到了优化。</p>
<p>如果可以的话，也可以考虑为document添加事件处理程序，以减少在具体元素上添加各种事件，而且document在页面加载时是最先呈现的，几乎随时都可调用到。</p>
<p>另一个与事件有关的影响性能的则是事件的移除，我们在页面中的DOM操作常常会移除一些页面元素，而这些元素可能会带有事件，看下面的例子:</p>
<pre class="prettyprint">
&lt;div id=&quot;form&quot;&gt;
	&lt;button type=&quot;submit&quot; id=&quot;btn&quot;&gt;提交&lt;/button&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	var btn = document.getElementById(&quot;btn&quot;);
	btn.onclick = function(){
		//执行一些操作...
		document.getElementById(&quot;form&quot;).innerHTML = &quot;已提交，等待中...&quot;
	};
&lt;/script&gt;
</pre>
<p>上面的代码中点击按钮后移除了按钮，但按钮上的onclick事件并没有移除，事件会驻留在内存中，特别是IE不能很好的处理，此时我们可以在事件无用的时候手动移除，如下：</p>
<pre class="prettyprint">
&lt;div id=&quot;form&quot;&gt;
	&lt;button type=&quot;submit&quot; id=&quot;btn&quot;&gt;提交&lt;/button&gt;
&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	var btn = document.getElementById(&quot;btn&quot;);
	btn.onclick = function(){
		//执行一些操作...
		btn.onclick = null; //移除事件处理函数
		document.getElementById(&quot;form&quot;).innerHTML = &quot;已提交，等待中...&quot;
	};
&lt;/script&gt;
</pre>
<p>所以我们在往页面添加事件的时候，在不用的时候记得移除，释放内存。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ueder.net/2011/01/09/%e9%a1%b5%e9%9d%a2%e6%80%a7%e8%83%bd%e4%bc%98%e5%8c%96%e4%b9%8b%e4%ba%8b%e4%bb%b6%e5%a7%94%e6%89%98/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

