翻译|其它|编辑:郝浩|2008-01-07 09:31:22.000|阅读 1288 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
一.纯数据输出
1.早在看 ActionScript 的时候便接触到了这种写法,直到 ajax 很火的时候,才知道这种格式叫 json.
json 数据格式是供前端 javascript 进行操作的暂时性的数据格式,由于 javascript 语言的原因,访问 json 数据非常方便,灵活.本来由后端负责产生 Ui 的,现在全部由 javascript 操作 dom 来产生.避免重复,请大家参考此文 JSON 简介,同时推荐看看 IBM 的掌握 Ajax 系列.
为了产生 json 格式的数据,asp.net ajax 框架提供了一个 JavaScriptSerializer 类用于将数据转换成 json.
分析下此做法的优点与缺点
优点:
1.后台传输数据量会比较小,减轻服务器压力
2.前端操作非常灵活,可以做很多事情
3.适用于交互性比较强的应用.
缺点:
1.必须要操作 dom 才能产生 ui,无法与美工配合工作,需要熟悉 javascript 和 dom 的人来参与
2.大数据量下,前端 javascript 对 json 数据的解析和 dom 的生成会明显减慢.
豪无疑问的,直接产生 html 比解析要速度来的快.这是一点,要是在后端直接输出 html 的话,可能会由于产生的字符串太多,直接拖垮 IE,挂掉.
我想唯一的做法就是尽量避免大数据量,这便要看大家的创意了,还有就是输出 json,然后对 json 分批操作解析,这样也会有所缓解.
3.灵活的同时,降低了通用性(我有一个需求,某一天我用 ajax 用到我不想用了,我想回到传统的网页上去,啊噢,这种开发模式做不到)
4.前端开发人员必须了解 json 数据格式
二.与 Ui 一起输出
这是我们一贯的做法,如 asp.net ajax 中的 UpdatePanel,其会去后端请求其 Panel 中所有的 UI,然后返回给前端,前端不需要解析,直接得到数据输出便可.
分析下此做法的优点与缺点
优点:
1.可以与美工配合,避免动态产生 dom 的错误
2.前端开发人员不再需要了解后端传回什么数据格式,直接输出
3.复用性比较强,可以同时满足 ajax 和传统网页的浏览模式
缺点:
1.大大降低了数据的交互性,前端有时候无法得到想要的对象,只能依赖于后端产生的 html 数据.
2.后端数据传输量稍微变大,不过影响不大.(相对而言,后端把对象解析成 json 格式需要时间,前端解析 json 数据也是需要时间的,主要的速度瓶颈还是在数据库连接访问这里)
三.选择你想要的开发模式
上面两种模式没有谁好谁不好之说,追求效率的人可能会选第一种,这种模式与语言无端,可以套用在 php,jsp,asp,都可以.
第二种开发模式比较适合 asp.net,为什么呢?因为 asp.net 本身便存在着控件这一用法,而且效率并不低.
大家可以先看看老赵这篇技巧:使用 User Control 做 HTML 生成
四.我的做法
1.我有一个白老鼠程序,自己写的 blog 程序,我会在其上面应用一些新技术,然后思考一些问题.
初期阶段,我用 ajax 去加载 UserControl 中产生的 html,开始感觉很好.后来我又想做成传统的网页形式,去掉 ajax 的加载方式,所以,我需要这么写(很高兴,终于看到代码了)
<%@ Page ContentType="text/html" Language="C#" EnableViewState="true" MasterPageFile="~/Templete.Master" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="NLBS._default" Title="无标题页" %>
<%@ Register Src="Control/content.ascx" TagName="content" TagPrefix="uc11" %>
<asp:Content ID="Content1" runat="server" contentplaceholderid="ContentPlaceHolder1">
<uc11:content ID="content" runat="server" />
</asp:Content>content用户控件,用于显示文章列表.
然后我做着做着...看到别人的 blog 有 ajax 应用,那个酷啊,而且我的虚拟主机便宜,访问数据速度慢.我又想把它换成 ajax 模式爽一把(我的天),或者说我想随意变换数据的加载模式.这种模式采用 json 数据格式的话根本无法满足需求,修改太大.怎么办怎么办?
由于本人偷偷的看了下 ComponentArt 的 CallBack 控件的源码(其实很早就看了),所以本人也仿照其做了一个自己的 CallBack 控件.我需要一个容器放 content 用户控件,然后再异步加载.现在现实的问题,这个页面便是 content 用户控件的容器.我们通过改变 url 参数来加载不同数据.(控件呈现是在 Render 方法中实现)
看下面代码.
singleArticle_param=true&ID=70 这样的 url 来获取 content 数据
protected override void Render(HtmlTextWriter writer)
{
//得到一个 querystring 参数
string[] requestParams = this.GetCallbackParameters();
if (requestParams != null && requestParams.Length > 0)
{
//输出控件数据
this.HandleCallback(requestParams);
return;
}
base.Render(writer);
}
private void HandleCallback(string[] arParams)
{
try
{
//try render the HtmlTextWriter
StringWriter oStringWriter = new StringWriter();
HtmlTextWriter oWriter = new HtmlTextWriter(oStringWriter, string.Empty);
CallBackEventArgs oArgs = new CallBackEventArgs(oWriter);
oArgs.Parameter = arParams[0];
oArgs.Parameters = arParams;
this.OnCallback(oArgs);
oWriter.Close();
Context.Response.Clear();
Context.Response.Write(oStringWriter.ToString().Trim());
}
catch (Exception ex)
{
//render ther error
this.HandleCallbackError(ex);
}
try
{
Context.Response.End();
}
catch { }
}
小心:如果此时,你在本页面来请求 content 用户控件,呈现出来的会是2个 content 控件的 ui.所以我们需要另建一个空白页面。使用此模式你不旦可以加载用户控件,同时也可以加载 asp.net 的内置控件。
2.ajax 数据加载与传统 url 同在
我要访问一篇:博客园的一篇随笔,如http://www.cnblogs.com/JeffreyZhao/archive/2007/12/30/usercontrol_as_an_template.html,那在 ajax 模式下,我们不是要去掉此 url,换成 javascript 的一个数据请求函数?我们可以用 preventDefault()方法把链接给屏蔽掉,或者用 stopPropagation()方法把事件给阻截下来.(上面两个方法都是 firefox 下的方法,ie 也有此功能方法,asp.net ajax 框架进行了封装)
三.ajax 加载用户控件在 MVC 中的应用
相信有部分人已经在开始研究 asp.net ajax 了,请看此文 Ajax with the ASP.NET MVC Framework。作者写了一个 Script#,所以其前端 javascript 代码也是通过用其生成了。我们不管前端,我们只来谈加载方式。让我们看一个 Control 中的 Add 方法
[ControllerAction]
public void Add(string name) {
Task task = null;
if (String.IsNullOrEmpty(name) == false) {
task = _taskDB.AddTask(name);
}
if (IsAjaxRequest) {
if (task != null) {
RenderView("TaskView", task);
}
}
else {
if (task != null) {
RedirectToAction("List");
}
else {
Dictionary<string, object> viewData = new Dictionary<string, object>();
viewData["Tasks"] = _taskDB.GetTasks();
viewData["ShowAddTaskError"] = true;
RenderView("List", viewData);
}
}
}
RenderView 会呈现控件的 ui,(page,usercontrol 都是控件).此代码我们可以看到如果用 ajax 模式,则会转到 TaskView 用户控件这里,其本质还是输出 UserControl 的数据,然后前端得到数据并呈现。但这种做法个人认为不好,每个 Action 都需要去写 if else 的语句。我想应该分离出来。
四。控件 Id 与 Name
上次发的随笔篇幅太小,被刷了下来,希望这次没这么倒霉。但我还是希望大家看看修改服务器控件的 ID 和 Name,解决大家的痛,我们是有办法解决。最后阿门,愿MVC模式与控件同在,呵呵。我可不想 <% %> 横行霸道。
五.让数据绑定控件代码更漂亮
让我们来看个 Repater 控件的传统应用
<asp:Repeater ID="normalArticleList" runat="server">
<ItemTemplate>
<div class="textbox">
<div class="textbox-title">
<h4><a onclick="<%# urlFormats.ArticleConent(Convert.ToInt32(Eval("ArticleID").ToString()))%>" href="#"><span runat=server visible=<%# Eval("IsTop")%>>[置顶]</span><%# Eval("Title")%></a>
</h4>
<div class="textbox-label">
[
<%# Eval("PostTime")%>
| <%=lang["author"]%>: <a onclick="<%# urlFormats.UserDetail(int.Parse(Eval("AuthorID").ToString()))%>" href="#"><%# Eval("Author") %></a> ]</div>
</div>
<div class="textbox-content">
<%# GetContent(Eval("Content0").ToString(), Eval("Content1").ToString())%><%--<%# Eval("Content1") %>--%></div>
<div class="textbox-bottom">
<asp:PlaceHolder ID="actionLinkPanel" runat="server">
<a href="articleManage.aspx?act=edit&id=<%# Eval("ArticleID") %>" title="<%=lang["edit"]%>">
<img src="/styles/default/images/icon_edit.gif" alt="<%=lang["edit"]%>" />
</a>| <a href="/articleManage.aspx?act=delete&id=<%# Eval("ArticleID") %>" title="<%=lang["delete"]%>">
<img src="/styles/default/images/icon_del.gif" alt="<%=lang["delete"]%>" /></a> |
</asp:PlaceHolder>
<a onclick="<%# urlFormats.ArticleCategoryUrl(Convert.ToInt32(Eval("categoryID").ToString()))%>" href="#"><%=lang["category"]%>:<%# Eval("CategoryName")%></a> | <a href="?id=<%# Eval("ArticleID") %>"><%=lang["permalink"]%></a> | <a onclick="<%# urlFormats.ArticleConent(Convert.ToInt32(Eval("ArticleID").ToString()))%>" href="#commentbox" title="评论"><%=lang["comments"]%>:<%# Eval("CommentCount") %></a> | <a href="#"><%=lang["trackbacks"]%>:<%# Eval("TrackbackCount") %></a> | <%=lang["views"]%>:<%# Eval("ViewCount") %>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
很好的完成了工作,通过数据绑定语法。可这界面太烦,字段多,金黄色语法就更多,那个心里烦啊,我们还是无法逃避这个问题,而且我们偶尔还会对一些字段进行逻辑判断。我的做法:用 Literal 控件代替绑定语法,在 ItemDataBound 事件中完成数据的填充。现在前端
<asp:Repeater ID="normalArticleList" runat="server">
<ItemTemplate>
<div class="textbox">
<div class="textbox-title">
<asp:Literal ID="articleTitle" runat="server"></asp:Literal>
<div class="textbox-label">
<asp:Literal ID="articleLabel" runat="server"></asp:Literal>
</div>
</div>
<div class="textbox-content">
<asp:Literal ID="articleContent" runat="server"></asp:Literal>
</div>
<div class="textbox-bottom">
<asp:Literal ID="articleBottom" runat="server"></asp:Literal>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
后端
void normalArticleList_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Article item = (Article)e.Item.DataItem;
Literal title = (Literal)e.Item.FindControl("articleTitle");
Literal articleLabel = (Literal)e.Item.FindControl("articleLabel");
Literal articleContent = (Literal)e.Item.FindControl("articleContent");
Literal articleBottom = (Literal)e.Item.FindControl("articleBottom");
title.Text = RenderNormalTitle(item);
articleLabel.Text = RenderNormalLabel(item);
articleContent.Text = RenderNormalContent(item);
articleBottom.Text = RenderNormalBottom(item);
}
}
这样的写法会漂亮很多,而且数据绑定是通过反射机制的,听过会损失性能。。。
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:.NET博客园