惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
T
Threat Research - Cisco Blogs
量子位
Last Week in AI
Last Week in AI
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
爱范儿
爱范儿
D
Docker
人人都是产品经理
人人都是产品经理
S
SegmentFault 最新的问题
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog RSS Feed
A
About on SuperTechFans
P
Proofpoint News Feed
博客园 - 司徒正美
Recent Announcements
Recent Announcements
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
有赞技术团队
有赞技术团队
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
Vercel News
Vercel News
SecWiki News
SecWiki News
Attack and Defense Labs
Attack and Defense Labs
Hacker News: Ask HN
Hacker News: Ask HN
AI
AI
博客园_首页
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
T
Tailwind CSS Blog
MyScale Blog
MyScale Blog
T
Tenable Blog
宝玉的分享
宝玉的分享
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
S
Secure Thoughts
C
Check Point Blog
S
Security Affairs
L
LINUX DO - 最新话题
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
月光博客
月光博客
Y
Y Combinator Blog

博客园 - YFeng_Lee

webHttpBinding+wsHttpBinding+basicHttpBinding的区别 (转) AppDomain对于静态对象的独享引用 AppDomain 详解(转) .net工具 InstallShield12 添加自定义对话框,并根据输入值修改对应的Config文件。 普通管理类程序开发之难度系数、层次之说法(转自csdn) 待阅读书目 C#开发Windows Service程序 创建一个windows service应用程序 Ext的组件结构分析(转) XML与数据库 分析模式 - 责任模式 NHibernate Cascades: the different between all, all-delete-orphans and save-update 企业开发框架NHibernate和Spring.Net简介-4 企业开发框架NHibernate和Spring.Net简介-3 企业开发框架NHibernate和Spring.Net简介-2 企业开发框架NHibernate和Spring.Net简介-1 Nhibernate学习之many-to-many篇(转 明了篇) Nhibernate学习起步之many-to-one篇(转 明了篇)
Ext简介(转)
YFeng_Lee · 2009-03-11 · via 博客园 - YFeng_Lee

无论你是Ext库的新手,抑或是想了解Ext的人,本篇文章的内容都适合你。本文将简单地介绍Ext的几个基本概念,和如何快速地做出一个动态的页面并运行起来,假设读者已具备了一些JavaScript经验和初级了解HTML Dom。否则的话,请从阅读初学JavaScript资源开始。

下载Ext
如果你未曾下载过,那应从这里下载最新版本的Ext http://extjs.com/downloads

针对你的下载需求,有几个不同的弹性选项。通常地,最稳定的版本,是较多人的选择。下载解包后,那个example文件夹便是一个探索Ext的好地方!

开始!
我们将使用Ext,来完成一些JavaScript任务。

Zip文件包括三个文件:ExtStart.html, ExtStart.js和ExtStart.css。解包这三个文件到Ext的安装目录中(例如,Ext是在“C:\code\Ext\v1.0”中,那应该在"v1.0"里面新建目录“tutorial”。双击ExtStart.htm,接着你的浏览器打开启动页面,应该会有一条消息告诉你配置已完毕。如果是一个Javascript错误,请按照页面上的指引操作。

在你常用的IDE中或文本编辑器中,打开ExtStart.js看看:

Ext.onReady可能是你接触的第一个方法。这个方法是指当前DOM加载完毕后,保证页面内的所有元素能被Script引用(reference)。你可删除alert()那行,加入一些实际用途的代码试试:

Ext.onReady(function() {
 alert("Congratulations!  You have Ext configured correctly!");
});

Element:Ext的核心
大多数的JavaScript操作都需要获取页面上的某个元素(reference),好让你来做有趣的事情。传统的JavaScript方法,是通过ID获取Dom节点的:

var myDiv = document.getElementById('myDiv');

这毫无问题,不过这样单单返回一个对象(DOM节点),用起来并不是太强大和好用。为了要用那节点干点事情,你将会要写不少自定义的代码;另外,对于不同类型浏览器之间的差异,要你处理起来可真头大了。

进入Ext.element 对象。元素(element)的的确确是Ext的心脏地带,--无论是访问元素(elements)还是完成一些动作,都要涉及它。Element的API是整个Ext库的基础,如果你时间不多,只想了解Ext中的一个类的话,Element一定是首选!

由ID获取一个Ext Element如下(首页ExtStart.htm包含一个div,ID名字为“myDiv”,然后,在ExtStart.js中加入下列语句):

Ext.onReady(function() {var myDiv = Ext.get('myDiv');});

再回头看看Element对象,发现什么有趣的东东呢?

> Element包含了常见的DOM方法和属性,提供一个快捷的、统一的、跨浏览器的接口(若使用Element.dom的话,就可以直接访问底层DOM的节点。);
> Element.get()方法内置缓存处理(Cache),多次访问同一对象效率上有极大优势;
> 内置常用的DOM节点的动作,并且是跨浏览器的定位的位置、大小、动画、拖放等等(add/remove CSS classes, add/remove event handlers, positioning, sizing, animation, drag/drop)。

这意味着你可用最小的代码来做各种各样的事情,这里仅仅是一个简单的例子(完整的列表在ElementAPI中)。

继续在ExtStart.js中,在刚才我们获取好myDiv的位置中加入:

myDiv.highlight();      //黄色高亮显示然后渐退
myDiv.addClass('red');  // 添加自定义CSS类 (在ExtStart.css定义)
myDiv.center();         //在视图中将元素居中
myDiv.setOpacity(.25);  // 使元素半透明

获取多个DOM的节点
通常情况下,不能由ID获取多个DOM的节点,有可能因为没设置ID,或者你不知道ID,又或者直接用ID方式引用有太多元素了。这种情况下,你会不用ID来作为获取元素的依据,可能会用属性(attribute)或CSS Classname代替。基于以上的原因,Ext引入了一个功能异常强大的Dom Selector库,叫做DomQuery。

DomQuery可作为单独的库使用,但常用于Ext,你可以在上下文环境中(Context)获取多个元素,然后通过Element接口调用。幸运的是,Element对象本身便有Element.selcect的方法来实现查询,即内部调用DomQuery选取元素。这个简单的例子中,ExtStart.htm包含若干段落(<p>标签),没有一个是有ID的,而你想轻松地通过一次操作马上获取每一段,全体执行它们的动作,可以这样做:

// 每段高亮显示
Ext.select('p').highlight();

DomQuery的选取参数是一段较长的数组,其中包括W3C CSS3 Dom选取器、基本XPatch、HTML属性和更多,请参阅DomQuery API文档以了解这功能强大的库的细节。

响应事件
到这范例为止,我们所写的代码都是放在onReady中,即当页面加载后总会立即执行,功能较单一——这样的话,你便知道,如何响应某个动作或事件来执行你希望做的事情,做法是,先分配一个function,再定义一个event handler事件处理器来响应。我们由这个简单的范例开始,打开ExtStart.htm,编辑下列的代码:

Ext.onReady(function() {
 Ext.get('myButton').on('click', function(){
  alert("You clicked the button");
 });
});

加载好页面,代码依然会执行,不过区别是,包含alert()的function是已定义好的,但它不会立即地被执行,是分配到按钮的单击事件中。用浅显的文字解释,就是:获取ID为'myDottom'元素的引用,监听任何发生元素被单击的情况,并分配一个function,以准备任何单击元素的情况。

正路来说,Element.select也能做同样的事情,即作用在获取一组元素上。下一例中,演示了页面中的某一段落被单击后,便有弹出窗口:

Ext.onReady(function() {
 Ext.select('p').on('click', function() {
  alert("You clicked a paragraph");
 });
});

这两个例子中,事件处理的function均是简单几句,没有函数的名称,这种类型函数称为“匿名函数(anonymous function)”,即是没有名的的函数。你也可以分配一个有名字的event handler,这对于代码的重用或多个事件很有用。下一例等效于上一例:

Ext.onReady(function() {
 var paragraphClicked = function() {
  alert("You clicked a paragraph");
 }
 Ext.select('p').on('click', paragraphClicked);
});

到目前为止,我们已经知道如何执行某个动作。但当事件触发时,我们如何得知这个event handler执行时是作用在哪一个特定的元素上呢?要明确这一点非常简单,Element.on方法传入到even handler的function中(我们这里先讨论第一个参数,不过你应该浏览API文档以了解even handler更多的细节)。在我们之前的例子中,function是忽略这些参数的,到这里可有少许的改变,——我们在功能上提供了更深层次的控制。必须先说明的是,这实际上是Ext的事件对象(event object),一个跨浏览器和拥有更多控制的事件。例如,可以用下列的语句,恢复这个事件的指定的DOM节点:

Ext.onReady(function() {
 var paragraphClicked = function(e) {
  Ext.get(e.target).highlight();
 }
 Ext.select('p').on('click', paragraphClicked);
});

注意指定的是DOM节点,所以我们首先将其恢复成为适当的元素,然后执行欲完成的事件,这个例子中,我们看见段落是高亮显示的。

使用Widgets
(Widget原意为“小器件”,现指页面中UI控件)
除了我们已经讨论过的核心JavaScript库,现在的Ext亦包括了一系列的最前端的JavaScirptUI组件库。文本以一个最常用的widget为例子,作简单的介绍。

MessageBox
比起略为沉闷的“HelloWolrd”消息窗口,我们做少许变化,前面我们写的代码是,单击某个段落便会高亮显示,现在是单击段落,在消息窗口中显示段落内容出来。
在上面的paragraphClicked的function中,将这行代码:

Ext.get(e.target).highlight();

替换为:

var paragraph = Ext.get(e.target);
paragraph.highlight();
Ext.MessageBox.show({
 title: 'Paragraph Clicked',
 msg: paragraph.dom.innerHTML,
 width:400,
 buttons: Ext.MessageBox.OK,
 animEl: paragraph
});

这里有些新的概念讨论一下。在第一行中我们创建了一个局部变量(Local Variable)来保存某个元素的引用,即被单击的那个DOM节点(本例中,我们总是段落paragrah,事因我们已经定义该事件与<p>标签发生关联的了)。为什么要这样做呢?嗯...观察上面的代码,我们需要引用同一元素来高亮显示,在MessageBox中也是引用同一元素作为参数使用。
一般来说,多次重复使用同一值(Value)或对象,是一个不好的方式,所以,作为一个好的OOP开发者,应该是将其分配到一个局部变量中,反复使用这变量!

现在,观察MessageBox的调用,准备作为阐述新概念的演示用。乍一看,这像一连串的参数传入到方法中,但仔细看,这是一个非常特别的语法。实际上,传入到MessageBox.show的只有一个参数:一个Object literal,包含一组属性和属性值。在Javascript中,Object Literal是动态的,你可在任何时候用{和}创建一个典型的对象(object)。其中的字符由一系列的name/value组成的属性,属性的格式是[property name]:[property value]。在整个Ext中,你将会经常遇到这种模式的语法,因此你应该消耗掉这知识!
使用Object Literal的原因是什么呢?主要的原因是“韧性(flexibility)",随时可新增、删除属性,亦可不管顺序地插入。而方法不需要改变。这也是多个参数的情况下,为最终开发者带来不少的方便(本例中的MessageBox.show())。例如,我们说这儿的foo.action方法,有四个参数,而只有一个是你必须传入的。本例中,你想像中的代码可能会是这样的foo.action(null, null, null, 'hello').,如果那方法用Object Literal来写,却是这样, foo.action({ param4: 'hello' }),这更易用和易读。

Gird
Gird是Ext中人们最想先睹为快的Widgets之一,也是最流行之一。好,让我们看看怎么轻松地创建一个Gird并运行。用下列代码替换ExtStart.js中全部语句:

Ext.onReady(function() {
    var myData = [
        ['Apple',29.89,0.24,0.81,'9/1 12:00am'],
        ['Ext',83.81,0.28,0.34,'9/12 12:00am'],
        ['Google',71.72,0.02,0.03,'10/1 12:00am'],
        ['Microsoft',52.55,0.01,0.02,'7/4 12:00am'],
        ['Yahoo!',29.01,0.42,1.47,'5/22 12:00am']
    ];

    var ds = new Ext.data.Store({
        proxy: new Ext.data.MemoryProxy(myData),
        reader: new Ext.data.ArrayReader({id: 0}, [
            {name: 'company'},
            {name: 'price', type: 'float'},
            {name: 'change', type: 'float'},
            {name: 'pctChange', type: 'float'},
            {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
    ])
    });
    ds.load();

    var colModel = new Ext.grid.ColumnModel([
        {header: "Company", width: 120, sortable: true, dataIndex: 'company'},
        {header: "Price", width: 90, sortable: true, dataIndex: 'price'},
        {header: "Change", width: 90, sortable: true, dataIndex: 'change'},
        {header: "% Change", width: 90, sortable: true, dataIndex: 'pctChange'},
        {header: "Last Updated", width: 120, sortable: true, 
        renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
    ]);

    var grid = new Ext.grid.Grid('grid-example', {ds: ds, cm: colModel});
        grid.render();
        grid.getSelectionModel().selectFirstRow();
    });

这看上去很复杂,但实际上加起来,只有七行代码。第一行创建数组并作为数据源。实际案例中,你很可能从数据库、或者WebService那里得到动态的数据。接着,我们创建并加载data store, data store将会告诉Ext的底层库接手处理和格式化这些数据。接着,我们定义一个column模型,用来轻松地调配Gird的每一列参数。最后我们生成这个Gird,传入data store和column模型两个对象,进行渲染并选好第一行。不是太困难吧?如果一切顺利,搞掂之后你会看到像这样的:

当然,你可能对这段代码的某些细节,并不完全掌握其中的含义(像MemoryProxy究竟是什么?)但先不要紧,这个例子的目的是告诉你,用少量的代码,创建一个富界面的多功能的UI组件而已——这是完全可能的,更多细节的内容,留给读者你自己学习吧。这儿有许多学习Grid的资源。Ext Grid教程、交叉Gird演示和Grid API文档。

还有更多的..
这只是冰山一角。还有一打的UI Widgets可以供调用,如 layouts, tabs, menus, toolbars, dialogs, tree view等等。请参阅API文档中范例演示。

使用Ajax
在弄好一些页面后,你已经懂得在页面和脚本之间的控制原理(interact)。接下来,你想知道的是,怎样与后台服务器(remote server)交换数据,常见的是从数据库加载数据(load)或是保存数据(save)到数据库中。通过JavaScript异步无刷新交换数据的这种方式,就是所谓的Ajax。Ext内建卓越的Ajax支持,例如,一个普遍的用户操作就是,异步发送一些东西到服务器,然后,UI元素根据回应(Response)作出更新。这是一个包含text input的表单,一个div用于显示消息(注意,你可以在ExtStart.html中加入下列代码,但这必须要访问服务器):

<div id="msg" style="visibility: hidden"></div> 
Name: 
<input type="text" id="name" /><br /> 
<input type="button" id="oKButton" value="OK" />

接着,我们加入这些处理交换数据的JavaScript代码到文件ExtStart.js中(用下面的代码覆盖):

Ext.onReady(function(){
 Ext.get('oKButton').on('click', function(){
  var msg = Ext.get("msg");
   msg.load({
   url: [server url], //换成你的URL
   params: "name=" + Ext.get('name').dom.value,
   text: "Updating"
  });
  msg.show();
 });
});

这种模式看起来已经比较熟悉了吧!先获取按钮元素,加入单击事件的监听。在事件处理器中(event handler),我们使用一个负责处理Ajax请求、接受响应(Response)和更新另一个元素的Ext内建类,称作UpdateManager。UpdateManager可以直接使用,或者和我们现在的做法一样,通过Element的load方法来访问(本例中该元素是“msg“的div)。当使用Element.load方法,请求(request)会被加工处理后发送,等待服务器的响应(Response),来自动替换元素的innerHTML。简单传入服务器url地址,加上字符串参数,便可以处理这个请求(本例中,参数值来自“name”元素的value),而text值就是请求发送时提示的文本,完毕后显示那个msg的div(因为开始时默认隐藏)。当然,和大多数Ext组件一样,UpdateManager有许多的参数可选,不同的Ajax请求有不同的方案。而这里仅演示最简单的那种。

PHP

<? 
if(isset($_GET['name'])) 
{  
  echo 'From Server: '.$_GET['name']; 
}
?>

ASP.Net

protected void Page_Load(object sender, EventArgs e)

  if (Request["name"!= null
  {  
     Response.Write(
"From Server: " + Request["name"]);  
     Response.End(); 
  }

Cold Fusion

<cfif StructKeyExists(url, "name")> 
<cfoutput>From Server: #url.name#</cfoutput>
</cfif>

最后一个关于Ajax的谜题就是,服务器实际处理请求和返回(Resposne)是具体过程。这个过程会是一个服务端页面,一个Servlet,一个Http处理器,一个WebService,甚至是Perl或CGI脚本,即任何一个服务器都可以处理http请求。无法预料的是,服务器返回什么是服务器的事情,无法给一个标准的例子来覆盖所有的可能性。(这段代码输出刚才我们传入'name'的那个值到客户端,即发送什么,返回什么)。

使用Ajax的真正挑战,是需经过适当处理过的手工代码,并相应格式化为服务端可用接受的数据结构。有几种格式供人们选择(最常用为JSON/XML)。正因Ext是一种与服务器中立的语言,使得其它特定语言的库亦可用于Ext处理Ajax服务。只要页面接受到结果是合适的数据格式,Ext绝不会过问服务器的事情!要全面讨论这个问题,已超出本文的范围。推荐正在使用Ajax的您,深入阅读Ext Ajax教程。