BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面


Posted in Javascript onAugust 01, 2016

前言:上篇介绍了下ko增删改查的封装,确实节省了大量的js代码。博主是一个喜欢偷懒的人,总觉得这些基础的增删改查效果能不能通过一个什么工具直接生成页面效果,啥代码都不用写了,那该多爽。于是研究了下T4的语法,虽然没有完全掌握,但是算是有了一个大致的了解。于是乎有了今天的这篇文章:通过T4模板快速生成页面。

KnockoutJS系列文章:

一、T4的使用介绍

我们知道,MVC里面在添加视图的时候可以自动生成增删改查的页面效果,那是因为MVC为我们内置了基础增删改查的模板,这些模板的语法就是使用T4,那么这些模板在哪里呢?找了下相关文章,发现MVC4及以下的版本模板位置和MVC5及以上模板的位置有很大的不同。

•MVC4及以下版本的模板位置:VS的安装目录+\ItemTemplates\CSharp\Web\MVC 2\CodeTemplates。比如博主的D:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 4\CodeTemplates。

找到cshtml对应的模板,里面就有相应的增删改查的tt文件

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

•MVC5及以上版本的模板位置:直接给出博主的模板位置D:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Web\Mvc\Scaffolding\Templates

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

知道了这个,那么接下来就是改造模板,添加自己的生成内容了。可以直接将List和Edit模板拷贝到过来自行改造,但是最后想了想,还是别动MVC内置的东西了,我们自己来建自己的模板不是更好。

在当前Web项目的根目录下面新建一个文件夹,命名为CodeTemplates,然后将MVC模板里面的MvcControllerEmpty和MvcView两个模板文件夹拷贝到CodeTemplates文件夹下面,去掉它里面的原始模板,然后新建几个自己的模板,如下图:

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

这样我们在添加新的控制器和新建视图的时候就可以看到我们自定义的模板了:

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

二、T4代码介绍

上面介绍了如何新建自己的模板,模板建好之后就要开始往里面塞相应的内容了,如果T4的语法展开了说,那一篇是说不完的,有兴趣的园友可以去园子里找找,文章还是挺多的。这里主要还是来看看几个模板内容。还有一点需要说明下,貌似从MVC5之后,T4的模板文件后缀全部改成了t4,而之前的模板一直是tt结尾的,没有细究它们语法的区别,估计应该差别不大。

1、Controller.cs.t4

为什么要重写这个空的控制器模板呢?博主觉得增删改查的好多方法都需要手动去写好麻烦,写一个模板直接生成可以省事很多。来看看模板里面的实现代码:

<#@ template language="C#" HostSpecific="True" #>
<#@ output extension="cs" #>
<#@ parameter type="System.String" name="ControllerName" #>
<#@ parameter type="System.String" name="ControllerRootName" #>
<#@ parameter type="System.String" name="Namespace" #>
<#@ parameter type="System.String" name="AreaName" #>
<#
var index = ControllerName.LastIndexOf("Controller");
var ModelName = ControllerName.Substring(0, index);
#>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestKO.Models;
namespace <#= Namespace #>
{
public class <#= ControllerName #> : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Edit(<#= ModelName #> model)
{
return View(model);
}
[HttpGet]
public JsonResult Get(int limit, int offset)
{
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//新增实体
[HttpPost]
public JsonResult Add(<#= ModelName #> oData)
{
<#= ModelName #>Model.Add(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//更新实体
[HttpPost]
public JsonResult Update(<#= ModelName #> oData)
{
<#= ModelName #>Model.Update(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//删除实体
[HttpPost]
public JsonResult Delete(List<<#= ModelName #>> oData)
{
<#= ModelName #>Model.Delete(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
}
}

这个内容不难理解,直接查看生成的控制器代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TestKO.Models;
namespace TestKO.Controllers
{
public class UserController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Edit(User model)
{
return View(model);
}
[HttpGet]
public JsonResult Get(int limit, int offset)
{
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//新增实体
[HttpPost]
public JsonResult Add(User oData)
{
UserModel.Add(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//更新实体
[HttpPost]
public JsonResult Update(User oData)
{
UserModel.Update(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
//删除实体
[HttpPost]
public JsonResult Delete(List<User> oData)
{
UserModel.Delete(oData);
return Json(new { }, JsonRequestBehavior.AllowGet);
}
}
}

2、KoIndex.cs.t4

这个模板主要用于生成列表页面,大致代码如下:

<#@ template language="C#" HostSpecific="True" #>
<#@ output extension=".cshtml" #>
<#@ include file="Imports.include.t4" #>
<#
// The following chained if-statement outputs the file header code and markup for a partial view, a view using a layout page, or a regular view.
if(IsPartialView) {
#>
<#
} else if(IsLayoutPageSelected) {
#>
@{
ViewBag.Title = "<#= ViewName#>";
<#
if (!String.IsNullOrEmpty(LayoutPageFile)) {
#>
Layout = "<#= LayoutPageFile#>";
<#
}
#>
}
<#
} else {
#>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title><#= ViewName #></title>
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />
<script src="~/scripts/jquery-1.9.1.min.js"></script>
<script src="~/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script>
<script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>
<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>
<script src="~/scripts/knockout/extensions/knockout.mapping-latest.js"></script>
<script src="~/scripts/extensions/knockout.index.js"></script>
<script src="~/scripts/extensions/knockout.bootstraptable.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
bindId: "div_index",
tableParams :
{
url : "/<#=ViewDataTypeShortName#>/Get",
pageSize : 2,
},
urls :
{
del : "/<#=ViewDataTypeShortName#>/Delete",
edit : "/<#=ViewDataTypeShortName#>/Edit",
add : "/<#=ViewDataTypeShortName#>/Edit",
},
queryCondition :
{
}
};
ko.bindingViewModel(viewModel);
});
</script>
</head>
<body>
<#
PushIndent(" ");
}
#>
<div id="toolbar">
<button data-bind="click:addClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增
</button>
<button data-bind="click:editClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>修改
</button>
<button data-bind="click:deleteClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>删除
</button>
</div>
<table data-bind="bootstrapTable:bootstrapTable">
<thead>
<tr>
<th data-checkbox="true"></th>
<#
IEnumerable<PropertyMetadata> properties = ModelMetadata.Properties;
foreach (PropertyMetadata property in properties) {
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey) {
#>
<th data-field="<#= GetValueExpression(property) #>"><#= GetValueExpression(property) #></th>
<#
}
}#>
</tr>
</thead>
</table>
<#
// The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
#>
<#
if(!IsPartialView && !IsLayoutPageSelected) {
ClearIndent();
#>
</body>
</html>
<#
}
#>
<#@ include file="ModelMetadataFunctions.cs.include.t4" #>

添加一个视图Index,然后选择这个模板

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

得到的页面内容

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
<link href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />
<script src="~/scripts/jquery-1.9.1.min.js"></script>
<script src="~/Content/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script>
<script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>
<script src="~/scripts/knockout/knockout-3.4.0.min.js"></script>
<script src="~/scripts/knockout/extensions/knockout.mapping-latest.js"></script>
<script src="~/scripts/extensions/knockout.index.js"></script>
<script src="~/scripts/extensions/knockout.bootstraptable.js"></script>
<script type="text/javascript">
$(function () {
var viewModel = {
bindId: "div_index",
tableParams :
{
url : "/User/Get",
pageSize : 2,
},
urls :
{
del : "/User/Delete",
edit : "/User/Edit",
add : "/User/Edit",
},
queryCondition :
{
}
};
ko.bindingViewModel(viewModel);
});
</script>
</head>
<body>
<div id="toolbar">
<button data-bind="click:addClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增
</button>
<button data-bind="click:editClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>修改
</button>
<button data-bind="click:deleteClick" type="button" class="btn btn-default">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>删除
</button>
</div>
<table data-bind="bootstrapTable:bootstrapTable">
<thead>
<tr>
<th data-checkbox="true"></th>
<th data-field="Name">Name</th>
<th data-field="FullName">FullName</th>
<th data-field="Age">Age</th>
<th data-field="Des">Des</th>
<th data-field="Createtime">Createtime</th>
<th data-field="strCreatetime">strCreatetime</th>
</tr>
</thead>
</table>
</body>
</html>
Index.cshtml

我们将上篇说的viewmodel搬到页面上面来了,这样每次就不用从controller里面传过来了。稍微改一下表格的列名,页面就可以跑起来了。

这里有待优化的几点:

(1)查询条件没有生成,如果将T4的语法研究深一点,可以在需要查询的字段上面添加特性标识哪些字段需要查询,然后自动生成对应的查询条件。

(2)表格的列名似乎也可以通过属性的字段特性来生成。这点和第一点类似,都需要研究T4的语法。

3、KoEdit.cs.t4

第三个模板页就是编辑的模板了,它的大致代码如下:

<#@ template language="C#" HostSpecific="True" #>
<#@ output extension=".cshtml" #>
<#@ include file="Imports.include.t4" #>
@model <#= ViewDataTypeName #>
<#
// "form-control" attribute is only supported for all EditorFor() in System.Web.Mvc 5.1.0.0 or later versions, except for checkbox, which uses a div in Bootstrap
string boolType = "System.Boolean";
Version requiredMvcVersion = new Version("5.1.0.0");
bool isControlHtmlAttributesSupported = MvcVersion >= requiredMvcVersion;
// The following chained if-statement outputs the file header code and markup for a partial view, a view using a layout page, or a regular view.
if(IsPartialView) {
#>
<#
} else if(IsLayoutPageSelected) {
#>
@{
ViewBag.Title = "<#= ViewName#>";
<#
if (!String.IsNullOrEmpty(LayoutPageFile)) {
#>
Layout = "<#= LayoutPageFile#>";
<#
}
#>
}
<h2><#= ViewName#></h2>
<#
} else {
#>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title><#= ViewName #></title>
</head>
<body>
<#
PushIndent(" ");
}
#>
<#
if (ReferenceScriptLibraries) {
#>
<#
if (!IsLayoutPageSelected && IsBundleConfigPresent) {
#>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
<#
}
#>
<#
else if (!IsLayoutPageSelected) {
#>
<script src="~/Scripts/jquery-<#= JQueryVersion #>.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<#
}
#>
<#
}
#>
<form id="formEdit" class="form-horizontal">
@Html.HiddenFor(model => model.Id)
<div class="modal-body">
<#
IEnumerable<PropertyMetadata> properties = ModelMetadata.Properties;
foreach (PropertyMetadata property in properties) {
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey) {
#>
<div class="form-group">
@Html.LabelFor(model => model.<#= GetValueExpression(property) #>, "<#= GetValueExpression(property) #>", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.<#= GetValueExpression(property) #>, new { @class = "form-control", data_bind = "value:editModel.<#= GetValueExpression(property) #>" })
</div>
</div>
<#
}
}
#>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>保存</button>
</div>
</form>
<#
var index = ViewDataTypeName.LastIndexOf(".");
var ModelName = ViewDataTypeName.Substring(index+1, ViewDataTypeName.Length-index-1);
#>
<script src="~/Scripts/extensions/knockout.edit.js"></script>
<script type="text/javascript">
$(function () {
var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
var viewModel = {
formId: "formEdit",
editModel : model,
urls :
{
submit : model.id == 0 ? "/<#= ModelName #>/Add" : "/<#= ModelName #>/Update"
},
validator:{
fields: { 
Name: {
validators: {
notEmpty: {
message: '名称不能为空!'
}
}
}
}
}
};
ko.bindingEditViewModel(viewModel); 
});
</script>
<#
if(IsLayoutPageSelected && ReferenceScriptLibraries && IsBundleConfigPresent) {
#>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
<#
}
#>
<#
else if(IsLayoutPageSelected && ReferenceScriptLibraries) {
#>
<script src="~/Scripts/jquery-<#= JQueryVersion #>.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<#
}
#>
<#
// The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
#>
<#
if(!IsPartialView && !IsLayoutPageSelected) {
ClearIndent();
#>
</body>
</html>
<#
}
#>
<#@ include file="ModelMetadataFunctions.cs.include.t4" #>

BootstrapTable+KnockoutJS自定义T4模板快速生成增删改查页面

生成的代码:

@model TestKO.Models.User
<form id="formEdit" class="form-horizontal">
@Html.HiddenFor(model => model.Id)
<div class="modal-body">
<div class="form-group">
@Html.LabelFor(model => model.Name, "Name", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control", data_bind = "value:editModel.Name" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FullName, "FullName", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.FullName, new { @class = "form-control", data_bind = "value:editModel.FullName" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Age, "Age", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.Age, new { @class = "form-control", data_bind = "value:editModel.Age" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Des, "Des", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.Des, new { @class = "form-control", data_bind = "value:editModel.Des" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Createtime, "Createtime", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.Createtime, new { @class = "form-control", data_bind = "value:editModel.Createtime" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.strCreatetime, "strCreatetime", new { @class = "control-label col-xs-2" })
<div class="col-xs-10">
@Html.TextBoxFor(model => model.strCreatetime, new { @class = "form-control", data_bind = "value:editModel.strCreatetime" })
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>保存</button>
</div>
</form>
<script src="~/Scripts/extensions/knockout.edit.js"></script>
<script type="text/javascript">
$(function () {
var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
var viewModel = {
formId: "formEdit",
editModel : model,
urls :
{
submit : model.id == 0 ? "/User/Add" : "/User/Update"
},
validator:{
fields: { 
Name: {
validators: {
notEmpty: {
message: '名称不能为空!'
}
}
}
}
}
};
ko.bindingEditViewModel(viewModel); 
});
</script>
Edit.cshtml

当然,代码也需要做稍许修改。通过添加自定义的模板页,只要后台对应的实体模型建好了,在前端只需要新建两个自定义视图,一个简单的增删改查即可完成,不用写一句js代码。

三、select组件的绑定

上面介绍了下T4封装增删改查的语法,页面所有的组件基本都是文本框,然而,在实际项目中,很多的查询和编辑页面都会存在下拉框的展示,对于下拉框,我们该如何处理呢?不卖关子了,直接给出解决方案吧,比如编辑页面我们可以在后台将下拉框的数据源放在实体里面。

用户的实体

[DataContract]
public class User
{
[DataMember]
public int id { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string FullName { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Des { get; set; }
[DataMember]
public DateTime Createtime { get; set; }
[DataMember]
public string strCreatetime { get; set; }
[DataMember]
public string DepartmentId { get; set; }
[DataMember]
public object Departments { get; set; }
}

然后编辑页面

public ActionResult Edit(User model)
{
model.Departments = DepartmentModel.GetData();
return View(model);
}

然后前端绑定即可。

<div class="form-group">
<label for="txt_des">所属部门</label>
<select id="sel_dept" class="form-control" data-bind="options: editModel.Departments,
optionsText: 'Name',
optionsValue: 'Id',
value:editModel.DepartmentId"></select>
</div>

JS代码不用做任何修改,新增和编辑的时候部门字段就能自动添加到viewmodel里面去。

当然,我们很多项目使用的下拉框都不是单纯的select,因为单纯的select样式实在是难看,于是乎出了很多的select组件,比如博主之前分享的select2、MultiSelect等等。当使用这些组件去初始化select时,审核元素你会发现,这个时候界面上的下拉框已经不是单纯的select标签了,而是由组件自定义的很多其他标签组成。我们就以select2组件为例来看看直接按照上面的这样初始化是否可行。

我们将编辑页面初始化的js代码增加最后一句:

<script type="text/javascript">
$(function () {
var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));
var viewModel = {
formId: "formEdit",
editModel : model,
urls :
{
submit : model.id == 0 ? "/User/Add" : "/User/Update"
},
validator:{
fields: {
Name: {
validators: {
notEmpty: {
message: '名称不能为空!'
}
}
}
}
}
};
ko.bindingEditViewModel(viewModel);
$("#sel_dept").select2({});
});
</script>

通过新增和编辑发现,这样确实可行!分析原因,虽然初始化成select2组件之后,页面的html发生了变化,但是组件最终还是会将选中值呈现在原始的select控件上面。不知道除了select2,其他select初始化组件会不会这样,待验证。但是这里有一点需要说明下,在初始化select2之前,下拉框的options必须先绑定值,也就是说,组件的初始化必须要放在ko.applyBinding()之后。

四、总结

至此,ko结合bootstrapTable的模板生成以及select控件的使用基本可用,当然,还有待完善。后面如果有时间,博主会整理下其他前端组件和ko的联合使用,比如我们最常见的日期控件。如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
img标签中onerror用法
Aug 13 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
Aug 03 Javascript
各浏览器中querySelector和querySelectorAll的实现差异分析
May 23 Javascript
JavaScript改变HTML元素的样式改变CSS及元素属性
Nov 12 Javascript
Javascript 实现匿名递归的实例代码
May 25 Javascript
基于JavaScript实现带数据验证和复选框的表单提交
Aug 23 Javascript
详解Vue如何支持JSX语法
Nov 10 Javascript
jQuery实现文件编码成base64并通过AJAX上传的方法
Apr 12 jQuery
jQuery实现DIV响应鼠标滑过由下向上展开效果示例【测试可用】
Apr 26 jQuery
小程序视频或音频自定义可拖拽进度条的示例代码
Sep 30 Javascript
vue-quill-editor插入图片路径太长问题解决方法
Jan 08 Vue.js
微信小程序实现拍照和相册选取图片
May 09 Javascript
AngularJS基础 ng-href 指令用法
Aug 01 #Javascript
jQuery实现点击行选中或取消CheckBox的方法
Aug 01 #Javascript
AngularJS基础 ng-hide 指令用法及示例代码
Aug 01 #Javascript
使用JS中的exec()方法构造正则表达式验证
Aug 01 #Javascript
javascript创建含数字字母的随机字符串方法总结
Aug 01 #Javascript
jQuery简单实现彩色云标签效果示例
Aug 01 #Javascript
jQuery实现的简单百分比进度条效果示例
Aug 01 #Javascript
You might like
Php做的端口嗅探器--可以指定网站和端口
2006/10/09 PHP
PHP实现执行外部程序的方法详解
2017/08/17 PHP
浅谈PHPANALYSIS提取关键字
2019/03/08 PHP
Laravel框架使用技巧之使用url()全局函数返回前一个页面的地址方法详解
2020/04/06 PHP
javascript 短路法代码精简
2009/08/20 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
JQuery实现动态添加删除评论的方法
2015/05/18 Javascript
动态加载jQuery的两种方法实例分析
2015/07/17 Javascript
JSON+Jquery省市区三级联动
2016/01/13 Javascript
React Js 微信禁止复制链接分享禁止隐藏右上角菜单功能
2017/05/26 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
vue.js+ElementUI实现进度条提示密码强度效果
2020/01/18 Javascript
Python基于二分查找实现求整数平方根的方法
2016/05/12 Python
Python中列表元素转为数字的方法分析
2016/06/14 Python
Django实现自定义404,500页面教程
2017/03/26 Python
python使用标准库根据进程名如何获取进程的pid详解
2017/10/31 Python
flask中使用蓝图将路由分开写在不同文件实例解析
2018/01/19 Python
完美解决Pycharm无法导入包的问题 Unresolved reference
2018/05/18 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
Python对excel文档的操作方法详解
2018/12/10 Python
在python plt图表中文字大小调节的方法
2019/07/08 Python
html5 div布局与table布局详解
2016/11/16 HTML / CSS
Bjorn Borg官方网上商店:国际运动时尚品牌
2016/08/27 全球购物
英国经典球衣网站:Classic Football Shirts
2017/05/20 全球购物
Jimmy Choo美国官网:周仰杰鞋子品牌
2018/06/08 全球购物
Linux Interview Questions For software testers
2013/05/17 面试题
上班早退检讨书
2014/01/09 职场文书
员工工作表扬信范文
2014/01/13 职场文书
网上商城创业计划书范文
2014/01/31 职场文书
创建省级文明单位实施方案
2014/02/27 职场文书
《开国大典》教学反思
2014/04/19 职场文书
英语求职信范文
2014/05/23 职场文书
贷款委托书怎么写
2014/08/02 职场文书
优秀乡村医生先进事迹材料
2014/08/23 职场文书
戒毒悔改检讨书
2014/09/21 职场文书
2015年度高中教师工作总结
2015/05/26 职场文书