详解MVC如何使用开源分页插件(shenniu.pager.js)


Posted in Javascript onDecember 16, 2016

最近比较忙,前期忙公司手机端接口项目,各种开发+调试+发布现在几乎上线无问题了;虽然公司项目忙不过在期间抽空做了两件个人觉得有意义的事情,一者使用aspnetcore开发了个人线上项目(要说线上其实只能ip访问,没有域名哈哈),其架构组成由:aspnetcore1.0.0+redis+ postgressql+TaskMainForm服务,这个项目在后期会开源出来供大家分享学习,站点地址点这里心声网;一者是目前正在做的后台管理框架一叶子,现目前刚好吧js分页插件shenniu.pager.js写完,个人觉得还是可以的,这也是本章将要和大家分享的内容;那么开始今天的分享内容,希望各位多多扫码支持:

  • 为什么采用js分页及效果图
  • 在view中如何使用及分享个后台方法
  • 开发者视角阅读shenniu.pager.js代码

下面一步一个脚印的来分享:

. 为什么采用js分页及效果图

首先,咋们来了解下市面上mvc两种常用的分页方式:跳转分页和ajax分页;跳转分页意思就是页面重定向到指定的页面并通过传递分页需要的参数,从而获取数据后通过Modal来绑定数据,这个每次都会刷下页面体验上不是很好;ajax分页通过异步js请求某个接口,然后从接口获取到数据后,再赋值到展示的界面上,这种方式是不会刷新页面,从而保证了用户体验;

下面来看下这次分享的js分页插件效果图:

图一:

详解MVC如何使用开源分页插件(shenniu.pager.js)

图二:

详解MVC如何使用开源分页插件(shenniu.pager.js)

图三:

详解MVC如何使用开源分页插件(shenniu.pager.js)

看效果图好像看不出来什么东西,我只能说没办法,以后争取弄个gif动态图片吧,后面代码才是关键

. 在view中如何使用及分享个后台方法

首先,为了页面样式好看我使用了bootstrap+ace样式框架,样式效果就是如上面几张图所示(这里是样式和js文件);由于该插件是采用jquery格式书写的所以需要引用jquery.js,如上面图所示使用到了日期选择框,因为我采用的样式都是基于h5的设计所以这里引用的日期选择插件bootstrap-datepicker.min.js和她的样式bootstrap-datepicker3.min.css;该实例需要的引用文件都好了,下面看下截图:

详解MVC如何使用开源分页插件(shenniu.pager.js)

再来,咋们就开始使用shenniu.pager.js,我们需要在点击“查询”按钮的时候去调用这个插件,然后通过插件去获取后台接口返回的数据,并绑定到页面展示出来,所以有了如下代码:

var snTool = new shenniuTool();
 $("button[id='btnSearch']").on("click", function () {
 var data = {
 txtName: $("input[name='txtName']").val(),
 nStatus: $("select option:selected").val(),
 dOperateTime: $("input[name='dOperateTime']").val()
 };
 snTool.listFun({
 showId: "divShowResult", //内容显示的div的Id
 url: "/Menu/Search",
 data: data,
 pageSize: 2, //每页N条
 headText: [
 { nickName: "全选", name: "Id", colType: "checkbox" },
 { nickName: "名称", name: "Name", colType: "label", isModalHeadText: true },
 { nickName: "链接", name: "Link" },
 { nickName: "状态", name: "EnableDes" },
 { nickName: "操作人", name: "OperatorDes" },
 { nickName: "操作时间", name: "OperateTime", format: "yyyy-MM-dd" },
 { nickName: "操作", name: "Id", colType: "operate" }
 ],
 editeOption: {
 url: "/Menu/Edit",
 title: "编辑",
 height: 500
 },
 viewOption: {
 url: "/Menu/Details",
 title: "查看",
 height: 500
 },
 delOption: {
 url: "/Menu/Delete",
 title: "删除",
 height: 500
 },
 modalExt: modalExt
 });
 });

注意参数url: "/Menu/Search",这个指向的就是后台接口,那么咋们来看下我后台咋们写的:

[HttpGet]
 public JsonResult Search()
 {
 var moPageResult = new StageModel.MoPageResult<dynamic>();
 try
 {
 var txtName = Request.Params["txtName"];
 var nStatus = string.IsNullOrWhiteSpace(Request.Params["nStatus"]) ? -1 : Convert.ToInt32(Request.Params["nStatus"]);
 var dOperateTime = string.IsNullOrWhiteSpace(Request.Params["dOperateTime"]) ? Convert.ToDateTime("1991-01-01") : Convert.ToDateTime(Request.Params["dOperateTime"]);
 var data = db.MoMenus.AsQueryable();
 if (!string.IsNullOrWhiteSpace(txtName))
 {
 data = data.Where(b => b.Name.Contains(txtName));
 }
 if (nStatus >= 0)
 {
 data = data.Where(b => b.IsEnable == (nStatus == (int)StageEnumHelper.ComStatus.启用));
 }
 if (dOperateTime > Convert.ToDateTime("1991-01-01"))
 {
 data = data.Where(b => b.OperateTime >= dOperateTime && b.OperateTime < dOperateTime.AddDays(1));
 }
 moPageResult.MoPageContent(
 data,
 b => b.OperateTime,
 b => new
 {
 Id = b.Id,
 Name = b.Name,
 Link = b.Link,
 Des = b.Des,
 IsEnable = b.IsEnable,
 Operator = b.Operator,

 OperatorDes = b.MoUserInfo.NickName,
 EnableDes = b.IsEnable ? "启用" : "禁用",
 OperateTime = b.OperateTime
 });
 }
 catch (Exception ex)
 {
 }
 return Json(moPageResult, JsonRequestBehavior.AllowGet);
 }

后台接口Request.Params获取的几个参数就是从前端

var data = {
 txtName: $("input[name='txtName']").val(),
 nStatus: $("select option:selected").val(),
 dOperateTime: $("input[name='dOperateTime']").val()
 };

传递过来的,分别代码了视图中的名称,状态,操作时间等查询条件;下面来看下,后台这儿没有看到获取类似分页的当前页数和分页记录数的操作,是封装到了MoPageResult类中的MoPageContent()中,来看下MoPageResult类代码如:

#region 分页数据返回
 public class MoPageResult<TResult> where TResult : class, new()
 {
 public MoPageResult()
 {
 }
 public IQueryable<TResult> MoResult;
 /// <summary>
 /// 总页数
 /// </summary>
 public int PageTotal { get; set; }
 /// <summary>
 /// 当前页数
 /// </summary>
 public int CurrentPage { get; set; }
 /// <summary>
 /// 分页记录数
 /// </summary>
 public int PageSize { get; set; }
 /// <summary>
 /// 分页方法
 /// </summary>
 /// <typeparam name="TKey"></typeparam>
 /// <param name="query"></param>
 /// <param name="order_desc"></param>
 public void MoPageContent<T, TKey>(IQueryable<T> query, Expression<Func<T, TKey>> desc, Expression<Func<T, TResult>> selector = null, bool isDesc = true) where T : class,new()
 {
 if (HttpContext.Current == null) { return; }
 var Request = HttpContext.Current.Request;
 this.PageSize = string.IsNullOrWhiteSpace(Request.Params["pageSize"]) ? 15 : Convert.ToInt32(Request.Params["pageSize"]);
 this.CurrentPage = string.IsNullOrWhiteSpace(Request.Params["currentPage"]) ? 1 : Convert.ToInt32(Request.Params["currentPage"]);
 var nTotal = query.Count();
 this.PageTotal = nTotal / this.PageSize + (nTotal % this.PageSize > 0 ? 1 : 0);
 if (selector != null)
 {
 if (isDesc)
 {
 query = query.OrderByDescending(desc);
 }
 else
 {
 query = query.OrderBy(desc);
 }
 this.MoResult = query.
 Skip((this.CurrentPage - 1) * this.PageSize).
 Take(this.PageSize).
 Select(selector);
 }
 }
 }
#endregion

MoPageContent()中默认是获取了pagesize,currentpage参数,这样减少了用户操作性,并且此方法承担了计算总页数和执行分页语句的角色,注意最后查询语句Select(selector),selector是Expression<Func<T, TResult>>类型,这个T有条件约束where T : class,new();我在调用该分页类的使用传递的T是dynamic,因为赖人如我觉得匿名类更方便;唯一遗憾的是select输出暂时无法直接对某个属性直接使用方法;

最后,插件使用还需要注意一个地方,就是时间,如果后台不处理时间直接DateTime的json格式化,那么在插件获取出来的时间格式如:

详解MVC如何使用开源分页插件(shenniu.pager.js)

这个时候就需要在使用shenniu.pager.js插件时候在属性headText中,指定时间列的格式如:

{ nickName: "操作时间", name: "OperateTime", format: "yyyy-MM-dd" }

使用format格式化时间格式,这个插件兼容的给有:yyyy,MM,dd,HH,mm,ss,相信满足大家需要了;

. 开发者视角阅读shenniu.pager.js代码

首先,我们从上而下,映入眼帘的是插件属性:

var defOption = {
 showId: "divShowResult", //内容显示的div
 url: "", //ajax数据来源地址
 headText: [
 { nickName: "A", colType: "checkbox", name: "Id" },
 { nickName: "B", colType: "label", name: "Name", isModalHeadText: true } //isModalHeadText:是否是模式窗体头部显示的信息
 ],
 data: {}, //查询条件
 editeOption: {
 url: "",
 title: "编辑",
 width: 500,
 height: 500
 }, //编辑地址,不包括id
 viewOption: {
 url: "",
 title: "查看",
 width: 500,
 height: 500
 }, //查看地址
 delOption: {
 url: "",
 title: "删除",
 width: 500,
 height: 500
 }, //删除地址
 currentPage: 1, //当前页数
 pageSize: 15, //分页记录数
 showPageTab: 6, //展示6个页数
 modalExt: null, //模式窗体对象
 //可忽略
 callback: function () { }, //回调函数
 tabId: "tab001",
 loading: "努力加载中,等会吧...", //可以直接写出<img src=''/>
 sucFun: function (data) { },
 befFun: function () { },
 errFun: function () { },
 comFun: function () { },
 timeout: 60000 //超时60S
 };
$.extend(defOption, option);

里面已经包括了注释说明,看起来应该不是问题; $.extend(defOption, option); 这段代码意思是吧用户传递进来的参数和插件里面默认的参数合并,用户大于插件直接可以覆盖相同属性的值;

再来,看请求后台的方法:

//请求后台
 function ajaxFun(option) {
 if (option) {
 $.extend(defOption, option);
 }
 //获取分页参数
 var hidPageSize = defOption.pageSize;
 var hidCurrentPage = defOption.currentPage;
 if ($("form input[name='pageSize']").val()) {
 hidPageSize = $("form input[name='pageSize']").val();
 }
 if ($("form input[name='currentPage']").val()) {
 hidCurrentPage = $("form input[name='currentPage']").val();
 }
 //合并用户查询条件和分页参数条件
 var searchData = {
 pageSize: hidPageSize,
 currentPage: hidCurrentPage
 };
 $.extend(searchData, defOption.data);
 //请求后台数据
 $.ajax({
 url: defOption.url,
 type: "get",
 data: searchData,
 dataType: "json",
 timeout: defOption.timeout,
 async: true,
 beforeSend: defOption.befFun,
 success: defOption.sucFun,
 });
 }

这个方法就是请求接口获取数据的方法,里面默认获取了页面中的pageSize,currentPage两个分页所需要的参数,这里采用的是get方式来请求,当然可以写成post,不过需要后台支持post就行了;

我们再看查询列表方法:

//查询列表
 listFun: function (option) {
 if (option) {
 $.extend(defOption, option);
 }
 //默认格式
 var tab = [];
 tab.push('<table id="' + defOption.tabId + '" class="table table-bordered table-hover">');
 tab.push('<thead><tr role="row">');
 for (var i in defOption.headText) {
 var head = defOption.headText[i];
 if (head.colType == "label") {
 tab.push('<th class="center" tabindex="0" rowspan="1" colspan="1">' + head.nickName + '</th>');
 } else if (head.colType == "checkbox") {
 tab.push('<th class="center " rowspan="1" colspan="1" aria-label="">');
 tab.push(' <label class="pos-rel">');
 tab.push(' <input type="checkbox" name="cbAll" class="ace">');
 tab.push(' <span class="lbl">' + head.nickName + '</span>');
 tab.push(' </label>');
 tab.push('</th>');
 } else {
 tab.push('<th class="center" tabindex="0" rowspan="1" colspan="1">' + head.nickName + '</th>');
 }
 }
 tab.push('</tr></thead>');
 tab.push('<tbody><tr><td class="text-center" colspan="' + defOption.headText.length + '">' + defOption.loading + '</td></tr></tbody>');
 tab.push('</table>');
 tab.push('<div id="divPager" class="text-center"></div>');
 $("#" + defOption.showId).html(tab.join(''));
 //全选事件
 $("input[type='checkbox'][name='cbAll']").on("click", function () {
 var cbStatus = $(this).is(":checked");
 if (cbStatus) {
 $("input[name='cb']:checkbox").prop("checked", true);
 } else {
 $("input[name='cb']:checkbox").prop("checked", false);
 }
 });
 //数据返回成功处理
 defOption.sucFun = function (data) {
 var head = $("table[id='" + defOption.tabId + "'] tbody");
 if (data) {
 if (data.MoResult) {
 //遍历table展示的数据
 var rows = [];
 $.each(data.MoResult, function (i, item) {
 rows.push('<tr>');
 var modalHeadText = "";
 for (var h_i in defOption.headText) {
 var head = defOption.headText[h_i];
 var item_val = item[head.name];
 if (item_val && typeof (item_val) != "undefined") { } else { item_val = ""; }
 //时间格式化
 if (head.format && item_val.length > 0) {
 console.log(item_val);
 var date = new Date(parseInt(item_val.replace("/Date(", "").replace(")/", ""), 10));
 item_val = head.format.
 replace("yyyy", date.getFullYear()).
 replace("MM", date.getMonth() + 1).
 replace("dd", date.getDate()).
 replace("HH", date.getHours()).
 replace("mm", date.getMinutes()).
 replace("ss", date.getMilliseconds());
 }
 //获取模式窗体头部信息
 if (modalHeadText.length <= 0) { modalHeadText = head.isModalHeadText ? item_val : "" };
 if (head.colType == "label") {
 rows.push('<td class="center">' + item_val + '</td>');
 } else if (head.colType == "checkbox") {
 rows.push('<td class="center">');
 rows.push(' <label class="pos-rel">');
 rows.push(' <input type="checkbox" name="cb" value="' + item_val + '" class="ace">');
 rows.push(' <span class="lbl"></span>');
 rows.push(' </label>');
 rows.push('</td>');
 } else if (head.colType == "operate") {
 rows.push('<td class="center"><div class="hidden-sm hidden-xs action-buttons">');
 if (defOption.editeOption.url.length > 0) {
 var editOption = $.extend({}, defOption.editeOption);
 editOption.url += "/" + item_val;
 editOption.title += modalHeadText.length > 0 ? "-" + modalHeadText : "";
 var op = JSON.stringify(editOption);
 rows.push('<a class="blue" data-item=\'' + op + '\' href="javascript:;"><i class="ace-icon fa fa-pencil bigger-130"></i></a>');
 }
 if (defOption.viewOption.url.length > 0) {
 var viewOption = $.extend({}, defOption.viewOption);
 viewOption.url += "/" + item_val;
 viewOption.title += modalHeadText.length > 0 ? "-" + modalHeadText : "";
 var op = JSON.stringify(viewOption);
 rows.push('<a class="blue" data-item=\'' + op + '\' href="javascript:;"><i class="ace-icon fa fa-search-plus bigger-130"></i></a>');
 }
 if (defOption.delOption.url.length > 0) {
 var delOption = $.extend({}, defOption.delOption);
 delOption.url += "/" + item_val;
 delOption.title += modalHeadText.length > 0 ? "-" + modalHeadText : "";
 var op = JSON.stringify(delOption);
 rows.push('<a class="blue" data-item=\'' + op + '\' href="javascript:;"><i class="ace-icon fa fa-trash-o bigger-130"></i></a>');
 }
 rows.push('</div></td>');
 }
 else {
 rows.push('<td class="center">' + item_val + '</td>');
 }
 }
 rows.push('</tr>');
 });
 //页数展示
 if (data.MoResult.length > 0) {
 var pager = [];
 pager.push('<div class="text-center">');
 pager.push(' <ul class="pagination" style="margin-top:0px">');
 var nPager = defOption.showPageTab;//每次展示6个分页
 //上一页
 var nprev = (data.CurrentPage - 1 >= 1 ? data.CurrentPage - 1 : 1);
 pager.push(' <li class="paginate_button previous" aria-controls="dynamic-table" tabindex="0" id="dynamic-table_previous">');
 pager.push(' <a href="javascript:;" name="npager" data-page="' + nprev + '">上一页</a>');
 pager.push(' </li>');
 //当前页之前页码
 var preTotal = data.CurrentPage - nPager >= 1 ? data.CurrentPage - nPager : 1;
 for (var i = preTotal; i < data.CurrentPage ; i++) {
 pager.push(' <li class="paginate_button ' + (i == data.CurrentPage ? "active disabled" : "") + '" aria-controls="dynamic-table">');
 pager.push(' <a href="javascript:;" name="npager" data-page="' + i + '">' + i + '</a>');
 pager.push(' </li>');
 }
 //当前页
 pager.push(' <li class="paginate_button active disabled" aria-controls="dynamic-table">');
 pager.push(' <a href="javascript:;" name="npager" data-page="' + data.CurrentPage + '">' + data.CurrentPage + '</a>');
 pager.push(' </li>');
 //当前页以后页码
 var nextTotal = data.CurrentPage + nPager > data.PageTotal ? data.PageTotal : data.CurrentPage + nPager;
 for (var i = data.CurrentPage + 1; i <= nextTotal; i++) {
 pager.push(' <li class="paginate_button ' + (i == data.CurrentPage ? "active disabled" : "") + '" aria-controls="dynamic-table">');
 pager.push(' <a href="javascript:;" name="npager" data-page="' + i + '">' + i + '</a>');
 pager.push(' </li>');
 }
 //下一页
 var nnext = (data.PageTotal < data.CurrentPage + 1 ? data.PageTotal : data.CurrentPage + 1);
 pager.push(' <li class="paginate_button next" aria-controls="dynamic-table" tabindex="0" id="dynamic-table_next">');
 pager.push(' <a href="javascript:;" name="npager" data-page="' + nnext + '">下一页</a>');
 pager.push(' </li>');
 pager.push(' </ul>');
 //分页查询条件
 pager.push('<div style="display:none">');
 pager.push(' <form>');
 pager.push(' <input type="hidden" name="pageSize" value="' + defOption.pageSize + '"/>');
 pager.push(' <input type="hidden" name="currentPage" value="' + defOption.currentPage + '"/>');
 pager.push(' </form>');
 pager.push('</div>');
 pager.push('</div>');
 //移除加载中
 //head.html("");
 //添加结果
 head.html(rows.join(''));
 $("div[id='divPager']").html(pager.join(''));
 //操作按钮事件
 $("a[data-item]").on("click", function () {
 var data_Item = $(this).attr("data-item");
 if (data_Item) {
 var data_Item_Obj = JSON.parse(data_Item);
 defOption.modalExt.modalFun({
 width: data_Item_Obj.width,
 height: data_Item_Obj.height,
 url: data_Item_Obj.url,
 title: data_Item_Obj.title,
 callback: defOption.callback
 });
 }
 });
 //绑定分页按钮事件
 $("a[name='npager']").on("click", function () {
 var nPager = $(this).attr("data-page");
 if (nPager.length <= 0) { return; }
 $("form input[name='currentPage']").val(nPager);
 //执行请求后台
 ajaxFun(defOption);
 });
 } else {
 head.html("<tr><td class=\"text-center\" colspan=\"" + defOption.headText.length + "\">未能查询到数据!</td></tr>");
 $("div[id='divPager']").html("");
 }
 } else {
 head.html("<tr><td class=\"text-center\" colspan=\"" + defOption.headText.length + "\">未能查询到数据。</td></tr>");
 $("div[id='divPager']").html("");
 }
 } else {
 head.html("<tr><td class=\"text-center\" colspan=\"" + defOption.headText.length + "\">未能查询到数据</td></tr>");
 $("div[id='divPager']").html("");
 }
 };
 if (option) {
 $.extend(defOption, option);
 }
 //执行请求后台
 ajaxFun(defOption);
 }

这个方法体挺长的,主要操作是:

默认格式展示列表头部并呈现出加载中的提示=》绑定复选框全选事件=》创建数据返回成功函数sucFun()=》调用请求后台方法ajaxFun();

再来看函数sucFun()等到数据返回后执行的操作是:

遍历json返回数据展示到table中(其中包括了时间格式化的处理,复选框,label及操作按钮类型operate的初始化)=》页数展示及事件绑定(目前只有上一页,当前页之前页码,当前页,当前页以后页码,下一页的效果展示,分页查询条件(生成pagesize和currentPage隐藏控件),绑定分页按钮事件)

以上就是shenniu.pager.js整个插件内容,不多且清晰,感觉分享给大家挺高兴,下面贴出示例中用到的js文件和css文件可以在这里下载:http://xiazai.3water.com/201612/yuanma/shenniu.pager_3water.rar

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
Prototype使用指南之enumerable.js
Jan 10 Javascript
event.X和event.clientX的区别分析
Oct 06 Javascript
jQuery中click事件的定义和用法
Dec 20 Javascript
js实现继承的5种方式
Dec 01 Javascript
基于Vuejs框架实现翻页组件
Jun 29 Javascript
vue2.0嵌套路由实现豆瓣电影分页功能(附demo)
Mar 13 Javascript
浅谈es6 javascript的map数据结构
Dec 14 Javascript
Ionic学习日记实现验证码倒计时
Feb 08 Javascript
nginx+vue.js实现前后端分离的示例代码
Feb 12 Javascript
vue引入js数字小键盘的实现代码
May 14 Javascript
vue移动端弹起蒙层滑动禁止底部滑动操作
Jul 22 Javascript
JavaScript本地储存:localStorage、sessionStorage、cookie的使用
Oct 13 Javascript
js继承实现方法详解
Dec 16 #Javascript
详解jQuery简单的表格应用
Dec 16 #Javascript
JS中parseInt()和map()用法分析
Dec 16 #Javascript
HTML5canvas 绘制一个圆环形的进度表示实例
Dec 16 #Javascript
JS数字千分位格式化实现方法总结
Dec 16 #Javascript
jquery插件锦集【推荐】
Dec 16 #Javascript
jQuery Easyui 下拉树组件combotree
Dec 16 #Javascript
You might like
站长助手-网站web在线管理程序 v1.0 下载
2007/05/12 PHP
php中的路径问题与set_include_path使用介绍
2014/02/11 PHP
JavaScript中Math对象使用说明
2008/01/16 Javascript
JavaScript继承方式实例
2010/10/29 Javascript
提高NodeJS中SSL服务的性能
2014/07/15 NodeJs
JavaScript中变量声明有var和没var的区别示例介绍
2014/09/15 Javascript
一个JavaScript函数把URL参数解析成Json对象
2014/09/24 Javascript
触屏中的JavaScript事件分析
2015/02/06 Javascript
原生js实现轮播图
2017/02/27 Javascript
JS+HTML5 FileReader对象用法示例
2017/04/07 Javascript
AngularJS实现进度条功能示例
2017/07/05 Javascript
AugularJS从入门到实践(必看篇)
2017/07/10 Javascript
深入了解javascript 数组的sort方法
2018/06/01 Javascript
详解vue填坑之解决部分浏览器不支持pushState方法
2018/07/12 Javascript
浅析vue 函数配置项watch及函数 $watch 源码分享
2018/11/22 Javascript
JS脚本实现定时到网站上签到/签退功能
2020/04/22 Javascript
vue 授权获取微信openId操作
2020/11/13 Javascript
[53:52]EG vs VGJ.T 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python PyQt4实现QQ抽屉效果
2018/04/20 Python
浅谈python中字典append 到list 后值的改变问题
2018/05/04 Python
pandas 小数位数 精度的处理方法
2018/06/09 Python
基于Python开发chrome插件的方法分析
2018/07/07 Python
Python初学者常见错误详解
2019/07/02 Python
关于PyTorch源码解读之torchvision.models
2019/08/17 Python
Django 返回json数据的实现示例
2020/03/05 Python
python爬虫快速响应服务器的做法
2020/11/24 Python
css3 盒模型以及box-sizing属性全面了解
2016/09/20 HTML / CSS
CSS3实现文字描边的2种方法(小结)
2020/02/14 HTML / CSS
Java里面Pass by value和Pass by Reference是什么意思
2016/05/02 面试题
生产厂厂长岗位职责
2013/12/25 职场文书
迟到检讨书1000字
2014/01/15 职场文书
中学生差生评语
2014/01/30 职场文书
倡议书范文
2014/04/16 职场文书
学校党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
优秀教师单行材料
2014/12/16 职场文书
Java 定时任务技术趋势简介
2022/05/04 Java/Android