#快速入门

##NEJ是什么? NEJ是一个简洁、美观,真正跨平台的javascript开发框架。它拥有依赖管理,多平台适配,自由定制,新技术应用,多方案集成和多工具支持六大特性。

##下载NEJ 你可以在三个地方找到NEJ下载链接。第一个地方是首页。首页提供最新稳定版本的下载。第二个地方是下载页面。下载页面提供最新版本和历史版本的下载。第三个地方是github。你可以通过gitHub地址下载NEJ的最新版本。下载下来的NEJ压缩包包含有NEJ库和NEJ依赖库两个部分,其中NEJ依赖库为nej/src/define.js文件,其余为NEJ库文件。

##引入NEJ依赖库 为了方便开发者管理脚本文件,NEJ开发了一套依赖管理系统来管理脚本。依赖系统通过文件定义来引用本脚本需要的脚本文件。要使用NEJ,要先引入NEJ依赖库。引入NEJ文件可以分为两种方式,一种为引入下载的依赖库。另一种可以直接引用在线的依赖库。假设项目文件目录如下:

  • project
    • js
    • css
    • image
    • index.html

将下载NEJ压缩包解压到js中,则解压后目录如下:

  • project
    • css
    • image
    • index.html
    • js
      • pro
      • nej
        • demo
        • doc
        • res
        • qunit
        • src
          • define.js
          • define.cmp.js
          • base
          • native
          • patched
          • ui
          • util
          • test

上图中,./project/js/nej为解压的文件,./project/js/pro为项目自己的js文件夹。 在index.html中引入NEJ依赖包,其代码如下:

<script src="./js/nej/src/define.js?pro=./"></script>

无需下载NEJ包,直接在index.html中引入在线NEJ依赖库,其代码如下:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>

其中上述代码中,"pro=./"为路径配置,关于配置的相关内容请参考文件依赖使用手册。

##使用NEJ 下面是一个火车快跑的Demo。其效果如下:

要启动,请点车;要加速,请继续点车。
慢车
快速
直达
高铁

实现上面的代码如下:

html:

<div id='cardemo' class="demo">
    <div id='trainrun'>
        <div class='x-item'>要启动,请点车;要加速,请继续点车。</div>
        <div>
            <div class="x-item">慢车</div>
            <div class="x-item">快速</div>
            <div class="x-item">直达</div>
            <div class="x-item">高铁</div>
        </div>
    </div>
</div>

css:

.demo{width:800px;border:1px solid #3C3C3C;background-color:#FDF5E6;}
.x-item{position:relative;width:300px;height:50px;margin:5px 0;background-color:#FFE4C4;text-align:center;line-height:50px;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e'),
        _v = _('nej.v'),
        _j = _('nej.j'),
        _u = _('nej.u'),
        _p = _('nej.ut');
    //获取节点
    var _parent=_e._$get('trainrun');
    //滚动效果
    var _roll=function(_target,_index){
        if(!_target.style.left) _target.style.left=(_index*3)+"px";
        else _target.style.left=(parseInt(_target.style.left)>(600-_index*3))?
                                    "0px":parseInt(_target.style.left)+3*_index+"px";
    };
    //车速数组
    var _carSpeed=[0,0,0,0];
    //item节点点击事件
    var _onItemClick=function(_event,_index){
        var _target=_v._$getElement(_event);
        _carSpeed[_index-1]+=1;
        _target.innerHTML=_target.innerHTML.substring(0,2)+"x"+_carSpeed[_index-1];
        setInterval(_roll._$bind(this,_target,_index),1000);
    }
    //item回调函数
    var _cbWithItem=function(_item,_index,_list){
        if(_index%2==0)_item.style.backgroundColor="#B4EEB4";
        _v._$addEvent(_item,"click",_onItemClick._$bind2(this,_index+1));
    }
    //获取Item节点
    var _xItems=_e._$getByClassName(_e._$getChildren(_parent)[1],"x-item");
    //给Item节点添加事件
    _u._$forEach(_xItems,_cbWithItem,this);
};
define(['{lib}base/event.js'],f);
</script>

通过脚本,我们可以清楚地看到,NEJ的代码结构。

首先,引用依赖库,并进行路径配置,平台配置。本例中,路径配置了pro,平台配置采用默认的全浏览器平台支持。 然后,定义文件,引入我们依赖的库和项目的公共js。 最后,定义一个方法f,在方法体中实现本页面的所有逻辑。

代码解释:

NEJ采用名字空间的概念,它把不同的接口按照作用,分配到不同的名字空间中去,这样开发者,可以非常清晰方便地调用接口。而NEJ.P为创造或者取名字空间的方法。

例如:_e=NEJ.P(‘nej.e’),为名字空间window.nej.e。这个空间主要包含节点操作的接口,譬如,_$get(id|Node)取节点,_$hasClassName(id|_node,_className)判断节点含有某些类,_$create(_nodeType,_style,_parent)创造节点等接口。

_v=NEJ.P(‘nej.v’),为名字空间window.nej.v。这个空间主要包含事件接口,譬如,_$addEvent(_id|_node,_eventType,handler,bool)添加事件,_$stopDefault(_event)阻止默认事件,_$pageX(_event)获取事件的水平位置等。

_u=NEJ.P(‘nej.u’),为名字空间window.nej.u。这个空间主要包含一些便捷调用的接口,譬如,_$isFunction(_variable)判断数据类型,_$escape(_htmlStr)将HTMLString转码,_$forEach(_list,_cbFun,_object)遍历列表等等。

除了上述名字空间外,NEJ还定义了提供前后端及本地资源交互相关的的接口的名字空间window.nej.j,定义了NEJ的UI控件的名字空间window.nej.ui等等,具体请查看手册。

本Demo中,通过_$getByClassName的方法获取了所有了火车的节点,并对其进行遍历。在回调函数中,对序号为偶数的火车进行了背景色设置,并对每一列车添加了点击事件。这里要注意的是,为了保证this的一致性和区分各个列车的不同速度,用_$bind(_o,_arg0,_ar1…)绑定了当前对象,并传递各个列车的index参数。在各个车的点击事件处理中,通过绑定传递过来的index参数,实现了各个车的不同速度。

##使用控件 NEJ提供了大量控件,以帮助开发人员完成开发,加快开发速度。下面请看我们的日历控件Demo,看是如何方便使用的。

实现上面的代码如下:

html:

<div class="demo">
  <input type="text" id="datepick" />
</div>

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f = function(){
    var _  = NEJ.P,
        _e = _('nej.e'),
        _u = _('nej.u'),
        _v = _('nej.v'),
        _p = _('nej.ui');

     var _input = _e._$get('datepick');
     _v._$addEvent(_input,'click',onInputClick)

     function onInputClick(_event){
        _v._$stop(_event);//因为日历控件是卡片,在document上接收到click 事件都会回调到卡片,所以阻止掉事件
        var _datepick = _p._$$DatePick._$allocate({
                    parent: _input.parentNode,
                    clazz: 'm-dt',      //通过这个样式改变日历控件的表现
                    onchange: onChange
                }); 
     }

    //选中时回调,把值设到input中
    function onChange(_value){
        _input.value = _u._$format(_value,'yyyy-MM-dd');
    }
}
define(['{lib}ui/datepick/datepick.js'],f);
</script>

代码解释:

代码的核心部分为var _datepick = _p._$$DatePick.$allocate( {parent:_input.parentNode, clazz:’m-dt’,onchange:onChange} ); 它的作用是返回window.nej.ui的名字空间下的公共类_$$DatePick的一个实例。初始化这个实例需要三个参数,parent,日历节点的父节点;clazz,日历节点的样式,通过修改这个参数,实现样式不同的日历;onchange,日历变化事件函数。当日期发生改变时,如何进行处理,譬如回写等等。

本Demo中,当点击input时,触发onInputClick事件,生成一个日历,日历节点被append在parent节点的下面。在选定日期后,触发日历的onChange事件,将日期写回到input中去。

##使用Ajax NEJ提供了对AJAX的统一接口,位于window.nej.j名字空间的_$request方法。此方法还需要uitl控件xhr的支持,所以需要定义{lib}util/ajax/xhr.js文件。以下是通过AJAX请求好友数据的一个Demo。

点我

实现上面的代码如下:

html:

<div id='ajax'>
  <div id='cnt'></div>
  <div id='bnt'>点我</div>
</div>

css:

#ajax{position:relative;width:800px;height:200px;margin:5px 0;border:1px solid #696969;background-color:#F0FFF0;overflow:hidden;}
#bnt{position:absolute;top:0;left:0;width:50px;height:200px;background-color:#FFE4C4;font-size:12px;line-height:200px;text-align:center;cursor:pointer;}
#cnt{position:absolute;top:0;left:50px;width:848px;padding:10px 20px;}
#cnt p{height:28px;padding:4px 0;margin:0;font-size:12px;line-height:14px;color:#333;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e'),
        _v = _('nej.v'),
        _j = _('nej.j');
    //上次显示最后一条序号
    var _lastIndex=0;
    //ajax回调函数
    var _cbShowAjaxData=function(_data){
        var _cnt=_e._$get('cnt');
        _cnt.innerHTML='';
        var _len=_data.length;
        for(var i=(_lastIndex>=_len?(_lastIndex=0):_lastIndex),l=(i+5<_len?i+5:_len);i<l;i++){
            var _tempP=_e._$create("p",null,_cnt);
            _tempP.innerHTML="title:"+_data[i].title+"<br/>"+_data[i].shortPublishDateStr
                +" "+_data[i].publishTimeStr+" 访问"+_data[i].accessCount+" 评论"+_data[i].commentCount;
        }
        _lastIndex+=5;
    };
    //bntClick响应函数
    var _onBntClick=function(event){
        //ajax请求数据
        _j._$request("http://nej.netease.com/api/getFriendsLatestBlogs",{
            sync:false,
            type:"json",
            data:null,
            query:"userid=126770605",
            method:"GET",
            onload:_cbShowAjaxData
        });
    };
    //添加事件
    _v._$addEvent(_e._$get('bnt'),'click',_onBntClick._$bind(this));
};
define(['{lib}util/ajax/xdr.js'],f);
</script>

代码解释:

NEJ使用ajax的方法非常简单,只要定义好依赖文件{lib}util/ajax/xhr.js文件,就可以很方便的使用ajax请求。Demo中只使用了onload事件,其它还有出错回调onerror,上传中回调onuploading,下载中回调ondownloading等等配置,具体请参照ajax专题。

Demo中通过ajax请求到好友的最新日志列表。在获得数据后,为简化长度,通过对数据长度的判断,最多显示5条好友最新日志数据。随后在parent节点下面,为每条日志数据创建一个P标签,并将数据取出来放到标签上,最终显示在页面上。

##使用文件上传 NEJ的文件上传非常方便,下面是一个简单的图片上传Demo。

请选择一张大小不超过2M的图片

实现上面代码如下

html:

<form name="upload-form" action="../../upload/">
  <h3>请选择一张大小不超过2M的图片<span id="uploaderr"></span></h3>
  <p><input type="file" id="upload" name="upload" accept="image/*" /></p>
  <img id="preview" class="f-dn">
</form>

css:

#uploaderr{font-size:10px;color:#f00;}
#preview{width:100%;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e'),
        _v = _('nej.v'),
        _j = _('nej.j');

    //上传出错常量
    var UPLOADERR={
        UNSUPPORT:"不支持的文件类型,仅支持jpg,gif,jpeg,png,bmp图片类型!",
        TOOLARGER:"上传文件太大,不能超2M!",
        UNKNOWERR:"未知原因,上传失败!!"
    };
    //上传文件最大大小
    var UPLOADFILEMAXSIZE=2*1024*1024;
    //上传文件
    var _doUpload=function(_evt){
        //清理并初始化
        _e._$get('preview').src="";
        _e._$get('preview').style.display='';
        _e._$get('uploaderr').innerHTML="";
        //验证
        _evt=_evt || window.event;
        var _target= _evt.srcElement || _evt.target;
        //验证文件格式
        var _src=_target.value;
        var _type=(_src.substr(_src.lastIndexOf(".")+1)).toLowerCase();
        if(!/(jpg|gif|jpeg|png|bmp)/i.test(_type)){
            _e._$get('uploaderr').innerHTML=UPLOADERR.UNSUPPORT;
            return;
        }
        //验证文件大小
        var _size=0;
        if(_target.files){
            var _file=_target.files[0];
            _size=_file.fileSize ? _file.fileSize : _file.size;
        }else{
            //IE9以下放弃获取文件大小,改为后台判断
        }
        if(_size>UPLOADFILEMAXSIZE){
            _e._$get('uploaderr').innerHTML=UPLOADERR.TOOLARGER;
            return;
        }
        //上传文件
        _j._$upload(document.forms['upload-form'],{
            onload:function(_json){
                if(_json.state=="success"){
                    _e._$get('preview').style.display='block';
                    _e._$get('preview').src=_json.url;
                }else{
                    _e._$get('uploaderr').innerHTML=UPLOADERR.UNSUPPORT;
                }
            },
            onerror:function(_err){
                if(_err.data==413){
                    _e._$get('uploaderr').innerHTML=UPLOADERR.TOOLARGER;
                }else{
                    _e._$get('uploaderr').innerHTML=UPLOADERR.UNKNOWERR;
                }
            }
        })
    };
    //添加上传文件事件
    _v._$addEvent('upload','change',_doUpload);
};
define(['{lib}util/ajax/xdr.js'],f);
</script>

代码解释:

直接调用_j._$upload()接口就好

##使用模版 NEJ有非常好用且强大的模板功能,下面是一个关于模板的Demo。

  • Tab-0
  • Tab-1
  • Tab-2

实现上面代码如下

html:

<ul class="w-tab f-cb" id="tab-box">
  <li class="itm fl">Tab-0</li>
  <li class="itm fl">Tab-1</li>
  <li class="itm fl">Tab-2</li>
</ul>
<div id="module-box"></div>
<div id="template-box" style="display:none;">
  <textarea name="jst" id="mdl-tab-0">
    <div class="m-tab-1">
      {list xlist as x}
        <p>${x_index}.NEJ是一个简洁、美观,真正跨平台的javascript开发框架。</p>
      {/list}
    </div>
  </textarea>
  <textarea name="ntp" id="mdl-tab-1">
    <div class="m-tab-1">
      <p>为了方便开发者管理脚本文件,NEJ开发了一套依赖管理系统来管理脚本。依赖系统通过文件定义来引用本脚本需要的脚本文件。要使用NEJ,要先引入NEJ依赖库。引入NEJ文件可以分为两种方式,一种为引入下载的依赖库。另一种可以直接引用在线的依赖库。</p>
      <p>为了方便开发者管理脚本文件,NEJ开发了一套依赖管理系统来管理脚本。依赖系统通过文件定义来引用本脚本需要的脚本文件。要使用NEJ,要先引入NEJ依赖库。引入NEJ文件可以分为两种方式,一种为引入下载的依赖库。另一种可以直接引用在线的依赖库。</p>
      <p>为了方便开发者管理脚本文件,NEJ开发了一套依赖管理系统来管理脚本。依赖系统通过文件定义来引用本脚本需要的脚本文件。要使用NEJ,要先引入NEJ依赖库。引入NEJ文件可以分为两种方式,一种为引入下载的依赖库。另一种可以直接引用在线的依赖库。</p>
    </div>
  </textarea>
  <textarea name="txt" id="mdl-tab-2">
    <div class="m-tab-2">
      <p>你可以在三个地方找到NEJ下载链接。第一个地方是首页。首页提供最新稳定版本的下载。第二个地方是下载页面。下载页面提供最新版本和历史版本的下载。第三个地方是github。你可以通过gitHub地址下载NEJ的最新版本。下载下来的NEJ压缩包包含有NEJ库和NEJ依赖库两个部分,其中NEJ依赖库为nej/src/define.js文件,其余为NEJ库文件。</p>
      <p>你可以在三个地方找到NEJ下载链接。第一个地方是首页。首页提供最新稳定版本的下载。第二个地方是下载页面。下载页面提供最新版本和历史版本的下载。第三个地方是github。你可以通过gitHub地址下载NEJ的最新版本。下载下来的NEJ压缩包包含有NEJ库和NEJ依赖库两个部分,其中NEJ依赖库为nej/src/define.js文件,其余为NEJ库文件。</p>
      <p>你可以在三个地方找到NEJ下载链接。第一个地方是首页。首页提供最新稳定版本的下载。第二个地方是下载页面。下载页面提供最新版本和历史版本的下载。第三个地方是github。你可以通过gitHub地址下载NEJ的最新版本。下载下来的NEJ压缩包包含有NEJ库和NEJ依赖库两个部分,其中NEJ依赖库为nej/src/define.js文件,其余为NEJ库文件。</p>
    </div>
  </textarea>
</div>

css:

.f-cb:after{clear:both;content:'.';display:block;height:0;visibility:hidden;}
.f-cb{zoom:1;}
.f-cb .fl{float:left;}
.f-cb .fr{float:right;}
.w-tab{margin:0;padding:0;border-bottom:1px solid #aaa;text-align:center;}
.w-tab .itm{width:80px;height:30px;line-height:30px;margin:0 3px 0 0;background:#dcf;list-style:none;cursor:pointer;}
.w-tab .itm.js-selected{background:#aaa;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e');

    //解析模板
    _e._$parseTemplate('template-box');
    //使用tab控件
    _e._$tab('tab-box',{
        index:1,
        onchange:function(_event){
            var _element=_e._$get('module-box');
            switch(_event.index){
                case 0:
                    _element.innerHTML=_e._$getHtmlTemplate('mdl-tab-0',{xlist:new Array(6)});
                    break;
                case 1:
                    _element.innerHTML='';
                    _element.appendChild(_e._$getNodeTemplate('mdl-tab-1'));
                    break;
                case 2:
                    _element.innerHTML=_e._$getTextTemplate('mdl-tab-2');
                    break;
            }
        }
    })
};
define(['{lib}util/template/tpl.js','{lib}util/tab/tab.js'],f);

代码解释:

先通过_e._$parseTemplate()接口解析模板,再通过_e._$getHtmlTemplate(),_e._$getNodeTemplate(),_e._$getTextTemplate()等接口获取到模板。

##使用表单控件 这是一个带有验证功能的登陆表单Demo(测试帐号:netease,密码:123456)。

NEJ表单填写

用户名: 用户名输入提示信息
密 码: 密码输入提示信息
 

实现上面代码如下

html:

<form class="w-form" data-focus-mode="1">
  <p>NEJ表单填写</p>
  <table>
    <tr>
      <td class="c0">用户名:</td>
      <td class="c1">
          <input type="text"
                 name="username" 
                 class="text"
                 placeholder="用户名"
                 data-required="true"
                 data-message="请输入用户名"/>
      </td>
      <td class="c2">
        <span id="username-tip">用户名输入提示信息</span>
      </td>
    </tr>
    <tr>
      <td class="c0">密  码:</td>
      <td class="c1">
          <input type="password"
                 name="password" 
                 class="text"
                 placeholder="密码"
                 data-required="true"
                 data-message="请输入密码"/>
      </td>
      <td class="c2">
        <span id="password-tip">密码输入提示信息</span>
      </td>
    </tr>
    <tr>
      <td class="c0">&nbsp;</td>
      <td class="c1" colspan="2">
        <input type="button" value="提交" name="btn-ok"/>
      </td>
    </tr>
  </table>
</form>

css:

.w-form{text-align:left;}
.w-form input{margin:0;padding:0;}
.w-form td{padding:4px 0;border:none;}
.w-form table{table-layout:fixed;width:100%;}
.w-form .c0{width:90px;text-align:right;}
.w-form .c1{width:200px;}
.w-form .text{width:190px;border:1px solid #aaa;}
.w-form .js-invalid{border-color:#f00;}
.w-form .js-error{padding-left:10px;color:#f00;}
.w-form .js-pass{padding-left:10px;color:#22B14C;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e'),
        _v = _('nej.v'),
        _j = _('nej.j'),
        _p = _('nej.ut');

    //分配表单控件
    var _form=_p._$$WebForm._$allocate({
        form:document.forms[1],
        message:{
            pass:'ok'
        }
    });
    //提交表单事件
    var _doSubmit=function(){
        if(_form._$checkValidity()){
            var _data=_form._$data();
            _j._$request('../../api/login',{
                method:'POST',
                type:'json',
                data:'username='+_data.username+'&password='+_data.password,
                onload:function(_json){
                    switch(_json.code){
                        case -1:
                            _form._$showMsgError('password','密码错误!');
                            return;
                        case -2:
                            _form._$showMsgError('username','用户名不存在!');
                            return;
                    }
                    alert('提交成功!');
                }
            })
        }
    };
    //添加事件
    _v._$addEvent(_form._$get('btn-ok'),'click',_doSubmit);
};
define(['{lib}util/form/form.js','{lib}util/ajax/xdr.js'],f);

代码解释:

先通过_p._$$WebForm._$allocate()分配webForm控件,再添加ajax验证,最后处理回调函数。

##使用动画 NEJ也提供了对动画的支持,下面演示一个弹簧减速效果减速的动画效果。

点我

实现上面的代码如下

html:

<div id='anim'>
  <div id='bnt2'>点我</div>
  <div id='ball'></div>
</div>

css:

#anim{position:relative;height:50px;width:800px;margin:5px 0;border:1px solid #696969;}
#bnt2{position:absolute;top:0;left:0;width:50px;height:50px;background-color:#FFE4C4;font-size:12px;line-height:50px;text-align:center;cursor:pointer;}
#ball{position:absolute;top:20px;left:70px;width:10px;height:10px;background-color:black;border-radius:10px;}

js:

<script src="http://nej.netease.com/nej/src/define.js?pro=./"></script>
<script>
var f=function(){
    var _ = NEJ.P,
        _e = _('nej.e'),
        _v = _('nej.v'),
        _p = _('nej.ut');

    var _ac = _p._$$AnimBounce._$allocate({from:{offset:70,velocity:1000},acceleration:500,springtension:0.5,onstop:_onBounceStop,onupdate:_onBounceUpdate})

    function _onBounceStop(_offset){
        //todo
    }
    function _onBounceUpdate(_offset){
        _e._$get('ball').style.left = _offset.offset +'px';
    }

    _v._$addEvent(_e._$get('bnt2'),'click',_onBnt2Click._$bind(this));
    function _onBnt2Click(event){
        _ac._$play();
    };
};
define(['{lib}util/animation/bounce.js'],f);
</script>

代码解释:

NEJ使用动画效果,需要相应的util控件的支持,本Demo中使用了弹簧效果,所以在文件定义中依赖了动画中的弹簧效果控件。

##打包和发布 为了优化项目前端的代码和提高发布效率,NEJ提供了一套打包策略和发布工具,方便发布。下面以本文包含Demo的页面为例,介绍下如何进行打包发布。

环境配置

发布工具使用nodejs编写,因此需要使用者先安装nodejs环境,nodejs在各个平台下的安装配置请参阅官方说明。http://nodejs.org/

获取工具

下载页面有打包工具下载。解压,解压后目录结构如下:

添加打包标记

打包工具通过打包标记对内容进行打包配置。打包标记是基于html的注释标记扩展,不会影响到页面的实际呈现效果。详情请参阅打包工具说明书。本Demo的打包标记如下:

使用

  1. 将项目文件复制到nej_publisher/release下面。复制后项目文件如下nej_publisher/release/quickstart。目录结构为:

  2. 修改nej_publisher/release.conf配置文件。将第10行,DIR_WEBROOT修改为../quickstart/;将12行DIR_SOURCE修改为./html,将14行DIR_OUTPUT修改为./out/pub/;将16行DIR_OUTPUT_STATIC修改为./out/s/;

  3. 运行release.bat或者release.sh
  4. 查看结果。新生成的文件在/quickstart/out/文件夹中。./pub/中为index.html文件,./s/中为pp_index.css和pp_index.js文件。

新生成的压缩的index.html文件:

pp_index.css文件

pp_index.js文件

##其他 本页面打包后Demo(四合一)下载

© 1997-2013 Netease. All Rights Reserved.
comments powered by Disqus