[Web]网站优化之Ajax优化及相关工具

mikel阅读(722)

web2.0大量的ajax的使用,提高了ui交互的效率,但是过度的滥用会带来不少的问题。

ajax使用注意事项:
1 尽量避免使用同步ajax调用。在一些登录的场合常常使用同步调用服务器的登录接口。
同步调用,需要将页面上的所有元素给锁定住,代价高昂。

2 ajax调用时多使用超时设置,目前许多ajax框架如JQuery都会提供超时参数的设置。
利用超时,可以很好的完善ui的交互,同时避免对服务器造成压力。

3 针对业务特性开启ajax缓存。不需要重新拉取的东东,尽量的缓存起来。

4 发送请求前对发送的数据进行pre验证,一方面可以做到对用户友好,另一方面避免太多的异常。
不小心的异常数据会导致服务器down掉。

5 对于服务器返回的数据也要仔细处理,不要相信其数据一定是格式化和验证好的。譬如对于json的数据,需要先判断相应的key是否存在,再进行操作,
否则会出现undifined的情况。

ajax请求处理一般的ui交互流程是这样的:
1 当发起ajax请求时,更新ui,譬如出现一个高亮的tip,提示用户操作开始进行
2 锁住需要更新的ui部份,同时提醒用户会什么会锁住,譬如将原div隐藏,加载一个正在加载的gif图标
3 数据成功返回后,更新ui,解除对ui的锁定
4 如果服务器返回失败,提示用户友好的失败信息

ajax使用中一些提示:
1 由于浏览器的同时向一个域名发起请求的并发数是有限制的,如ie默认的是2个,如果同时发起的ajax太多的话,是会被阻塞的。
2 返回的数据类型选择json而不是xml,一方面json数据格式会更小一些,另一方面接送封装成为一个js对象,操作起来性能会更好一些
3 尽量缓存能够缓存的内容,避免重复的发起请求
1)使用全局对象
2) flash的本地存储
3)google gears
4) ie的userData

网站优化过程常用的工具:
1 firebug和yslow,ff下常用的两个工具了
2 httpwatch和fiddler,对于网络时间的检测也不错
3 Task manager
4 js内存泄漏检测工具
5 观看优化的工具:
1)AjaxView
2)JsLex
3)YUI profiler

[Web]网站优化之页面优化

mikel阅读(661)

效率和开始的节奏以及功能的丰富彼此相互制约。最近忙着做功能,明知道有些地方可以优化的也得先放放,但是老大一关注,你的马上去做。
在老大的眼中,一次优化好后就可以不再优化,或者只需要很少的时间来维护,却不知道,优化是一个持续的过程,想法赶不上变化。
做人难,做事情更难!

优化如何开始,怎么开始,以及做些什么还是值得思量的。

优化的一些准则:
1 优化是持续存在的,当你开始做一个功能的时候,优化就开始了。而我们往往认为新做的功能就是一个优化好的功能,殊不知这个功能或者会影响到其他的功能,
或者先把功能做到70%,稍后再去优化也不迟。
2 不到万不得已的时候不要去优化。用户对于性能是有一定的忍耐性的,有时一个小小的加载图标就能让用户感到很满足的。
3 优化时需要写下用例来驱动,什么条件下测试的结果如何,有了测试用例,我们才能做到有的放矢;优化时需要保存系统的一个快照;有了这些历史信息我们才能更好的去对比,去寻找不足和需要继续优化的地方。
4 优化需要针对的是系统的瓶颈所在,找到系统的性能瓶颈,攻破他,我们得到的是事半功倍的效果。

对于一个网站的页面优化又该从何入手呢?
一个web网站的页面的生命周期有3个阶段:
1 加载
2 渲染
3 响应用户的交互

针对这三个阶段需要采取不同优化策略:
1 对于加载阶段:
加载的核心是网络传输,因此重点就是将页面折腾到最小、放到离用户最近的地方,这样加载就快了。具体的实施细则可以参考:yahoo的14条建议
摘要如下:
折腾小的话,需要将页面中无用的信息去掉,gzip压缩。
1)采用yui compressor来进行压缩css和js等
2)合并js和css文件,使用jsmin等工具
3)压缩图片,合并背景图。常用工具PngCrushPngOptimizer
4)延迟加载,等用户用到了相应的素材时才对素材进行加载。
离用户最近的话,那就是用户的浏览器cache了,所以要设置页面元素的尽量长的过期时间,能够cache的统统cache住,能够放到cdn的都放到cdn上去

2 对于渲染阶段:
渲染阶段的核心是让用户尽快的看到页面的展现,能够与页面进行交互,因此重点是显示首屏的内容,让用户提早的能够看到页面,感受交互。
1 页面首屏先显示出来的话,需要将js代码的事件处理在dom树构建好之后,如同JQuery的ready事件。
2 对于html中一些默认可以不关闭的标签,尽早的关闭掉,这样也有助于提高渲染的速度。如果让浏览器去判断何时关闭才是ok的,那需要不少的回溯操作,花费不少的代价。
msdn上有详细的描述 Close Your HTML Tags
Unlike XML, HTML has the notion of implicitly closed tags. This includes frame, img, li, and p. If you don't close these tags, Internet Explorer renders your pages just fine. If you do close your tags, Internet Explorer will render your pages even faster.
3 一些大图片的延迟加载。由于浏览器并发的连接有限,对于一些大图片会被block住,所以尽量的延迟加载,或者按需加载,渲染的速度也会快一些
4 将web服务器缓冲区中的内容尽早的输出,会提浏览器开始渲染的时间。
5 页面首屏的显示尽量不要依赖于js代码。这一点很重要,这样做的话,你的一些css和js就可以延迟加载进来,而不影响首屏的展示
6 页面onload的时候可以考虑做一些预加载的事情,把一些其它页面需要用到的素材预先加载进来。搜索引擎如google,yahoo都这样做的,悄悄的加载一些大的背景图进来。

<script>

window.onload = function () {
var script = document.createElement("script");
script.src = …;
document.body.appendChild(script);
};

</script>

4 对于运行阶段:
运行阶段的核心是对js代码的优化,根据js代码的执行原理,写出高效的js代码来。
1)变量使用就近原则
js有作用域链的概念,如果本作用域找不到,就会到上一个作用域去找,如果过多的使用全局变量,就会导致每次使用变量都要去层层的检查各个作用域,性能花费不菲啊。
声明变量时记得要加上var,否则这个变量会被放到window这个顶级作用域下
不要使用with来遍历,它会阻止js执行器从本地来查找,而是遍历作用链来查找。
对于一些不得不用的全局变量,利用局部变量来缓存它
var arr = …;
var globalVar = 0;
(function () {
var i;
for (i = 0; i < arr.length; i++) {
globalVar++;
}
})();

var arr = …;
var globalVar = 0;
(function () {
var i, l, localVar;
l = arr.length;
localVar = globalVar;
for (i = 0; i < l; i++) {
localVar++;
}
globalVar = localVar;
})();
2)对于prototype链也是一样,尽量的避免prototype链的遍历

function A () {}
A.prototype.prop1 = 1;

function B () {
this.prop2 = 2;
} B.prototype = new A();

var b = new B();
alert(b.prop1);

从b读取属性prop1,就需要从b的prototype链遍历到a的ptototype链,想想如果链很长的话,结果会如何呢

3)还是prototype,如果要创建许多的对象,建议将对象的公共方法放到prototype中,而不是放到构造函数中。
由于prototype是公用的,构造函数是每个对象都需要初始化的,会节约不少的内存。
这个需要根据情况使用,通过prototype会增加对象成员的查找时间。

function Foo () {…}
Foo.prototype.bar = function () {…};
function Foo () {
this.bar = function () {…};
}

4)尽量不要使用eval,除非性能不是问题或者必须使用eval来解决问题。
同理在seTtimeout或者setInterval是最好使用匿名函数,使用字符串的话,会导致一次eval操作。

setTimeout(function () {
// 业务代码
}, 50);

5)字符串的连接操作,尤其实在循环中的连接操作,在ie的一些版本的浏览器上会导致频繁的临时变量的拷贝(如c语言中的realloc),建议使用Array对象的join方法来解决。
更多可以参考javascript优化

var i, s = “”;
for (i = 0; i < 10000; i++) {
s += “x”;
}
var i, s = [];
for (i = 0; i < 10000; i++) {
s[i] = “x”;
}
s = s.join(“”);

6)除非是为了动态构建正则表达式,尽量少的使用Regexp对象;而且为了判断一个字符串是否匹配,建议使用test而不是exec,exec有一些性能问题。
还有,正则表达式尽量的简单,如果复杂的话,想想来回的字符串匹配,复杂度提高不少。

7) 能够cache的地方尽量的使用cache,尤其使一些循环中使用到的大数据集,相对稳定,又只是大量的读操作。
//没有使用缓存,每次调用都要生成v
var fn = (function () {
var b = false, v;
return function () {
if (!b) {
v = …;
b = true;
}
return v;
};
})();

//将v存储到fn中
function fn () {
if (!fn.b) {
fn.v = …;
fn.b = true;
}
return fn.v;
}
//延迟加载
var fn = function () {
var v = …;
return (fn = function () {
return v;
})();
};

7)对于一些大数据集的处理,尽量放到server中去做,js处理大数据集没有优势。
不要让js执行导致ui被阻塞住,这个效果就太差了。
尽量将长时间js代码通过分块在setTimeout中来做,每块不要超过300ms。否则用户就会有意见了。

function doSomething (callbackFn) {

// 做一些初始化的工作
(function () {
// 做一小块工作,时间不要长
if (termination condition) {
callbackFn();
} else {
// 执行下一个块
setTimeout(arguments.callee, 0);
}

})();
}

这和ajax的原理是一样的,多线程,分小块的去执行,提高ui交互的效率。

8) 原语操作比函数的性能要高很多。尽量使用原语操作
//小于操作
var a = 1, b = 2, c;
c = Math.min(a, b);
c = a < b ? a : b;
//数组操作
myArray.push(value);
myArray[myArray.length] = value;
myArray[idx++] = value;

9)少在循环或者性能关键点处使用异常处理,因为异常处理需要保存不好的堆栈信息。
//循环中使用try、cache不明智
var i;
for (i = 0; i < 100000; i++) {
try {

} catch (e) {

}
}

//将try、cache提取出来
var i;
try {
for (i = 0; i < 100000; i++) {

}
} catch (e) {

}

10)性能关键点处少使用for、in,with这种操作,因为涉及到prototype链的查找
var key, value;
for (key in myArray) {
value = myArray[key];

}
//换成数组来操作
var i, value, length = myArray.length;
for (i = 0; i < length; i++) {
value = myArray[i];

}

11)在if、else的分支中如果分支一样,在外面定义它
function fn () {
if (…) {

} else {

}
}
var fn;
if (…) {
fn = function () {…};
} else {
fn = function () {…};
}

12)操作dom树的时候使用innerHtml,一次性的构造,而不是append,每次还需要调整
不过使用innerHtml也有不少的危险,比如插入script钓鱼脚本等,更多参考
The Problem With innerHTML
var i, j, el, table, tbody, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
row = document.createElement("tr");
for (j = 0; j < 5; j++) {
cell = document.createElement("td");
row.appendChild(cell);
}
tbody.appendChild(row);
}

var i, j, el, idx, html;
idx = 0;
html = [];
html[idx++] = "

";
for (i = 0; i < 1000; i++) {
html[idx++] = "

";
for (j = 0; j < 5; j++) {
html[idx++] = "

";
}
html[idx++] = "

 

 

 

";
}
html[idx++] = "

 

 

 

 

";
el = document.createElement("div");
document.body.appendChild(el);
el.innerHTML = html.join("");

13) 修改dom树时尽量使用clone,而不是动态的再创建。
至少可以省去不少初始化的时间
var i, j, el, table, tbody, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
row = document.createElement("tr");
for (j = 0; j < 5; j++) {
cell = document.createElement("td");
row.appendChild(cell);
}
tbody.appendChild(row);
}

var i, el, table, tbody, template, row, cell;
el = document.createElement("div");
document.body.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
template = document.createElement("tr");
for (i = 0; i < 5; i++) {
cell = document.createElement("td");
template.appendChild(cell);
}
for (i = 0; i < 1000; i++) {
row = template.cloneNode(true);
tbody.appendChild(row);
}

14)使用documentfragment
var i, j, el, table, tbody, row, cell, docFragment;
docFragment = document.createDocumentFragment();
el = document.createElement("div");
docFragment.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {

}
document.body.appendChild(docFragment);

15)事件绑定的时候尽量绑定到最少的页面元素的子集。
我们用JQuery的选择器,常常一下子就选择了许多的元素,each一下,然后绑定事件处理函数。
如果选择出来的集合很大的话,不仅选择费时间,绑定事件处理操作是比较费时间的。
适当的时候可以借助事件的冒泡机制来实现事件的绑定。

要较快页面的显示,光有js的优化是不够的,css也需要进行相应的优化。
css优化点:
1)css sprite合并背景图
2)js不要参与到布局中来,这样的话,在没有js的情况下页面也能够正常的显示,
就可以吧js放到后米去加载了。
3)不要使用ie的表达式,不要难过使用ie的过滤器
4) 优化table的布局,让table能够在接收到全部数居前就可以进行渲染
Use table-layout:fixed
Explicitly define a COL element for each column
Set the WIDTH attribute on each col

后续还会跟进ajax的优化,以及一些常用的优化工具介绍。
下一篇:网站优化之Ajax优化及相关工具

[Lucene]Lucene.Net2.3.1开发介绍

mikel阅读(700)

3、Field配置所产生的效果

索引数据,简单的代码,只要两个方法就搞定了,而在索引过程中用到的一些类里最简单,作用也不小的就是Field,接下来看看Field的各项设置都会有什么样的效果。

代码 3.1

代码3.1就是准备好的索引过程。运行,然后呢?这里要说到一个工具,luke(lukeall)这是一个java平台下的Lucene索引管理工具。抽空,我实现了一个简单的dotNet版本的,详细请查看 NLuke版本更新信息 。接下来的索引,会用这个软件对索引进行分析。

现在就可以开始调整AddDocument方法中Field实例化时的参数了,看看调整后会对索引造成什么样的影响。这里以title对应的Field为例。

3.1 Field.Stroe选项

这个选项有3个值,下面来分析下效果。

3.1.1 Field.Stroe.Yes

刚好,默认的就是这个。用这选项建完索引,然后用NLuke查看,发现,title这个字段有,而且有8个Term。切换到文档区域,发现文档的title有内容。这个选项表示的就是存储,所以,这些是正常状态。

3.1.2 Field.Stroe.No

title也有8个Term,但是文档中没有字段了。也就是说现在可以用这个字段来搜索,但是搜索结果Hits中,不能用Document实例的Get方法来取得字段的内容了。那就是字段内容没有被存储。

3.1.3 Field.Store.COMPRESS

设置为COMPRESS,报错了,错误信息%26ldquo;Compression support not configured%26rdquo;,是个配置错误。这个错误在SupportClass,CheckCompressionSupport方法被抛 出。这里读取了一个配置文件,然后根据配置文件指定的类名来创建实例。这个类必须实现接口 SupportClass.CompressionSupport.ICompressionAdapter。在Lucene.Net中内置了一 个%26ldquo;SharpZipLibAdapter%26rdquo;,但是需要有编译符号SHARP_ZIP_LIB才能编译进去。为了看看效 果,所以给项目添加SHARP_ZIP_LIB符号,然后增加app.config配置文件,在appseting中添加 Lucene.Net.CompressionLib.class键,值是SharpZipLibAdapter。然后下载 ICSharpCode.SharpZipLib.dll,这个dll才是真正实现压缩算法的。下载地址: http://sourceforge.net/project/downloading.php?groupname=sharpdevelop%26amp;filename=SharpZipLib_0855_Bin.zip%26amp;use_mirror=nchc

把ICSharpCode.SharpZipLib.dll引入项目,就可以使用COMPRESS这个选项了。效果与Yes是一样的。

3.1.4 效果对比

对于Field.Stroe.Yes,产生字节大小是:627字节

Field.Stroe.COMPRESS是:661字节

Field.Stroe.No是:579字节

使用Field.Stroe.COMPRESS反而是占用空间最大,这不符合原先的设想。那是因为我们索引的文本太小,你可以试试看增加索引的内容,再对比小效果。

3.2 Field.Index选项

现在把Field.Stroe设置为Field.Stroe.Yes,接着来看看Field.Index的效果。

3.2.1 Field.Index.TOKENIZED

这个选项是用来控制分词的,TOKENIZED表明需要分词。运行后title有8个Term,没有问题。

3.2.2 Field.Index.UN_TOKENIZED

运行后只有4个Term,而且Term是原先写入的内容,和存储的完整内容没有区别。

3.2.3 Field.Index.NO

和预想的一样,title的Term一个也没有了。

3.2.4 Field.Index.NO_NORMS

效果似乎和Field.Index.UN_TOKENIZED一样,但是它把词条的附加信息全去掉了。比如,它将不再记录词的正太分布数据一类的东 西。这样可以减少占用的空间。而且这个用法也有一个条件,就是只要开启,就要全部开启,否则会失效。比如索引了四条数据没使用NO_NORMS,而接下来 的两条使用了NO_NORMS,那么前面四条的数据效果,那么接下来的两条数据实际上并没有产生NO_NORMS的效果。

3.2.5 效果分析

1,2,4三种情况虽然不同,但是都可以搜索,而第三种情况,也就是设置为NO,则不可以搜索。第一种情况,可以分词搜索,并且可以排序。而2,4则不能分词搜索,第四种情况不可以排序(不可以排序指,不能按照词出现的频率进行排序)。

从上面也可以看出,假设Field.Store设置为NO,而Field.Index也设置为NO,那就和没添加是一样的了。 Field.Store是给你取完整数据用的,而Field.Index则是给搜索用的。在极端的情况下,可以设置Field.Store为NO,而 Field.Index可以搜索,等取数据的时候再从数据源(比如数据库),它们中间有个关联法则,那样可以有效的减轻Lucene的工作压力。

3.3 Field.TermVector

Field.TermVector选项,现在工具还没实现这个功能,不过可以自己编码来实现。

[MVC]从 Http Request 到 Controller

mikel阅读(663)

…….. 前言

  在 ASP.NET MVC 中,开发人员要花费大量的心思在 Controller 的设计上;当用户发起 Http 请求时,Controller 首先获得响应。

试想:用户发出请求 http://hostname:80/AzureApps/BookStore

        问自己以下两个问题:

  1).  MVC 是怎样定位 ZureAppsController 的 ?

  2).  URI 里确实指明了Controller 为 AzureApps,但命名Controller类时,为什么一定要将其命名为: AzureAppsController ?

…….. 预备知识

 [1].  下载 Reflector http://www.red-gate.com/products/reflector/ , 并 Reflect UrlRoutingModule : IHttpModule

                                                                                    图 1: Reflect UrlRoutingModule

 [2].  下载 MVC 源码 http://www.microsoft.com/downloads/details.aspx?FamilyID=53289097-73ce-43bf-b6a6-35e00103cb4b&displaylang=en ,

 并打开类 MvcHandler:                  

             

      图 2: MvcHandler

…….. Q1:        MVC 是怎样定位 ZureAppsController 的 ?

  图2清楚地告诉我们,哦,原来Controller 是 MvcHandler 通过 URI 传递的 controllerName 找到的。

但我们并未在 Web.config 中 配置 MvcHandler 啊?

  MVC 巧用 MvcRouteHandler 在 RoutingModule 中将 MvcHanlde 带了进来。


public class MvcRouteHandler : IRouteHandler {
        
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext) {
            
return new MvcHandler(requestContext);
        }


        
IRouteHandler Members
    }

 

 但我们也没有配置 "MvcRouteHandler" 啊?

 哈哈, 你在配置 Route ,调用扩展方法 MapRoute 时,MVC 做了手脚.  

 


[SuppressMessage("Microsoft.Design""CA1054:UriParametersShouldNotBeStrings", MessageId = "2#",
            Justification 
= "This is not a regular URL as it may contain special routing characters.")]
        
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces) {
            
if (routes == null{
                
throw new ArgumentNullException("routes");
            }

            
if (url == null{
                
throw new ArgumentNullException("url");
            }


            Route route 
= new Route(url, new MvcRouteHandler()) {
                Defaults 
= new RouteValueDictionary(defaults),
                Constraints 
= new RouteValueDictionary(constraints)
            }
;

            
if ((namespaces != null&& (namespaces.Length > 0)) {
                route.DataTokens 
= new RouteValueDictionary();
                route.DataTokens[
"Namespaces"= namespaces;
            }


            routes.Add(name, route);

            
return route;
        }

 

 此时,打开 Reflector,  可以清楚地看到 UrlRoutingModule 在初始化模块时,注册了 OnApplicationPostMapRequestHandler 。

OnApplicationPostMapRequestHandler 通过 MapRoute 指定的 MvcRouteHandler, 取得了 MvcHandler.

MvcHandler 在 ProcessRequest 时,根据 controllerName 找到了对应的 Controller ,并实例化之。

…….. 总结

  希望本文对和我一样,对第一个问题起初不太清楚的同仁,有些帮助。

  下一个问题: 

                     Q2:         命名Controller类时,为什么一定要将其命名为: ZureAppsController ? 

  因时间有限,留作下次吧。

[MVC]一步一步改写简单的登录注册(二)改写View和Controller

mikel阅读(791)

      书接上文,昨天我们写了一个简单的注册,今天我们来改写一下,改成像是MVC框架的样子,或者说本来就应该这么写。

      先来看看UserController里面,我们在昨天写了两个属性,是用来从表单中取值的:

Code

      如果是以前写WebForm写习惯了的朋友,这么写其实很常见,或者说我们大部分都是这么写的,现在在MVC中,我们从表单中获取数据就更加方便了,直接在Action中添加两个参数就OK了:

Code

      这里你要注意的是Action后面的参数必须要和你表单元素的名字一致,不然是获取不到的。但是MCV框架提供了一种更简便的方式,我们来看下:

Code

      这种写法也是有要求的,那就是你表单中元素的名称,必须要和你绑定的对象中的属性一致,比如说这个注册,如果我要这么写的话,表单中元素的命名必须为UserName和UserPwd,这样才能获取到绑定的对象。
      现 在Action貌似是改好了,可是现在问题又来了,当你点击首页的注册链接的时候,就会报错,因为首页的连接是没有传递任何参数进来的。解决这个问题的办 法当然也不是唯一的,你可以新写一个无参的Action,然后返回View("Register")。下面我要说的是另外一种方法,我在 UserController中新添加一个Action:

1public ActionResult Register()
2{
3     return View();
4}

      这么一看,貌似是重载了Action,但其实运行的时候会报错,这也很好理解,因为在Routing规则中是提交到了Register 中,但是从名字上来说是一模一样的,使得指代不明确。那么我们如何解决这个问题,其实也很简单,只需要在这个处理表单的Action上加一个特性就好了:

Code

      这个特性的意思是说,只有当处理Post请求的时候才会调用它,很显然首页的超链接是个Get请求,这样我们就把它们区分开来了。

      再来说View。这是我们昨天写的View:

1<%Html.BeginForm("Register""User"); %>
2    用户名:<%=Html.TextBox("txtName"%><br />
3    密  码:<%=Html.Password("txtPwd"%><br />
4    <input type="submit" value="提交" />
5<%Html.EndForm(); %>
6

      在实际开发中,页面实际上时美工做好了的,对于美工来说,表单中的元素都是像这样的<input type="text" />,难到说我们拿到页面之后第一件事就是把所有元素拿来改成咱们昨天写的那个样子吗?相信这是个不小的工作量,那么我们就干脆换成Html标签的 样子好了:

Code

      运行一下也没什么问题,但是这么写有一个缺陷,万一哪天Routing规则变了,你这里还要改Action,为了一劳永逸,我们就干脆这么写:

Code

      这样写的好处是,对于Routing的修改没有影响,然后不影响美工的开发,自己也不用多干好多事儿了。那么如果你一定要用昨天写的方式来做,可能会设计到元素样式的问题,我们大概写一下:

1<%=Html.TextBox("txtName","请输入用户名",new{style="border-width:1px;border-style:solid"})%>

      这样就写成了一个细边框样式的文本框,如果要用类选择器来写,可以这样:

1<%=Html.TextBox("txtName","请输入用户名",new{@class="mystyle"})%>

      今天就改到这里吧~谢谢大家捧场:)

代码在这里

[IE]完美解决IE不能显示论坛验证码等PNG图片问题

mikel阅读(673)

一、
…………………………………………………………  
使用 开始->运行,在运行输入框中输入 “regsvr32 c:\windows\system32\pngfilt.dll”(然后点击确定)
   注意,这个pngfilt.dll在有的系统中是在 c:\windows\system中的,要自己查看一下这文件在哪里,根据自己的系统修改一下路径。如果在注册时出现 “已加载 c:\windows\system32\pngfilt.dll,但没有找到DllRegisterSever 输入点。无法注册这个文件”,则表明这个文件可能损坏了,你要去别的机子去Copy一个好的过来。再进行一次注册。
二、
………………………………………………………..  
    有些人是因为自己系统的设置问题,即任意打开一个文件夹,在上方菜单上选择“工具”->“文件夹选项”->“文件类型”,选择下方的“还原”按钮。(如插图1)。
三、  
   
……………………………………………………………………
    开始 -> 运行,在运行输入框中输入“Regedit”,到这个路径“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft \Windows\CurrentVersion\Internet Settings\Accepted Documents
”,在右边右键“新建”->“字符串值” 紧接着最大的数字命名,我这里是3,故命名为4,并赋值为“image/png”。(见插图2)。
四  
………………………………………………………………………..  
    我打开Regedit,去到 [HKEY_CLASSES_ROOT\MIME\Database]一看,天哪!!!我这个键完全是空的!!!什么都没有!我再去朋友正常的机子(与我 一样是WinXPSP2)上一看,这个键里的项目不止一百项………………郁闷哪!于是我把他机子的[HKEY_CLASSES_ROOT\MIME]整个 键导出到mime.reg,再到我机子导入,咦,奇怪,什么都没有改变??什么都没有增加!!这里我想到了键的权限问题,在MIME键上右键,发现,权限 里居然一个人都没有!于是我把MIME项整个删除,导入,再右键查看权限,正常(自己账号是全权控制的)!
五  
…………………………………………………………………….  
    安装SP2后,大多数用户发现在访问某些需要填写验证码的地方,都无法显示验证码图片(显示为一个红色小叉),这是一个非常严重的BUG。解决办法为:运 行“Regedit”命令打开注册表编辑器,依次定位到“[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft \Internet Explorer\Security]”,在窗口右边新建一个名为“BlockXBM”的REG_DWORD值,将其值设置为“0”(十六进值)。
六   
..  …………………………………………………………………..
   首先注册文件dll 运行 regsvr32 pngfilt.dll
然后进行以下操作:
1.在WINDOWS开始/执行打入REGEDIT
2.到HKEY_LOCAL_MACHINE/SOFTWARE/MICROSOFT/INTERNET EXPLORER/EMBEDEXTNTOCLSIDMAPPINGS/.PNG
看存不存在.
3.假若不存在.
MOUSE点它的上一层,也就是EMBEDEXTNTOCLSIDMAPPINGS
4.然后按MOUSE右键新增机码,输入.PNG
5.然后MOUSE在.PNG反白,
按MOUSE右键新增字串值(预设值)
6.对着预设值按MOUSE右键,选择上面的"修改",
7.输入
clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
8.按确定.
假如.PNG存在,则检查它是否有个预设值的字串值.
里面是否有
clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
保存后关闭IE浏览器,重新打开IE,这时png图片就能正常显示了.

[JQuery]jQuery性能优化指南

mikel阅读(712)

现在JQuery应用的越来越多, 有些同学在享受爽快淋漓coding时就将性能问题忽略了,  比如我.  JQuery虽在诸多的js类库中性能表现还算优秀, 但毕竟不是在用原生的JavaScript开发, 性能问题还是需要引起重视的. 在twitter上发现了<jQuery Performance Rules>这篇文章, 简单的摘译了一下:

  1. 总是从ID选择器开始继承
  2. 在class前使用tag
  3. jQuery对象缓存起来
  4. 掌握强大的链式操作
  5. 使用子查询
  6. 对直接的DOM操作进行限制
  7. 冒泡
  8. 消除无效查询
  9. 推迟到 $(window).load
  10. 压缩js
  11. 全面掌握jQuery

1. 总是从ID选择器开始继承

jQuery中最快的选择器是ID选择器. 因为它直接来自于JavaScript的getElementById()方法.

<div id=“content”>
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>

像这样选择按钮是低效的:

var traffic_button = $(‘#content .button’);

用ID直接选择按钮效率更高:

var traffic_button = $(‘#traffic_button’);

选择多个元素

提到多元素选择其实是在说DOM遍历和循环, 这些都是比较慢的东西.为了提高性能, 最好从就近的ID开始继承.

var traffic_lights = $(‘#traffic_light input’); 

2. 在class前使用tag

第二快的选择器是tag选择器($(’head’)). 同理,因为它来自原生的getElementsByTagName() 方法.

<div id=“content”>
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>;

总是用一个tag name来限制(修饰)class (并且不要忘记就近的ID):

var active_light = $(‘#traffic_light input.on’);

注意: 在jquery中Class是最慢的选择器. IE浏览器下它会遍历所有DOM节点不管它用在那里.

不要用用tag name来修饰ID. 下面的例子将会遍历所有的div元素来查找id为’content’的哪一个节点:

var content = $(‘div#content’);

用ID修饰ID也是画蛇添足:

var traffic_light = $(‘#content #traffic_light’);

3.将jquery对象缓存起来

要养成将jquery对象缓存进变量的习惯.

永远不要这样做:

$(‘#traffic_light input.on).bind(’click‘, function(){…});
$(’#traffic_light input.on).css(‘border’, ‘3px dashed yellow’);
$(‘#traffic_light input.on).css(’background-color‘, ‘orange‘);
$(’#traffic_light input.on).fadeIn(’slow’);

最好先将对象缓存进一个变量然后再操作:

var $active_light = $(‘#traffic_light input.on’);
$active_light.bind(‘click’, function(){…});
$active_light.css(‘border’, ‘3px dashed yellow’);
$active_light.css(‘background-color’, ‘orange’);
$active_light.fadeIn(’slow’);

为了记住我们本地变量是jquery的封装, 通常用一个$作为变量前缀. 记住,永远不要让相同的选择器在你的代码里出现多次.

缓存jquery结果,备用

如果你打算将jquery结果对象用在程序的其它部分,或者你的function会多次执行, 那么就将他们缓存到一个全局变量中.

定义一个全局容器来存放jquery结果, 我们就可以在其它函数引用它们:

// 在全局范围定义一个对象 (例如: window对象)
window.$my =
{
// 初始化所有可能会不止一次要使用的查询
head : $(‘head’),
traffic_light : $(‘#traffic_light’),
traffic_button : $(‘#traffic_button’)
};

function do_something()
{
// 现在你可以引用存储的结果并操作它们
var script = document.createElement(’script’);
$my.head.append(script);

// 当你在函数内部操作是, 可以继续将查询存入全局对象中去.
$my.cool_results = $(‘#some_ul li’);
$my.other_results = $(‘#some_table td’);

// 将全局函数作为一个普通的jquery对象去使用.
$my.other_results.css(‘border-color’, ‘red’);
$my.traffic_light.css(‘border-color’, ‘green’);
}

4. 掌握强大的链式操作

上面的例子也可以写成这样:

var $active_light = $(‘#traffic_light input.on’);$active_light.bind(‘click’, function(){…})
.css(‘border’, ‘3px dashed yellow’)
.css(‘background-color’, ‘orange’)
.fadeIn(’slow’);

这样可以写更少的代码, 让我们的js更轻量.5.使用子查询

jQuery 允许我们对一个已包装的对象使用附加的选择器操作. 因为我们已经在保存了一个父级对象在变量里, 这样大大提高对其子元素的操作:

<div id=“content”>
<form method=“post” action=“/”>
<h2>Traffic Light</h2>
<ul id=“traffic_light”>
<li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
<li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
<li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
</ul>
<input class=“button” id=“traffic_button” type=“submit” value=“Go” />
</form>
</div>

例如, 我们可以用子查询的方法来抓取到亮或不亮的灯, 并缓存起来以备后续操作.

var $traffic_light = $(‘#traffic_light’),
$active_light = $traffic_light.find(‘input.on’),
$inactive_lights = $traffic_light.find(‘input.off’);

提示: 你可以用逗号分隔的方法一次声明多个局部变量–节省字节数

6.对直接的DOM操作进行限制

这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM 。这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作 。直接的DOM操作速度很慢。

例如,你想动态的创建一组列表元素, 千万不要这么做:

var top_100_list = […], // 假设这里是100个独一无二的字符串
$mylist = $(‘#mylist’); // jQuery 选择到 <ul> 元素

for (var i=0, l=top_100_list.length; i<l; i++)
{
$mylist.append(‘<li>’ + top_100_list[i] + ‘</li>’);
}

我们应该将整套元素字符串在插入进dom中之前全部创建好:

var top_100_list = […],
$mylist = $(‘#mylist’),
top_100_li = “”; // 这个变量将用来存储我们的列表元素

for (var i=0, l=top_100_list.length; i<l; i++)
{
top_100_li += ‘<li>’ + top_100_list[i] + ‘</li>’;
}
$mylist.html(top_100_li);

我们在插入之前将多个元素包裹进一个单独的父级节点会更快:

var top_100_list = […],
$mylist = $(‘#mylist’),
top_100_ul = ‘<ul id=”#mylist”>’;

for (var i=0, l=top_100_list.length; i<l; i++)
{
top_100_ul += ‘<li>’ + top_100_list[i] + ‘</li>’;
}
top_100_ul += ‘</ul>’; //关闭无序列表
$mylist.replaceWith(top_100_ul);

如果你做了以上几条还是担心有性能问题,那么:

  • 试试jquery的 clone() 方法, 它会创建一个节点树的副本, 它允许以”离线”的方式进行dom操作, 当你操作完成后再将其放回到节点树里.
  • 使用 DOM DocumentFragments. 正如jQuery作者所言, 它的性能要明显优于直接的dom操作.

    7. 冒泡

    除非在特殊情况下, 否则每一个js事件(例如:click, mouSEOver, 等.)都会冒泡到父级节点. 当我们需要给多个元素调用同个函数时这点会很有用.

    代替这种效率很差的多元素事件监听的方法就是, 你只需向它们的父节点绑定一次, 并且可以计算出哪个节点触发了事件.

    例如, 我们要为一个拥有很多输入框的表单绑定这样的行为: 当输入框被选中时为它添加一个class

    像这样绑定事件是低效的:

    $(‘#entryform input).bind(’focus‘, function(){
    $(this).addClass(’selected‘);
    }).bind(’blur‘, function(){
    $(this).removeClass(’selected‘);
    });

    我们需要在父级监听获取焦点和失去焦点的事件:

    $(‘#entryform’).bind(‘focus’, function(e){
    var cell = $(e.target); // e.target grabs the node that triggered the event.
    cell.addClass(’selected’);
    }).bind(‘blur’, function(e){
    var cell = $(e.target);
    cell.removeClass(’selected’);
    });

    父级元素扮演了一个调度员的角色, 它可以基于目标元素绑定事件. 如果你发现你给很多元素绑定了同一个事件监听, 那么你肯定哪里做错了.

    8.消除无效查询

    尽管jquery可以很优雅的处理没有匹配元素的情况, 但它还是需要花费时间去寻找. 如果你整站只有一个全局js, 那么极有可能把所有的jquery函数塞进$(document)ready(function(){//所有你引以为傲的代码})里.

    只运行在页面里用到的函数. 大多数有效的方法就是使用行内初始化函数, 这样你的模板就能准确的控制何时何处该执行js.

    例如, 你的”文章”页面模板, 你可能会引用如下的代码在body结束处:

    <script type=“text/javascript>
    mylib.article.init();
    </script>
    </body>

    如果你的页面模板包含一些多变的模块可能不会出现在页面中, 或者为了视觉呈现的原因你需要它们能够快速加载, 你可以将初始化函数紧跟在模块之后.

    <ul id=“traffic_light”>
    <li><input type=“radio” class=“on” name=“light” value=“red” /> Red</li>
    <li><input type=“radio” class=“off” name=“light” value=“yellow” /> Yellow</li>
    <li><input type=“radio” class=“off” name=“light” value=“green” /> Green</li>
    </ul>
    <script type=“text/javascript>
    mylib.traffic_light.init();
    </script>

    你的全局js库可能会是这样子的:

    var mylib =
    {
    article_page :
    {
    init : function()
    {
    // Article 特有的jQuery函数.
    }
    },
    traffic_light :
    {
    init : function()
    {
    // Traffic light 特有的jQuery函数.
    }
    }
    }

    9. 推迟到 $(window).load

    jquery对于开发者来说有一个很诱人的东西, 可以把任何东西挂到$(document).ready下冒充事件. 在大多数例子中你都会发现这样的情况.

    尽管$(document).rady 确实很有用, 它可以在页面渲染时,其它元素还没下载完成就执行. 如果你发现你的页面一直是载入中的状态, 很有可能就是$(document).ready函数引起的.

    你可以通过将jquery函数绑定到$(window).load 事件的方法来减少页面载入时的cpu使用率. 它会在所有的html(包括<iframe>)被下载完成后执行.

    $(window).load(function(){
    // 页面完全载入后才初始化的jQuery函数.
    });

    多余的功能例如拖放, 视觉特效和动画, 预载入隐藏图像,等等. 都是适合这种技术的场合.

    10. 压缩js

    推荐一个js在线压缩地址:  http://dean.edwards.name/packer/ 

    11. 全面掌握jquery库

    知己知彼, 百战百胜.  只有更深入的了解jQuery才能更灵活的使用它.  这里提供一个jQuery的速查手册, 可以打印出来随身携带.  要是有能力将jQuery源码通读一遍那就更好了.

    原文来自:jQuery Performance Rules ; 译文来自:Rlog.cn . 若转载请注明出处, 谢谢

    本文链接:http://www.blueidea.com/tech/web/2009/6737.asp 

[Flash]flash编程入门,用actionscript3.0实现经典游戏【连连看】

mikel阅读(708)

连连看作为一个经典的游戏受到很多上班族的喜爱

我老婆就很喜欢玩这个游戏,好,给她做一个

做起来也不难,只要知道实现的原理,不管用什么语言都很容易实现

先看效果

 

 

怎么去实现呢?一下是我的实现原理

1. 加载图片将图片

2. 创造一个二维数组,保存成对的随机图片,并显示在屏幕上

3. 连接算法。

算法是关键,我的思路很简单,首先判断是不是在一条直线上

然后再判断经过两个折线是不是能连接,最后判断经过三条折线是不是能够连接

以下是核心代码

 

private function SeekRoad():Array
        
{
            var road:Array 
= new Array();
            
            
//在一条直线上            
            if(IsThrough(this.firstClick_.ix,this.firstClick_.iy,this.secondClick_.ix,this.secondClick_.iy))
            
{
                road.push(GetPathPoint(
this.firstClick_.ix,this.firstClick_.iy));
                road.push(GetPathPoint(
this.secondClick_.ix,this.secondClick_.iy));
                
return road;
            }

            
            
for(var i:uint=0;i<GV.WidthNum+2;i++)
            
{
                
if(this.map_[i][this.firstClick_.iy].Type == 0 && IsXThrough(this.firstClick_.ix,this.firstClick_.iy,i,this.firstClick_.iy))
                
{
                    road 
= new Array();
                    road.push(GetPathPoint(
this.firstClick_.ix,this.firstClick_.iy));
                    road.push(GetPathPoint(i,
this.firstClick_.iy));
                    
//两折
                    if(IsYThrough(i,this.firstClick_.iy,this.secondClick_.ix,this.secondClick_.iy))
                    
{
                        road.push(GetPathPoint(
this.secondClick_.ix,this.secondClick_.iy));
                        
return road;
                    }

                    
//三折
                    if(this.map_[i][this.secondClick_.iy].Type == 0 && IsYThrough(i,this.firstClick_.iy,i,this.secondClick_.iy))
                    
{
                        road.push(GetPathPoint(i,
this.secondClick_.iy));
                        
if(IsXThrough(i,this.secondClick_.iy,this.secondClick_.ix,this.secondClick_.iy))
                        
{
                            road.push(GetPathPoint(
this.secondClick_.ix,this.secondClick_.iy));
                            
return road;
                        }

                    }

                }

            }

            
            
for(var j:uint=0;j<GV.HeightNum+2;j++)
            
{
                
if(this.map_[this.firstClick_.ix][j].Type == 0 && IsYThrough(this.firstClick_.ix,this.firstClick_.iy,this.firstClick_.ix,j))
                
{
                    road 
= new Array();
                    road.push(GetPathPoint(
this.firstClick_.ix,this.firstClick_.iy));
                    road.push(GetPathPoint(
this.firstClick_.ix,j));
                    
//两折
                    if(IsXThrough(this.firstClick_.ix,j,this.secondClick_.ix,this.secondClick_.iy))
                    
{
                        road.push(GetPathPoint(
this.secondClick_.ix,this.secondClick_.iy));
                        
return road;
                    }

                    
//三折
                    if(this.map_[this.secondClick_.ix][j].Type == 0 && IsXThrough(this.firstClick_.ix,j,this.secondClick_.ix,j))
                    
{
                        road.push(GetPathPoint(
this.secondClick_.ix,j));
                        
if(IsYThrough(this.secondClick_.ix,j,this.secondClick_.ix,this.secondClick_.iy))
                        
{
                            road.push(GetPathPoint(
this.secondClick_.ix,this.secondClick_.iy));
                            
return road;
                        }

                    }

                }

            }

            
return new Array();
        }

 

代码还未优化,仅供参考

[新闻]7月编程语言榜:借iphone成功,Objective-C排名接近前20

mikel阅读(502)

【CSDN 7月8日编译】Tiobe近日公布了2009年7月的编程语言排行榜,本期榜单中的显著变化是:一直在50名左右的Objective-C排名大幅提升, 它的流行当归功于iphone的成功,因为Objective-C一直被用于编写iphone应用程序。另一个需要关注的语言是JavaFX,一个月的时 间里它的排名从72迅速爬升到44.

前十位排名仍然没有变化,分别是:Java、C、C++、PHP、 Visual Basic、C#、,Python、Perl、JavaScript、Ruby。其中C#、,Python、Perl有轻微调整。

编程语言排名前20

【Objective-C百科】

简介:

Objective-C,通常写作ObjC和较少用的Objective C或Obj-C,是扩充C的面向对象编程语言。它主要使用于Mac OS X和GNUstep这两个使用OpenStep标准的系统,而在NeXTSTEP和OpenStep中它更是基本语言。Objective-C可以在 gcc运作的系统写和编译,因为gcc含Objective-C的编译器。

语言特性:

Objective-C是非常实际的语言。它使用一个用C写成、很小的运行库,只会令应用程序的大小增加很小,和大部分OO系统使用极大的VM执行 时间会取代了整个系统的运作相反。ObjC写成的程序通常不会比其原始码大很多。而其函式库(通常没附在软件发行本)亦和Smalltalk系统要使用极 大的内存来开启一个窗口的情况相反。
Objective-C的最初版本并不支持垃圾回收。在当时这是争论的焦点之一,很多人考虑到 Smalltalk回收时有漫长的死亡时间,令整个系统失去功用。Objective-C为避免此问题才不拥有这个功能。虽然某些第三方版本已加入这个功 能(尤是GNUstep), Apple在其Mac OS X 10.3中仍未引入这个功能。
另一个问题是ObjC不包括命名空间机制 (namespace mechanism)。取而代之的是程序设计师必须在其类别名称加上前缀,时常引致冲突。在2004年,在Cocoa编程环境中,所有Mac OS X类别和函式均有NS作为前缀,例如NSObject或NSButton来清楚分办它们属于Mac OS X核心;使用NS是由于这些类别的名称在NeXTSTEP开发时定下。

虽然Objective-C是C的母集,但它也不视C的基本型别为第一级的对象。

同C++的异同:

和C++不同,Objective-C不支援运算子多载(它不支持ad-hoc多型)。亦与C++不同,但和Java相同,Objective-C 只容许对象继承一个类别(不设多重继承)。Categories和protocols不但可以提供很多多重继承的好处,而且没有很多缺点,例如额外执行时 间过重和二进制不兼容。

推荐文章:

Objective-C introduction

iPhone开发入门和Objective-C 2.0简明教程

Objective-C入门

排名21到50的编程语言:

长期趋势图:

原文链接:http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html