zoukankan      html  css  js  c++  java
  • ExtJs 备忘录(2)—— Form表单(二) [ 控件封装 ]


    前言
      本以为可以稳稳当当的工作、安安心心的写文章,结果我做了一件非常疯狂的事情,换新工作一周后辞了——然后去了另外一家公司 - - #,理由就不详说了,总之现在是每天加班到8-9点,虽然如此但是这个团队非常棒,喜欢这里的气氛,大家都努力的工作着,经理也是常睡在公司,希望产品顺顺利利的月底上线,我也加油 !不过这样一来文章可能会慢点,挤挤时间吧:  )
      本篇主要是将对Ext常用控件和属性进行封装,以减少动辄几百行的JS代码,也方便使用。

    系列
      1.  ExtJs 备忘录(1)—— Form表单(一) [ 控件使用 ]
      2.  ExtJs 备忘录(2)—— Form表单(二) [ 控件封装 ]

    正文
      一、使用封装后Ext表单控件
        esayadd.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="esayadd.aspx.cs" Inherits="esayadd" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        
    <title>表单控件</title>
    </head>
    <body>
        
    <form id="form1" runat="server">
    <script type="text/javascript">
        Ext.onReady(
    function() {
        
            Ext.QuickTips.init();
            Ext.form.Field.prototype.msgTarget 
    = 'side';

            
    var form1 = new Ext.FormPanel({
                layout: 
    'form',
                collapsible: 
    true,
                autoHeight: 
    true,
                frame: 
    true,
                renderTo: Ext.getBody(),
                title: 
    '<center style="curor:hand" onclick="window.location.reload();">表单控件</center>',
                style: 
    'margin-left:auto;margin-right:auto;500px;margin-top:8px;',
                
    //设置标签对齐方式
                labelAlign: 'right',
                
    //设置标签宽
                labelWidth: 170,
                
    //设置按钮的对齐方式
                buttonAlign:'center',
                
    //默认元素属性设置
                defaults:{
                        
    180
                    },
                items: [
                    
    new TextField('TextBox','文本框控件'),
                    
    new NumberField('TextBoxNumber','只允许输入数字'),
                    
    new ComboBox('DropDownList','下拉框控件',[[1,''],[0,'']]),
                    
    new DateField('DateControl','日历控件'),
                    
    new RadioGroup('RadioItems','单选控件',[['选我','A',true],['选我吧','B']]),
                    
    new CheckboxGroup('CheckboxItems','复选控件',[['香蕉','A'],['苹果','B'],['橘子','C'],['桃子','D']],3),
                    
    new TextArea('textarea','文本域控件',null,50,'可以输好多字!'),
                    
    new TimeField(null,'时间控件',60,'H:i'),
                    
    new FieldSet('标签页','标签页',[new Panel('标签页中的面板',null,50,true)]),
                    
    new HtmlEditor('htmleditor','在线编辑器',260,100)
                ],
                buttons: [{
                    text: 
    "保 存"
                    ,handler:
    function(){
                        MsgError(
    '错误');
                        MsgWarning(
    '警告');
                        MsgInfo(
    '提示');
                        MsgConfirm(
    '确认');
                    }
                }, {
                    text: 
    "取 消"
                    ,handler:
    function(){
                        form1.form.reset();
                    }
                }]
            });
        });
        
    </script>
        
    </form>
    </body>
    </html>
        代码说明:
          请大家比较ExtJs 备忘录(1)—— Form表单(上) [ 控件使用 ]中的add.aspx与本文esayadd.aspx,封装带来的简洁、易用和减少使用控件出错几率是显而易见的。需要注意的是,这里只是做了简单的封装,因为Ext表单控件属性太多,起码也有10个以上,这里不可能把所有的属性都列为函数参数,所以根据实际项目情况进行调整,可以在这个现有函数基础上补上常用的参数设置,只要能满足80%-90%的情况价值就体现了 : )

      二、Ext表单控件封装
        easy-ext.js    
    /// <reference path="../adapter/ext/ext-base.js" />
    //
    / <reference path="../ext-all.js" />

    //<><><><><><><><><><><><><><><><><><><><>
    //
     作 者:农民伯伯
    //
     邮 箱:over140@gmail.com
    //
     博 客:http://over140.cnblogs.com/
    //
     时 间:2009-9-16
    //
    <><><><><><><><><><><><><><><><><><><><>

    //#region Ext.form.TextField
    function TextField(fName,fLabel,defaultValue)
    {
        
    /// <summary>
        /// Ext.form.TextField封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>Ext.form.TextField</returns>
        var text = new Ext.form.TextField();
        
        
    if(fName!=null)
            text.name 
    = fName;
        
        
    if(fLabel!=null)
            text.fieldLabel 
    = fLabel;
        
        
    //设置默认值
        if(defaultValue != null)
            text.setValue(defaultValue);
        
        
    return text;
    }
    //#endregion

    //#region Ext.form.TextField
    function NumberField(fName,fLabel,defaultValue,allowDecimals,allowNegative,maxValue,minValue)
    {
        
    /// <summary>
        /// Ext.form.NumberField封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="allowDecimals">是否允许小数点</param>
        /// <param name="allowNegative">是否允许负数</param>
        /// <param name="maxValue">最大值</param>
        /// <param name="minValue">最小值</param>
        /// <returns>Ext.form.NumberField</returns>
        var number = new Ext.form.NumberField();
        
        
    if(fName!=null)
            number.name 
    = fName;
        
        
    if(fLabel!=null)
            number.fieldLabel 
    = fLabel;
        
        
    //设置默认值
        if(defaultValue != null && typeof(defaultValue) == "number")
            number.setValue(defaultValue);
        
        
    //设置是否允许小数点,默认(不设置)为不允许
        if(allowDecimals != null && typeof(allowDecimals) == "boolean")
            number.allowDecimals 
    = Boolean(allowDecimals);
            
        
    //设置是否允许负数,默认(不设置)为不允许
        if(allowNegative != null && typeof(allowNegative) == "boolean")
            number.allowNegative 
    = Boolean(allowNegative);     
        
        
    //设置最大值
        if(maxValue != null && typeof(maxValue) == "number")
            number.maxValue 
    = Number(maxValue);     
            
        
    //设置最小值
        if(minValue != null && typeof(minValue) == "number")
            number.minValue 
    = Number(minValue);
        
        
    return number;
    }
    //#endregion

    //#region Ext.form.DateField
    function DateField(fName,fLabel,defaultValue,format,editable)
    {
        
    /// <summary>
        /// Ext.form.DateField封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="defaultValue">Boolean:true为当前日期/String: 按'Y-m-d'格式,如2009-1-1</param>
        /// <param name="format">设置日期格式化字符串</param>
        /// <param name="editable">是否允许输入,还是只能选择日期</param>
        /// <returns>Ext.form.DateField</returns>
        var date = new Ext.form.DateField();
        
        
    if(fName!=null)
            date.name 
    = fName;
        
        
    if(fLabel!=null)
            date.fieldLabel 
    = fLabel;
        
        
    //设置日期格式化字符串
        if(format == null)
            format 
    = 'Y-m-d';
        date.format 
    = format;
        
        
    //设置默认日期
        if(defaultValue != null)
        {
            
    if(typeof(defaultValue) == "boolean" && Boolean(defaultValue) == true)
            {
                date.setValue(
    new Date().dateFormat(format));
            }
            
    else if(typeof(defaultValue) == "string")
            {
                
    var strDate =String(defaultValue).split("-");
                
    if(strDate.length==3)
                    date.setValue(
    new Date(strDate[0],parseInt(strDate[1])-1,strDate[2]).dateFormat(format));
            }
        }
        
        
    //是否允许编辑
        if(editable==null)
            editable 
    = false;
        
    else if(typeof(editable) == "boolean")
            editable 
    = Boolean(editable);
        
        date.editable 
    = editable;
        
        
    return date;
    }
    //#endregion

    //#region Ext.form.TimeField

    function TimeField(fName,fLabel,increment,format)
    {
        
    /// <summary>
        /// Ext.form.TimeField封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="increment">设置时间间隔,单位为分钟</param>
        /// <param name="format">格式化输出,支持格式如下:"g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H"</param>
        /// <returns>Ext.form.TimeField</returns>
        var time = new Ext.form.TimeField();
        
        
    if(fName!=null)
            time.name 
    = fName;
        
        
    if(fLabel!=null)
            time.fieldLabel 
    = fLabel;
            
        
    //设置时间间隔 默认为15分钟
        if(increment!=null && typeof(increment) == "number")
            time.increment 
    = Number(increment);
            
        
    //设置格式化输出 默认为 "g:i A"
        if(format != null && typeof(format) == "string")
            time.format 
    = String(format);
        
        
    return time;
    }

    //#endregion

    //#region Ext.form.ComboBox
    function ComboBox(fName,fLabel,dataStore,defaultValue,displayField,valueField,editable)
    {
        
    /// <summary>
        /// Ext.form.ComboBox封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="dataStore">数据源。本地模式,如[[1,'男'],[0,'女']];远程模式,传入Ext.data.Store</param>
        /// <param name="defaultValue">默认值</param>
        /// <param name="displayField">选项的文本对应的字段</param>
        /// <param name="valueField">选项的值对应的字段</param>
        /// <param name="editable">是否可以输入,还是只能选择下拉框中的选项</param>
        /// <returns>Ext.form.ComboBox</returns>
        var combo = new Ext.form.ComboBox({
            mode: 
    'local',
            editable : 
    false,
            typeAhead: 
    true,
            triggerAction: 
    'all',
            selectOnFocus:
    true
        });
        
        
    if(fName!=null)
            combo.name 
    = fName;
        
        
    if(fLabel!=null)
            combo.fieldLabel 
    = fLabel;
            
        
    if(displayField==null || typeof(displayField) != "string")
            displayField 
    = "Name";
        combo.displayField 
    = String(displayField);
            
        
    if(valueField==null || typeof(valueField) != "string")
            valueField 
    = "Id";
        combo.valueField 
    = String(valueField);    
        
        
    //设置数据源
        if(Ext.isArray(dataStore))
        {
            combo.store 
    = new Ext.data.SimpleStore({
                fields: [valueField, displayField],
                data:dataStore
            });
        }
        
    else
        {
            combo.store 
    = dataStore;
            combo.mode 
    = 'remote';
        }
        
        
    //设置默认值
        if(defaultValue!=null)
            combo.setValue(defaultValue);
        
        
    //是否允许编辑
        if(editable!=null && typeof(editable) == "boolean")
            combo.editable 
    = Boolean(editable);  
        
        
    return combo;
    }
    //#endregion

    //#region Ext.form.TextArea

    function TextArea(fName,fLabel,width,height,value)
    {
        
    /// <summary>
        /// Ext.form.TextArea封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="width">width</param>
        /// <param name="height">height</param>
        /// <param name="value">value</param>
        /// <returns>Ext.form.TextArea</returns>
        var area = new Ext.form.TextArea();

        
    if(fName!=null)
            area.name 
    = fName;
        
        
    if(fLabel!=null)
            area.fieldLabel 
    = fLabel;
            
        
    if(width!=null && typeof(width) == "number")
            area.width 
    = Number(width);
            
        
    if(height!=null && typeof(height) == "number")
            area.height 
    = Number(height);
            
        
    if(value!=null)
            area.value 
    = value;
            
        
    return area;
    }

    //#endregion

    //#region Ext.form.RadioGroup

    function RadioGroup(fName,fLabel,items,columns)
    {
        
    /// <summary>
        /// Ext.form.RadioGroup封装
        ///     例子:new RadioGroup('Gender','性别',[['男','男',true],['女','女']])
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="items">数据,格式如下:[['男','男',true],['女','女']]</param>
        /// <param name="columns">设置几列自动排列,如果是1的话会按一行来显示</param>
        /// </summary>
        /// <returns>Ext.form.RadioGroup</returns>
        var rg = new Ext.form.RadioGroup();
        
        
    if(fName!=null)
            rg.name 
    = fName;
        
        
    if(fLabel!=null)
            rg.fieldLabel 
    = fLabel;
        
        
    if(columns!=null && typeof(columns) == "number")
            rg.columns 
    = Number(columns);
            
        
    var rebuildiItems = new Array();
            
        
    if(items !=null){
            
    for(var i = 0 ;i<items.length; i++)
            {
                rebuildiItems[i] 
    = {};
                rebuildiItems[i].name 
    = fName;
                rebuildiItems[i].boxLabel 
    = items[i][0];
                rebuildiItems[i].inputValue 
    = items[i][1];
                
    if(items[i].length > 2 && typeof(items[i][2]) == "boolean")
                    rebuildiItems[i].checked 
    = Boolean(items[i][2]);
            }
            
            
    //Ext.form.RadioGroup扩展
            Ext.override(Ext.form.CheckboxGroup, {
                setItems:
    function(data){
                    
    this.items = data;
                }
            });

            
    if(rg.setItems){
                rg.setItems(rebuildiItems);
            }        
        }
        
        
    return rg;
    }

    //#endregion

    //#region Ext.form.CheckboxGroup

    function CheckboxGroup(fName,fLabel,items,columns)
    {
        
    /// <summary>
        /// Ext.form.CheckboxGroup封装
        ///     例子:new CheckboxGroup('Gender','性别',[['男','男',true],['女','女']])
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="items">数据,格式如下:[['男','男',true],['女','女']]</param>
        /// <param name="columns">设置几列自动排列,如果是1的话会按一行来显示</param>
        /// </summary>
        /// <returns>Ext.form.CheckboxGroup</returns>
        var cg = new Ext.form.CheckboxGroup();
        
        
    if(fName!=null)
            cg.name 
    = fName;
        
        
    if(fLabel!=null)
            cg.fieldLabel 
    = fLabel;
        
        
    if(columns!=null && typeof(columns) == "number")
            cg.columns 
    = Number(columns);
            
        
    var rebuildiItems = new Array();
            
        
    if(items !=null){
            
    for(var i = 0 ;i<items.length; i++)
            {
                rebuildiItems[i] 
    = {};
                rebuildiItems[i].name 
    = fName;
                rebuildiItems[i].boxLabel 
    = items[i][0];
                rebuildiItems[i].inputValue 
    = items[i][1];
                
    if(items[i].length > 2 && typeof(items[i][2]) == "boolean")
                    rebuildiItems[i].checked 
    = Boolean(items[i][2]);
            }
            
            
    //Ext.form.RadioGroup扩展
            Ext.override(Ext.form.CheckboxGroup, {
                setItems:
    function(data){
                    
    this.items = data;
                }
            });

            
    if(cg.setItems){
                cg.setItems(rebuildiItems);
            }        
        }
        
        
    return cg;
    }

    //#endregion

    //#region Ext.form.HtmlEditor

    function HtmlEditor(fName,fLabel,width,height,value)
    {
        
    /// <summary>
        /// Ext.form.HtmlEditor封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="width">width</param>
        /// <param name="height">height</param>
        /// <param name="value">value</param>
        /// <returns>Ext.form.HtmlEditor</returns>
        var editor = new Ext.form.HtmlEditor();

        
    if(fName!=null)
            editor.name 
    = fName;
        
        
    if(fLabel!=null)
            editor.fieldLabel 
    = fLabel;
            
        
    if(width!=null && typeof(width) == "number")
            editor.width 
    = Number(width);
            
        
    if(height!=null && typeof(height) == "number")
            editor.height 
    = Number(height);
            
        
    if(value!=null)
            editor.value 
    = value;
            
        
    return editor;
    }

    //#endregion

    //#region Ext.form.Hidden

    function Hidden(fName,value)
    {
        
    /// <summary>
        /// Ext.form.Hidden封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="value">value</param>
        /// <returns>Ext.form.Hidden</returns>
        var hidden = new Ext.form.Hidden();

        
    if(fName!=null)
            hidden.name 
    = fName;
            
        
    if(value!=null)
            hidden.value 
    = value;
            
        
    return hidden;
    }

    //#endregion

    //#region Ext.form.Checkbox

    function Checkbox(fName,fLabel,value,boxLabel,inputValue,checked)
    {
        
    /// <summary>
        /// Ext.form.Checkbox封装
        /// </summary>
        /// <param name="fName">name</param>
        /// <param name="fLabel">fieldLabel</param>
        /// <param name="value">value</param>
        /// <param name="boxLabel"></param>
        /// <param name="inputValue"></param>
        /// <param name="checked"></param>
        /// <returns>Ext.form.Checkbox</returns>
        var checkbox = new Ext.form.Checkbox();

        
    if(fName!=null)
            checkbox.name 
    = fName;
            
        
    if(fLabel!=null)
            checkbox.fieldLabel 
    = fLabel;
            
        
    if(value!=null)
            checkbox.value 
    = value;
            
        
    if(boxLabel!=null && typeof(boxLabel) == "string")
            checkbox.boxLabel 
    = String(boxLabel);
        
        
    if(inputValue!=null)
            checkbox.inputValue 
    = inputValue;
            
        
    if(checked!=null && typeof(checked) == "boolean")
            checkbox.checked 
    = Boolean(checked);
            
        
    return checkbox;
    }

    //#endregion

    //#region Ext.form.FieldSet

    function FieldSet(fName,title,items)
    {
        
    /// <summary>
        /// Ext.form.FieldSet封装
        /// </summary>
        /// <param name="fName">fieldLabel</param>
        /// <param name="title">title</param>
        /// <param name="items">数据源</param>
        /// <returns>Ext.form.FieldSet</returns>
        var fieldset = new Ext.form.FieldSet();
        
        
    if(fName!=null)
            fieldset.fieldLabel 
    = fName;
            
        
    if(title!=null  && typeof(title) == "string")
            fieldset.title 
    = String(title);
            
        
    if(items!=null)
            fieldset.add(items);
        
        
    return fieldset;
    }

    //#endregion

    //#region Ext.Panel

    function Panel(title,width,height,frame)
    {
        
    /// <summary>
        /// Ext.Panel封装
        /// </summary>
        /// <param name="title">name</param>
        /// <param name="width">value</param>
        /// <param name="height">height</param>
        /// <param name="frame">frame</param>
        /// <returns>Ext.Panel</returns>
        if(title ==null)
            title 
    = '';  //默认值 如果为此值则不显示标题栏
            
        
    var panel = new Ext.Panel({
            title:title
        });
            
        
    if(width!=null && typeof(width) == "number")
            panel.width 
    = Number(width);
            
        
    if(height!=null && typeof(height) == "number")
            panel.height 
    = Number(height);
            
        
    if(frame!=null && typeof(frame) == "boolean")
            panel.frame 
    = Boolean(frame);
        
        
    return panel;
    }

    //#endregion

    //#region MessageBox

    function MsgConfirm(msg,title,fn,width)
    {
        
    /// <summary>
        /// Ext.Msg.show 问题确认框
        /// </summary>
        /// <param name="msg">设置要输出的信息</param>
        /// <param name="title">设置确认框标题</param>
        /// <param name="fn">设置回调fn函数</param>
        /// <param name="width">设置确认框宽</param>
        /// <returns>Ext.Msg.show</returns>
        if(msg ==null)
            msg 
    = "";
        
        
    if(title == null || typeof(title) != "string")
            title 
    = "问题";
            
        
    if(width == null || typeof(width) != "number")
            width 
    = 400;
            
        
    if(fn == null || typeof(fn) != "function")
            fn 
    = new function(){};
        
        
    return Ext.Msg.show({
            title: title,
            msg: msg,
             width,
            icon:Ext.MessageBox.QUESTION,
            buttons: Ext.MessageBox.YESNO,
            fn:fn
        });
    }

    function MsgInfo(msg,title,width)
    {
        
    /// <summary>
        /// Ext.Msg.show 信息提示框
        /// </summary>
        /// <param name="msg">设置要输出的信息</param>
        /// <param name="title">设置标题</param>
        /// <param name="width">设置提示框宽</param>
        /// <returns>Ext.Msg.show</returns>
        if(msg ==null)
            msg 
    = "";
        
        
    if(title == null || typeof(title) != "string")
            title 
    = "提示";
            
        
    if(width == null || typeof(width) != "number")
            width 
    = 400;
            
        
    return Ext.MessageBox.show({
            title: title,
            msg: msg,
             width,
            icon:Ext.MessageBox.INFO,
            buttons: Ext.MessageBox.OK
        });
    }

    function MsgError(msg,title,width)
    {
        
    /// <summary>
        /// Ext.Msg.show 错误提示框
        /// </summary>
        /// <param name="msg">设置要输出的信息</param>
        /// <param name="title">设置标题</param>
        /// <param name="width">设置提示框宽</param>
        /// <returns>Ext.Msg.show</returns>
        if(msg ==null)
            msg 
    = "";
        
        
    if(title == null || typeof(title) != "string")
            title 
    = "错误";
            
        
    if(width == null || typeof(width) != "number")
            width 
    = 400;

        
    return Ext.MessageBox.show({
            title: title,
            msg: msg,
             width,
            icon:Ext.MessageBox.ERROR,
            buttons: Ext.MessageBox.OK
        });
    }

    function MsgWarning(msg,title,width)
    {
        
    /// <summary>
        /// Ext.Msg.show 警告提示框
        /// </summary>
        /// <param name="msg">设置要输出的信息</param>
        /// <param name="title">设置标题</param>
        /// <param name="width">设置提示框宽</param>
        /// <returns>Ext.Msg.show</returns>
        if(msg ==null)
            msg 
    = "";
        
        
    if(title == null || typeof(title) != "string")
            title 
    = "警告";
            
        
    if(width == null || typeof(width) != "number")
            width 
    = 400;

        
    return Ext.MessageBox.show({
            title: title,
            msg: msg,
             width,
            icon:Ext.MessageBox.WARNING,
            buttons: Ext.MessageBox.OK
        });
    }

    //#endregion
        代码说明:
          这里封装了常用的Form表单控件、Panel控件、以及弹出消息提示的封装。这里为什么要封装MSG框呢,根据我使用ext3.0rc2的经验,如果不指定MSG宽且MSG字符串过少的话可能出现对话框残缺的情况,不知道是不是它的BUG,3.0正式版好像没有这情况,但还是封装了,这样能兼容前面的版本。

      三、说明
        1.  写好封装js后,还需要把它加入到head里面,以便其他地方也能方便使用,注意上篇文章ExtHelper.cs我注释的部分,解除注释即可。注意这里文件名称可能有变化,对应修改即可。
        2.  封装的好处在贴esayadd.aspx代码后面的说明里面有说,对于动辄几百行的JS代码,这样还是能有效的减少代码量,也不容易出错。一旦封装好后就不要轻易修改了,如果要修改也必须保证只能增加参数,这样才能保证你前面写的代码调用没有问题,对于特殊的复杂的设置可以在封装的基础上继续设置(你可以看到return 都是Ext的对象)或者重新写一个可能比较好!

      四、下载
        1.  ExtJS2009-9-20.rar

    结束语
      有点忙,今天不加班,所以也赶紧把这系列尽早写完吧:  )
  • 相关阅读:
    如何新建一个datatable,并往表里赋值
    c# 、 Asp.net 获取本地IP和MAC地址
    C# asp.net 比较两个时间的差求天数
    获取CheckBox的值
    Gradle的属性设置大全
    Gradle里配置jetty实现静态资源的热部署
    Gradle命令行黑魔法
    2013年上半年我读过的那些书
    SVN中Branch的创建与合并
    只有好的棋手才会走运-《打造Facebook》读后感
  • 原文地址:https://www.cnblogs.com/over140/p/1566010.html
Copyright © 2011-2022 走看看