仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1231|回复: 10
打印 上一主题 下一主题

[学习教程] ASP.NET网页设计asp.net MVC代码示例:体系设置(View复用示例)仓酷云

[复制链接]
不帅 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-18 11:17:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
一般的指的.net就是跟net网页编程相对的那种,主要是做企业级应用的。你如果想学这个,主要就是学C#和数据库。(ASP.NET好像很重要的,应该也要学的,ASP.NET上好像可以结合VB和C#等多种语言,但是微软主推C#)目次(?)[-]

  • 功效简介
  • 开辟历程

    • 第一步:开辟出StoryTreeType部分的Model代码
    • 第二步:完成StoryTreeType的View
    • 第三步:为StatusList的Model部分“打草稿”
    • 第四步:将StoryTreeType和StatusList改写为一个基类的派生类
    • 第五步:将处置StoryTreeType的View改写为同时能够处置StatusList的

      • 先启示一个第二疆场:
      • 一点点把StoryTreeType1中的StoryTreeType的影子抹失落

    • 第六步:到场对StatusList的处置

  • 后续及总结

    • 后续
    • 总结

功效简介

终极功效如图:

下面一行两张图,是火星人的用户故事树设置界面,在每一个用户故事的前面都有一个按钮(悬停可见),点击后呈现操纵菜单,个中一部分是新建上级故事菜单。
若用户选择左边,菜单上只包含一个项目“通用故事”;若选择右边,则包含良多故事(受以后故事范例的束缚,这个对照庞大今后再说)。
这段代码,等一下将会呈现关头字“StoryTreeType”,左边叫做“Simple”(复杂树),右边叫做“Leveled”(品级树)。
上面一行两张图,是火星人的形态链设置界面,在下面提到的操纵菜单上,除能新建故事以外,还能将以后故事转移到别的一个形态。
若用户选择左边,菜单上只包含与开辟相干的形态(新建-待开辟-开辟中-开辟终了-部署终了);做选择右边,则会呈现一切形态(新建后有审批等环节,而部署历程也包含多个形态)。
这段代码,等一下将会呈现关头字“StatusList”,左边叫做“DevelopmentOnly”(仅包括研发形态),右边叫做“All”(一切)。
很明显,不但是这两排界面很相似,这四个界面和面前的模子都十分邻近,上面谈谈怎样以最小代码完成这个设置功效。
开辟历程

Controller部分的代码略过,重点看Model和View的封装。
第一步:开辟出StoryTreeType部分的Model代码

[csharp]

  • publicpartialclassProduct
  • {
  • publicconststringUserDefaultProductIDKey="DefaultProductID";

  • //StoryTreetype(Simple,Leveled,etc.)
  • publicconststringStoryTreeTypeKey="StoryTreeType";
  • publicenumStoryTreeTypes
  • {
  • Simple=0,
  • Leveled=1
  • }

  • publicstaticreadonlyStoryTreeTypes[]StoryTreeTypeValues={StoryTreeTypes.Simple,StoryTreeTypes.Leveled};
  • publicstaticreadonlystring[]StoryTreeTypeTexts={"缺省(利用复杂父子干系构成故事树)","利用体系界说的故事品级构成故事树"};

  • publicStoryTreeTypesStoryTreeType
  • {
  • get{return(StoryTreeTypes)Config.ReadValueAsInt(StoryTreeTypeKey,"$"+ID);}
  • }

  • publicstringStoryTreeTypeText
  • {
  • get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StoryTreeTypeKey)];}
  • }
  • }
  1. publicpartialclassProduct{publicconststringUserDefaultProductIDKey="DefaultProductID";//StoryTreetype(Simple,Leveled,etc.)publicconststringStoryTreeTypeKey="StoryTreeType";publicenumStoryTreeTypes{Simple=0,Leveled=1}publicstaticreadonlyStoryTreeTypes[]StoryTreeTypeValues={StoryTreeTypes.Simple,StoryTreeTypes.Leveled};publicstaticreadonlystring[]StoryTreeTypeTexts={"缺省(利用复杂父子干系构成故事树)","利用体系界说的故事品级构成故事树"};publicStoryTreeTypesStoryTreeType{get{return(StoryTreeTypes)Config.ReadValueAsInt(StoryTreeTypeKey,"$"+ID);}}publicstringStoryTreeTypeText{get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StoryTreeTypeKey)];}}}
复制代码
注重这段代码里边有一个叫做Config的类,它卖力把分歧的设置写到数据库中的一个大众内外边,因而为了完成这个功效,我们其实不必要会商数据存储成绩。
这得益于火星人之前已封装好的浩瀚功效。
第二步:完成StoryTreeType的View

注重上面的代码,已将StroyTreeType的两品种型举行了Foreach轮回处置,而不是写逝世在里边。
偶然候会以为只要两种,还做甚么轮回,但假如不轮回就必要两段很靠近的代码,调试和保护都很费力。并且一旦养成这类习气,很简单把全部软件都写散了。
[csharp]

  • @foreach(vartypeinProduct.StoryTreeTypeValues)
  • {
  • <tdstyle="border:none;">
  • <divclass="help-sample">
  • <table>
  • <tr>
  • <tdstyle="border:none;width:500px;">
  • @MFCUI.Image("","/Products/StoryTree/Index16.png")<b>@Product.StoryTreeTypeTexts[(int)type]</b>
  • @if(Model.StoryTreeType==type)
  • {
  • <b>[以后设置]</b>
  • }
  • else
  • {
  • @MFCUI.Link("[启用]","/MFC/Configs/AjaxSet?key="+Product.StoryTreeTypeKey+"&value="+(int)type+"&user=$"+Model.ID,returnTo:this)
  • @:
  • }
  • <table>
  • <tr>
  • <tdstyle="border:none;width:200px;">
  • @RenderPage("~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeTypes/_"+Model.StoryTreeType+".cshtml")
  • </td>
  • <tdstyle="border:none;">
  • @MFCUI.Image("","/Products/Products/ManagementMethods/_"+type+"Example.png")<br/><br/>
  • </td>
  • </tr>
  • </table>
  • </td>
  • </tr>
  • </table>
  • </div>
  • </td>
  • }
  1. @foreach(vartypeinProduct.StoryTreeTypeValues){<tdstyle="border:none;"><divclass="help-sample"><table><tr><tdstyle="border:none;width:500px;">@MFCUI.Image("","/Products/StoryTree/Index16.png")<b>@Product.StoryTreeTypeTexts[(int)type]</b>@if(Model.StoryTreeType==type){<b>[以后设置]</b>}else{@MFCUI.Link("[启用]","/MFC/Configs/AjaxSet?key="+Product.StoryTreeTypeKey+"&value="+(int)type+"&user=$"+Model.ID,returnTo:this)@:}<table><tr><tdstyle="border:none;width:200px;">@RenderPage("~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeTypes/_"+Model.StoryTreeType+".cshtml")</td><tdstyle="border:none;">@MFCUI.Image("","/Products/Products/ManagementMethods/_"+type+"Example.png")<br/><br/></td></tr></table></td></tr></table></div></td>}
复制代码
注重
1.这段代码里边有一个叫做“/MFC/Configs/AjaxSet?..."的挪用,这个挪用将间接完成设置事情(写进数据库),并立即革新以后页(注重有个“returnTo:this,是火星人中回到以后页的封装)。
2.最下面的题目(“缺省(利用复杂父子干系构成故事树)”和“利用体系界说的故事品级构成故事树”)、图片(最上面一个@MFCUI.Image())都是在这个页面写出来的
3.两个RenderPage用于显现“长处”“弱点”“倡议”这些不同对照年夜的笔墨,分离存储在两个文件里边,文件名是在RenderPage里边用Model.StoryTreeType拼装出来的。
2和3标明了在MVC的View中的几个很主要的封装准绳:
A.类似的部分必定要For轮回出来在一个View经由过程拼接中办理
B.稍微分歧的参数利用变量拼接出来
C.图片、PartialView的定名要与变量对应,如许便利拼接
D.最年夜的分歧,利用PartialView来处置。
第三步:为StatusList的Model部分“打草稿”

(写这篇博客的时分,我的代码方才写到这里,为了能拷贝到一点“草稿代码”,不等编码失掉考证就入手下手写了)
做了良多年的封装,感到最疾速的办法,仍旧是探索性封装也就是先写出一个部分(如下面的StoryTreeType),然后拷贝别的一个类似的部分(以下面的StatusList),然后察看其类似点和分歧点,然后才举行封装。
与间接在开首就计划封装比拟,这类办法对照简单进修和承受,对职员的请求也绝对较低。自己编程这么多年,仍是没掌控在一切情形下都面临空屏幕间接先写底层,然后派生出子类。
注重StatusList部分的代码是间接拷贝、粘贴、修正出来的,它们是“草稿代码”,用来察看封装要点的。往后将被代替。
[csharp]

  • publicpartialclassProduct
  • {
  • publicconststringUserDefaultProductIDKey="DefaultProductID";

  • //StoryTreetype(Simple,Leveled,etc.)
  • publicconststringStoryTreeTypeKey="StoryTreeType";
  • publicenumStoryTreeTypes
  • {
  • Simple=0,
  • Leveled=1
  • }

  • publicstaticreadonlyStoryTreeTypes[]StoryTreeTypeValues={StoryTreeTypes.Simple,StoryTreeTypes.Leveled};
  • publicstaticreadonlystring[]StoryTreeTypeTexts={"缺省(利用复杂父子干系构成故事树)","利用体系界说的故事品级构成故事树"};

  • publicStoryTreeTypesStoryTreeType
  • {
  • get{return(StoryTreeTypes)Config.ReadValueAsInt(StoryTreeTypeKey,"$"+ID);}
  • }

  • publicstringStoryTreeTypeText
  • {
  • get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StoryTreeTypeKey)];}
  • }

  • //Statuslisttype(DevelopmentOnly,All,etc.)
  • publicconststringStatusListTypeKey="StatusListType";
  • publicenumStatusListTypes
  • {
  • DevelopmentOnly=0,
  • Allowed=1
  • }

  • publicstaticreadonlyStatusListTypes[]StatusListTypeValues={StatusListTypes.DevelopmentOnly,StatusListTypes.Allowed};
  • publicstaticreadonlystring[]StatusListTypeTexts={"缺省(只显现开辟相干的形态)","利用用户自界说的同意形态"};

  • publicStatusListTypesStatusListType
  • {
  • get{return(StatusListTypes)Config.ReadValueAsInt(StatusListTypeKey,"$"+ID);}
  • }

  • publicstringStatusListTypeText
  • {
  • get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StatusListTypeKey)];}
  • }
  • }
  1. publicpartialclassProduct{publicconststringUserDefaultProductIDKey="DefaultProductID";//StoryTreetype(Simple,Leveled,etc.)publicconststringStoryTreeTypeKey="StoryTreeType";publicenumStoryTreeTypes{Simple=0,Leveled=1}publicstaticreadonlyStoryTreeTypes[]StoryTreeTypeValues={StoryTreeTypes.Simple,StoryTreeTypes.Leveled};publicstaticreadonlystring[]StoryTreeTypeTexts={"缺省(利用复杂父子干系构成故事树)","利用体系界说的故事品级构成故事树"};publicStoryTreeTypesStoryTreeType{get{return(StoryTreeTypes)Config.ReadValueAsInt(StoryTreeTypeKey,"$"+ID);}}publicstringStoryTreeTypeText{get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StoryTreeTypeKey)];}}//Statuslisttype(DevelopmentOnly,All,etc.)publicconststringStatusListTypeKey="StatusListType";publicenumStatusListTypes{DevelopmentOnly=0,Allowed=1}publicstaticreadonlyStatusListTypes[]StatusListTypeValues={StatusListTypes.DevelopmentOnly,StatusListTypes.Allowed};publicstaticreadonlystring[]StatusListTypeTexts={"缺省(只显现开辟相干的形态)","利用用户自界说的同意形态"};publicStatusListTypesStatusListType{get{return(StatusListTypes)Config.ReadValueAsInt(StatusListTypeKey,"$"+ID);}}publicstringStatusListTypeText{get{returnStoryTreeTypeTexts[Config.ReadValueAsInt(StatusListTypeKey)];}}}
复制代码
第四步:将StoryTreeType和StatusList改写为一个基类的派生类

说假话,这个改写历程失利了,5分钟后发明,由于每行代码都有分歧的地方,即便改写乐成,初始化代码不比这些代码少。
并且还要冒着保持enum的风险,以是停止了改写企图。
第五步:将处置StoryTreeType的View改写为同时能够处置StatusList的

良多老手在这个时分大概会间接入手下手下手,但上面先容一下一个小技能:
1.先启示一个第二疆场:

[html]

  • <tableclass="noborder">
  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType.cshtml")
  • </tr>
  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType1.cshtml",Product.StoryTreeTypeValues)
  • </tr>
  • </table>
  1. <tableclass="noborder"><tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType.cshtml")</tr><tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType1.cshtml",Product.StoryTreeTypeValues)</tr></table>
复制代码
上面的_StoryTreeType1.cshtml是拷贝出来的,将显现在本来页面的上面,如许能够修正的同时能够察看新旧代码及其效果。
2.一点点把StoryTreeType1中的StoryTreeType的影子抹失落

所谓影子,就是间接写着“StoryTreetype”而非一个变量的中央。固然,每抹失落一个,就要多传进一个参数。这里用的是PageData[]参数(MVC3新呈现的)。
注重抹一点测试一下,碰到成绩越早越好。
最初View的外部酿成(注重完整看不就任何和StoryTreeType相干的陈迹了):
[csharp]

  • @foreach(varcurrentConfiginPageData[0])
  • {
  • <tdstyle="border:none;">
  • <divclass="help-sample">
  • <table>
  • <tr>
  • <tdstyle="border:none;width:500px;">
  • @MFCUI.Image("",PageData[1])<b>@PageData[2][(int)currentConfig]</b>
  • @if(PageData[3]==currentConfig)
  • {
  • <b>[以后设置]</b>
  • }
  • else
  • {
  • @MFCUI.Link("[启用]","/MFC/Configs/AjaxSet?key="+PageData[4]+"&value="+(int)currentConfig+"&user=$"+Model.ID,returnTo:this)
  • @:
  • }
  • <table>
  • <tr>
  • <tdstyle="border:none;width:200px;">
  • @RenderPage(PageData[5])
  • </td>
  • <tdstyle="border:none;">
  • @MFCUI.Image("",Page[6]+"_"+currentConfig+".png")<br/><br/>
  • </td>
  • </tr>
  • </table>
  • </td>
  • </tr>
  • </table>
  • </div>
  • </td>
  • }
  1. @foreach(varcurrentConfiginPageData[0]){<tdstyle="border:none;"><divclass="help-sample"><table><tr><tdstyle="border:none;width:500px;">@MFCUI.Image("",PageData[1])<b>@PageData[2][(int)currentConfig]</b>@if(PageData[3]==currentConfig){<b>[以后设置]</b>}else{@MFCUI.Link("[启用]","/MFC/Configs/AjaxSet?key="+PageData[4]+"&value="+(int)currentConfig+"&user=$"+Model.ID,returnTo:this)@:}<table><tr><tdstyle="border:none;width:200px;">@RenderPage(PageData[5])</td><tdstyle="border:none;">@MFCUI.Image("",Page[6]+"_"+currentConfig+".png")<br/><br/></td></tr></table></td></tr></table></div></td>}
复制代码
而接口也酿成:
[html]

  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType.cshtml")
  • </tr>
  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType1.cshtml",
  • Product.StoryTreeTypeValues,"/Products/StoryTree/Index16.png",Product.StoryTreeTypeTexts,Model.StoryTreeType,Product.StoryTreeTypeKey,
  • "~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeType/_"+Model.StoryTreeType+".cshtml",
  • "/Products/Products/ManagementMethods/")
  • </tr>
  1. <tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType.cshtml")</tr><tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethods/_StoryTreeType1.cshtml",Product.StoryTreeTypeValues,"/Products/StoryTree/Index16.png",Product.StoryTreeTypeTexts,Model.StoryTreeType,Product.StoryTreeTypeKey,"~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeType/_"+Model.StoryTreeType+".cshtml","/Products/Products/ManagementMethods/")</tr>
复制代码
注重看上面“第二疆场”呈现了良多输出参数。
从表面看,高低两个View的显现效果完整不异(就不贴图了)。
第六步:到场对StatusList的处置

删除第一个tr的代码,拷贝出来一个处置StatusListType的tr,并慢慢修正使之能够事情:
[csharp]

  • <tableclass="noborder">
  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethod/_StoryTreeType1.cshtml",
  • Product.StoryTreeTypeValues,"/Products/StoryTree/Index16.png",Product.StoryTreeTypeTexts,Model.StoryTreeType,Product.StoryTreeTypeKey,
  • "~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeType/",
  • "/Products/Products/ManagementMethod/StoryTreeType/")
  • </tr>
  • <tr>
  • @RenderPage("~/Areas/Products/Views/Products/SetManagementMethod/_StoryTreeType1.cshtml",
  • Product.StatusListTypeValues,"/MFC/Statuses/Index16.png",Product.StatusListTypeTexts,Model.StatusListType,Product.StatusListTypeKey,
  • "~/Areas/DLC/Views/Products/ManagementMethod/StatusListType/",
  • "/Products/Products/ManagementMethod/StatusListType/")
  • </tr>
  • </table>
  1. <tableclass="noborder"><tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethod/_StoryTreeType1.cshtml",Product.StoryTreeTypeValues,"/Products/StoryTree/Index16.png",Product.StoryTreeTypeTexts,Model.StoryTreeType,Product.StoryTreeTypeKey,"~/Areas/DLC/Views/Products/ManagementMethod/StoryTreeType/","/Products/Products/ManagementMethod/StoryTreeType/")</tr><tr>@RenderPage("~/Areas/Products/Views/Products/SetManagementMethod/_StoryTreeType1.cshtml",Product.StatusListTypeValues,"/MFC/Statuses/Index16.png",Product.StatusListTypeTexts,Model.StatusListType,Product.StatusListTypeKey,"~/Areas/DLC/Views/Products/ManagementMethod/StatusListType/","/Products/Products/ManagementMethod/StatusListType/")</tr></table>
复制代码
有几个小技能:
1.修正过程当中,应当修正一个参数就检察一下是不是还事情。
2.优先修正那些不太会招致毛病的数据,好比能够先修正"/MFC/Statuses/Index16.png",Product.StatusListTypeTexts这两个参数,由于他们是笔墨,基础上不会招致毛病。
看看最初了局(由于短少两个图片,以是屏幕显现有成绩):

后续及总结

后续

做完这些,_StoryTreeType1.cshtml这个文件名已不当了,由于它能够1行代码完成任何体系设置(包括一个题目,多少可选项,一组形貌,一张图片),以是下一步必要修正它的名字,而且放到符合的中央。
不外就我们本人的习气而言,我们会先修改名字,然后就放在本来利用它的中央。直到下一次真正被从头利用,再商议放在甚么中央符合。
这句话的官方说法叫做“Useitbeforereusingit“,假如它如今就管这四个界面,就让它好好管着,等往后再说。
总结

全部历程包含写作本博客,约莫耗时2小时。
大概有人会问:不外就是4个页面嘛,就是拷贝粘贴,也用不了1个小时啊,为何要这么费力?
有这么几个缘故原由:
1.将来我们约莫会有20多个如许的设置页面,按下面先容的封装,每天生一页只必要在View中增加一行代码。
2.因为我们还没有美术职员,以是将来大概会修改页面效果,而这些页面都必要坚持不异的作风。
3.将来手艺上大概也会做一些修改,好比谁人Config,这些修改都不但愿往修正良多代码。
实在,全部火星人的产物,就是在这类积木代码中发生的,有良多意想不到的中央都是只需1~2行代码就可以挪用出来(故事树、构造布局图、燃尽图、一切菜单(每一个菜单都是提早加载的)……)
这类习气一旦养成了,代码就会愈来愈简练,而编写历程也愈来愈复杂。
有专家说:net网页编程不是跨平台,net网页编程就是平台,这很好的定义了net网页编程的特点。有了net网页编程,你只需要等待net网页编程平台在新平台上移植。这还不错吧!只是,net网页编程不是一个平台,而是多个平台。你需要在这个net网页编程平台移植到另一个net网页编程平台。
因胸联盟 该用户已被删除
沙发
发表于 2015-1-19 20:02:12 | 只看该作者
网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项!
小女巫 该用户已被删除
板凳
发表于 2015-1-24 13:41:19 | 只看该作者
众所周知,Windows以易用而出名,也因此占据不少的服务器市场。
愤怒的大鸟 该用户已被删除
地板
发表于 2015-1-26 21:24:15 | 只看该作者
我觉得什么语言,精通就好,你要做的就是比其他80%的人都厉害,你就能得到只有20%的人才能得到的高薪。
柔情似水 该用户已被删除
5#
发表于 2015-2-4 20:32:44 | 只看该作者
网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项!
山那边是海 该用户已被删除
6#
发表于 2015-2-10 07:09:00 | 只看该作者
由于JSP/Servlet都是基于Java的,所以它们也有Java语言的最大优点——平台无关性,也就是所谓的“一次编写,随处运行(WORA–WriteOnce,RunAnywhere)”。除了这个优点,JSP/Servlet的效率以及安全性也是相当惊人的。
若相依 该用户已被删除
7#
发表于 2015-2-16 20:48:54 | 只看该作者
ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。
变相怪杰 该用户已被删除
8#
发表于 2015-3-4 10:03:54 | 只看该作者
由于JSP/Servlet都是基于Java的,所以它们也有Java语言的最大优点——平台无关性,也就是所谓的“一次编写,随处运行(WORA–WriteOnce,RunAnywhere)”。除了这个优点,JSP/Servlet的效率以及安全性也是相当惊人的。
谁可相欹 该用户已被删除
9#
发表于 2015-3-11 18:11:40 | 只看该作者
当然我们在选择Asp.net主机是,除了要考虑服务提供商在版本是否是实时更新以外,机房的环境和配置也是非常重要的,通常选择骨干网的机房,在速度和稳定性上会非常有保证。
深爱那片海 该用户已被删除
10#
发表于 2015-3-13 02:07:20 | 只看该作者
网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项!
兰色精灵 该用户已被删除
11#
发表于 2015-3-20 09:29:47 | 只看该作者
但是java靠开源打出的一片天地,特别是在微软的垄断下能打开今天的局面还是有它的生命力的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 20:53

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表