서문 : 이전 기사는 KO 첨가, 삭제, 수정 및 검색의 캡슐화를 소개하여 실제로 많은 JS 코드를 저장합니다. 블로거는 게으르기를 좋아하는 사람입니다. 그는 항상 이러한 기본 추가, 삭제, 수정 및 점검이 도구를 통해 페이지 효과를 직접 생성 할 수 있으며 코드가 필요하지 않다고 생각합니다. 그것은 너무 멋질 것입니다. 그래서 나는 T4의 문법을 연구했습니다. 나는 그것을 완전히 익히지 않았지만 일반적인 이해가있었습니다. 오늘의 기사 : T4 템플릿을 통해 페이지를 빠르게 생성하십시오.
Knockoutjs 시리즈 기사 :
부트 스트랩 가능 및 Knockoutjs는 결합하여 추가, 삭제, 수정 및 점검의 기능을 달성합니다 [1]
부트 스트랩 가능 및 Knockoutjs는 결합하여 추가, 삭제, 수정 및 점검의 기능을 달성합니다 [2]
부트 스트랩 가능 + Knockoutjs는 결합하여 추가, 삭제, 수정 및 확인 솔루션을 실현합니다 (3) 두 개의 뷰 모델은 추가, 삭제, 수정 및 확인을 완료 할 수 있습니다.
1. T4 사용 소개
MVC에서 뷰를 추가 할 때 추가, 삭제, 수정 및 점검의 페이지 효과가 자동으로 생성 될 수 있음을 알고 있습니다. MVC에는 추가, 삭제, 수정 및 확인을위한 기본 템플릿이 내장되어 있기 때문입니다. 이 템플릿의 구문은 T4를 사용하는 것이므로이 템플릿은 어디에 있습니까? 관련 기사를 검색 한 후 MVC4 이상의 버전 템플릿의 위치는 MVC5 이상의 위치와 매우 다르다는 것을 알았습니다.
• MVC4 및 다음 버전의 템플릿 위치 : vs 설치 디렉토리 +/itemtemplates/csharp/web/mvc 2/codetemplates. 예를 들어, 블로거의 D :/Program 파일 (x86)/Microsoft Visual Studio 12.0/Common7/IDED/ItemTemplates/CSHARP/Web/MVC 4/Codetemplates.
CSHTML에 해당하는 템플릿을 찾으면 추가, 삭제, 수정 및 확인에 해당하는 TT 파일이 있습니다.
• MVC5 이상의 템플릿 위치 : 블로거 D :/Program Files (x86)/Microsoft Visual Studio 12.0/Common/ID/Extensions/Microsoft/Web/MVC/Scaffolding/Templates의 템플릿 위치를 직접 제공합니다.
이 사실을 알면 다음 단계는 템플릿을 리모델링하고 자신의 생성 된 컨텐츠를 추가하는 것입니다. 목록을 직접 복사하고 템플릿을 자체 변형으로 편집 할 수 있지만, 생각 후에는 내장 MVC를 만지지 않는 것이 좋습니다. 자신의 템플릿을 직접 구축하는 것이 낫지 않습니다.
현재 웹 프로젝트의 루트 디렉토리 아래에 새 폴더를 만들고, 이름으로 이름을 지정 한 다음, 두 개의 템플릿 폴더 MVCControllerEmpty 및 MVCView를 CodetemPlates 폴더에 MVC 템플릿의 MVCView를 복사 한 다음 아래 그림과 같이 여러 개의 새로운 템플릿을 작성하십시오.
이런 식으로 새 컨트롤러를 추가하고 새 뷰를 만들 때 맞춤형 템플릿을 볼 수 있습니다.
2. T4 코드 소개
위의 내용은 자신의 템플릿을 만드는 방법을 소개합니다. 템플릿이 빌드되면 해당 콘텐츠를 채취하기 시작해야합니다. T4의 문법이 확장되면 해당 기사는 끝이 없습니다. 관심있는 정원사는 정원에서 검색 할 수 있습니다. 여전히 많은 기사가 있습니다. 여기에서 몇 가지 템플릿 내용을 살펴 보겠습니다. 또 다른 점은 MVC5 이후 T4의 템플릿 파일 접미사가 T4로 변경되었고 이전 템플릿은 항상 TT로 끝났다는 것입니다. 구문의 차이를 보지 않으면 차이가 거의없는 것으로 추정됩니다.
1. Controller.cs.t4
이 빈 컨트롤러 템플릿을 다시 작성하는 이유는 무엇입니까? 블로거는 많은 추가, 삭제, 수정 및 확인 방법이 수동으로 작성되어야한다고 생각하며 템플릿을 직접 작성하는 데 많은 어려움이 있다고 생각합니다. 템플릿의 구현 코드를 살펴 보겠습니다.
<#@ template language = "c#"hastspecific = "true"#>####@ output extension = "cs"#>########@ parameter type = "system.string"name = "컨트롤러 이름"#> <##@ parameter type = "System.String"이름 = "controlLerrootName"#> <@ parameter type = "system" 이름 = "areaname"#> <#var index = controllerName.lastIndexof ( "컨트롤러"); var modelname = controllerName.subString (0, index);#> 시스템 사용; System.Collections.generic 사용; System.Web 사용; system.web.mvc 사용; namespace#> namespace##{namespace##= namespace 사용 #> : 컨트롤러 {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.come); jsonresult add (< #= modelname #> odata) {< #= modelname #> model.add (odata); return json (new}, jsonrequestbehavior.allowget);} // update entity [httppost] public jsonresult update (< #= modelname) {modelname (model name)); JSON (new {}, jsonRequestBehavior.allowget);} // 엔티티 삭제 [httppost] public jsonresult delete (list << #= modelname #> odata) {< #= modelname #> model.delete (odata (new {}, jsonrequestbe)}}};이 내용은 이해하기 어렵지 않습니다. 생성 된 컨트롤러 코드를 확인하십시오.
System.collections.generic 사용 사용 시스템 사용; System.Web; System.Web 사용; System.Web.MVC 사용; TestKo.Models 사용; Fublic Class UserController : Controller {Public ActionResult index () {return view (return view) [return view (Model)) [return view (return view); 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);} // Entity 업데이트 [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#"hastspecific = "true"#>###@ output extension = ". cshtml"#> <##reclude file = "imports.include.t4"#> <#// 다음 체인 if-statement는 파일 헤더 코드 및 Markup, 부분적보기를 사용하여 파일 코드 및 Markup을 출력합니다. if (islayoutPageSelected) {#>@{viewbag.title = "<#= viewName#>"; <#if (! string.isnullOrempty (layoutPageFile)) {#> layout = "<#= layoutPageFile#"; <#}#>} <#} eloppe {@@@@@@} 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"/> <scrc = "~/scripts/jquery-1.9.1.min.js"> </script> <script src = "~/content/bootstrap/js/js/bootstrap.min.js"> 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-3.4.0.min.js"> src = "~/scripts/knockout/extensions/knockout.mapping-latest.js"> </script> <script src = "~/scripts/extensions/knockout.index.js"> </script> <script src = "~/scripts/extenss/knockout.js"> </script> <script> <script> src = "~/scripts/extensions/knockout.js.js"> </script> <script src = "~/scripts/scripts/scripts/scripts/scripts/knockout.bootstraptable.js"> </script> <script type = "text/javascript () {var viewmodel = {div_index" "/<#= viewDatatyPeshortName#>/get", pagesize : 2,}, urls : {del : "/<#= viewDatAtAtyShortName#>/delete", edit : "/<#= viewDatatyPhortName#>/edit", add : "/<#= viewDatatyPeshortName" : {}}; ko.bindingViewModel (ViewModel);}); </script> </head> <body> <#pushIndent ( "");}#> <div id = "도구 인"> <버튼 데이터 -Bind = "클릭 : addClick"type = "butter"> <true "> </span> </span> </span> data-bind = "click : editclick"type = "button"> <span aria-hidden = "true"> </span> modify </button> <버튼 데이터-결합 = "클릭 : deleteclick"type = "button"> <span aria-hidden = "true"> <true "> <trut </button> </div> <table bind = data-checkbox = "true"> </th> <#ienumerable <pospertmetadata> properties = modelmetadata.properties; foreach (properties in properties) {if (property.scaffold &&! property.isprimarykey && property.isforeignkey) {#> <th data-field = "#=####################. getValueExpression (property)#> </th> <#}}#> </tr> </thead> </table> <#// 다음 코드는 레이아웃 페이지와 본문 및 HTML 태그를 사용하여 뷰와 HTML 태그를 사용하여 사용 된 태그를 닫습니다. {clearIndent ();#> </body> </html> <#}#}#}#} include file = "ModelMetAdAtAftions.cs.include.t4"#>보기 인덱스를 추가 하고이 템플릿을 선택하십시오
얻은 페이지 내용
@{layout = null;} <! doctype html> <html> <head> <meta name = "viewport"content = "width = device-width"/> <title> index </title> <link href = "~/bootstrap/css/bootstrap.min.css"rel = "inke" href = "~/content/bootstrap-table/bootstrap-table.min.css"rel = "stylesheet"/> <scrc = "~/scripts/jquery-1.9.1.min.js"> </script> <script src = "~/content/bootstrap/js/js/bootstrap.min.js"> 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-3.4.0.min.js"> src = "~/scripts/knockout/knockout-3.4.0.min.js"> </script> <script src = "~/scripts/knockout/extensions/knockout.mapping-latest.js"> </script> <script src = "~//scripts/extens/knockout.js"> </script src = "~/scripts/extensions/knockout.bootstraptable.js"> </script> <script type = "text/javaScript"> $ (function () {var viewModel = {bindId : "div_index", tableParams : {url : "/user/get", pages : 2,}, urlls : "/user/delit" "/user/edit", add : "/user/edit",}, querycondition : {}}; ko.bindingViewModel (viewModel);}); </script> </head> <body> <div id = "툴바"> <button data-bind = "click : addclick"type = "button"> <span aria-hidden = "true"> </span> add </button> <button data-bind = "click : editclick"type = "button"> <span aria-hidden = "true"> </span> modify </button> <button data-bind = "click : deleteclick"type = "button"> <true "> </span> </div> <table Data-Bind = "BootStraptable : bootstraptable"> <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 </th> <th Data-Field = "CreateTime"> CreateTime </th> <th data-field = "strcreateTime"> strcreateTime </th> </tr> </thead> </table> </body> </html> index.cshtml이전 기사에서 언급 된 뷰 모델을 페이지로 옮겼으므로 매번 컨트롤러에서 전달할 필요가 없습니다. 테이블의 열 이름을 약간 변경하면 페이지가 실행될 수 있습니다.
다음은 최적화 할 몇 가지 요점입니다.
(1) 쿼리 조건이 생성되지 않았습니다. T4의 구문을 조금 더 깊이 연구하면 쿼리 해야하는 필드를 식별하기 위해 쿼리 해야하는 필드에 특성을 추가 한 다음 해당 쿼리 조건을 자동으로 생성 할 수 있습니다.
(2) 테이블의 열 이름은 속성의 필드 속성을 통해 생성되는 것 같습니다. 이것은 첫 번째 요점과 유사하며 둘 다 T4의 문법을 연구해야합니다.
3. koedit.cs.t4
세 번째 템플릿 페이지는 편집 된 템플릿이며 거친 코드는 다음과 같습니다.
<#@ template language = "c#"hastspecific = "true"#>###@ output extension = ". cshtml"#>##ruclear file = "imports.include.t4"#> model <#= viewDatatyPename#> <#// "Form-Control"속성은 All editorfor ()에서만 지원됩니다. 부트 스트랩 스트링 부리에서 div를 사용하는 checkbox, booltype = "system.boolean"; 버전 uredghtmvcversion = new 버전 ( "5.1.0.0"); bool iscontrolhtmlattrubtessupported = mvcversion> = 필수 mvcversion; // 다음 번에 Chained if-statement outputs a a a a a a evertion weance a a a a a everated mvcversion; if (iSpartialView) {#> <#} else if (islayoutPagesElected) {#>@{viewbag.title = "<#= viewName#>"; <#if (! string.isnullorEmpty (layoutPageFile)) {#> layout = "#= layoutPageFile#" ViewName#> </h2> <#} else {#>@{#> {layout = null;} <! doctype html> <html> <head> <head> <meta name = "viewport"content = "width = device-width"/> <title> <#= viewname#> </title> </head> <#푸시 인덴트 ( "}#}; (참조 ScriptLibraries) {#> <#if (! islayoutPageSelect && isbundleConfigPresent) {#>@scripts.render ( "~/bundles/jquery")@scripts.render ( "~/bundles/jqueryVal") <}#<#el#<else (! islayoutPagesepted)#> 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">@html.hiddenfor (model => model.id) <div> <#ienumerable <positymetadata = properterties = propopties; (property.scaffold &&! property.isprimarykey &&! property.isforeignkey) {#> <div>@html.labelfor (model => model. <#= getValueExpression (property)#>, "<#= getValueExpression (property)#>", new {@class = "Control-Label col-xs-2"<@html. =#= getValueExpression (속성)#>, new {@class = "form-control", data_bind = "value : editModel. <#= getValueExpression (property)#>"}) </div> </div> <#}}#> </div> <버튼 유형 = "data-dismiss ="data-dismiss = "data-dismiss aria-hidden = "true"> </span> close </button> <button type = "제출"> <span aria-hidden = "true"> </span> 저장 </button> </div> </form>#var index = viewDatatyPename.lastIndexOf ( "); var modelname = viewDatatyPename.substring (+1,+1, substring). ViewDatatypename.length-index-1);#> <script src = "~/scripts/extensions/knockout.edit.js"> </script> <script> <script> <text/javaScript "> $ () {var model = @html.raw (newtonsoft.json.jsonconvert.serivelize.serobvert.serobvert.serobvert.serobver. {CORMID : "formedit", editModel : model, urls : {제출 : model.id == 0? "/< #= modelname #>/add": "/< #= modelname #>/update"} : {name : {validator : {message : '이름이 될 수 없습니다. 빈! '}}}}}}; ko.bindingEditViewModel (viewModel); </script> <#if (islayoutPagesElect && referenceLibraries && isbundleconfigpresent) {#>@section scripts {@scripts.render ( "~/bundles/jqueryval")} <#}#> <else if (islayoutPageSelect && referenceScriptLibraries) {#> <script src = "~/scripts/jquery- <#= jqueryversion#> </script> </script> src = "~/scripts/jquery.validate.min.js"> </script> <script src = "~/scripts/jquery.validate.unobtrous.min.js"> </script> <script src = "~/scripts/jquery.validate.unobtrusive.min.js"> </script> <#}#> <#// 다음 코드는 레이아웃 페이지와 신체 및 HTML 태그를 사용하여 뷰와 HTML 태그를 사용하여 사용되는 태그를 닫습니다. {clearIndent ();#> </body> </html> <#}#}#}#} include file = "ModelMetAdAtAftions.cs.include.t4"#>생성 된 코드 :
@model testko.models.user <form id = "formedit">@html.hiddenfor (model => model.id) <div> <div>@html.labelfor (model => model.name, "name", new {@class = "컨트롤-라벨 col-xs-2") <div>@html. @class = "form-control", data_bind = "value : editModel.name"}) </div> </div> <div> @html.labelfor (model => model.fullname, "fullName", new {@class = "컨트롤-라벨 col-xs-2") <div> @html. @class = "form-control", data_bind = "value : editmodel.fullname"}) </div> </div> <div> @html.labelfor (model => model.age, "age", new {@class = "컨트롤-라벨 col-x-2"}) < @html.textbox => necclox. "form-control", data_bind = "value : editModel.age"}) </div> </div> <div> @html.labelfor (model => model.des, "des", new {@class = "Control-Label col-xs-2"}) <div> @html.textboxfor (model => new {@class =). "form-control", data_bind = "value : value : editmodel.des"}) </div> </div> <div> @html.labelfor (model => model.createTime, "createTime", new {@class = "컨트롤-라벨 col-x-2"}) <div> @html.textbox, new @createstime "form-control", data_bind = "value : value : editModel.createTime"}) </div> </div> <div>@html.labelfor (model => model.strcreateTime, "strcreateTime", new {@class = "컨트롤-라벨 col-xs-2") <div>@html. {@class = "form-control", data_bind = "value : editModel.StrcreateTime"}) </div> </div> </div> <버튼 유형 = "button"data-dismiss = "modal"> <span aria-hidden = "true"> </span> 닫기> <버튼 유형 "> aria-hidden = "true"> </span> 저장 </div> </div> </div> </div> </div> </div> <script src = "~/scripts/extensions/knockout.edit.js"> </script> <script type = "text/javaScript"> $ (function () {var model = @html.raw (newtonsoft.json.json.json.json.json.sonconconedoverd ViewModel = {cormid : "formedit", editmodel : model, urls : {제출 : model.id == 0? "/user/uddate"}, validator : {name : {notempty : {이름이 비어있을 수 없습니다! '}}}}}}}; KO.BindingEditViewModel (ViewModel); </script> edit.cshtml물론 코드도 약간 수정해야합니다. 배경의 해당 엔티티 모델이 구축되는 한 사용자 정의 템플릿 페이지를 추가하면 프론트 엔드에서 두 개의 새로운 사용자 정의보기 만 만들면 간단한 추가, 삭제, 수정 및 검색이 JS 코드 문장을 작성하지 않고 완료 할 수 있습니다.
3. 선택 구성 요소의 바인딩
위의 내용은 T4 포장 첨가, 삭제, 수정 및 검색의 구문을 소개합니다. 페이지의 모든 구성 요소는 기본적으로 텍스트 상자입니다. 그러나 실제 프로젝트에서 많은 쿼리 및 편집 페이지에는 드롭 다운 상자가 표시됩니다. 드롭 다운 상자를 어떻게 처리해야합니까? 비밀을 지키지 않으면 해결책을 제시하십시오. 예를 들어, 드롭 다운 상자의 데이터 소스를 편집 페이지의 백그라운드에 배치 할 수 있습니다.
사용자 엔티티
[DataContract] 공개 클래스 사용자 {[Datamember] public int id {get; 세트; } [datamember] 공개 문자열 이름 {get; 세트; } [datamember] public String fullName {get; 세트; } [datamember] public int age {get; 세트; } [datamember] public String des {get; 세트; } [datamember] public dateTime createTime {get; 세트; } [datamember] public String strcreateTime {get; 세트; } [datamember] public String DepartmentId {get; 세트; } [datamember] 공공 개체 부서 {get; 세트; }}그런 다음 페이지를 편집하십시오
public actionResult edit (사용자 모델) {model.departments = besignmodel.getData (); return view (model);}그런 다음 프론트 엔드를 바인딩하십시오.
<div> <label for = "txt_des"> department </label> <select id = "sel_dept"data-bind = "옵션 : editModel.DepArtments, 옵션 스테 텍스트 : 'name', 'ID', value : editModel.departModel.departmentId"> </div>
JS 코드를 수정할 필요가 없습니다. 추가 또는 편집 할 때 부서 필드를 뷰 모델에 자동으로 추가 할 수 있습니다.
물론, 우리의 많은 프로젝트에서 사용하는 드롭 다운 박스는 단순히 선택적이지 않습니다. 간단한 선택 스타일은 실제로 못 생겼기 때문에 이전에 블로거가 공유 한 Select2, MultiSelect 등과 같은 많은 선택 구성 요소가 생성됩니다. 이러한 구성 요소를 사용하여 Select를 초기화 할 때 인터페이스의 드롭 다운 상자는 더 이상 간단한 선택 태그가 아니지만 구성 요소가 사용자 정의하는 다른 많은 태그로 구성됩니다. 위의 내용에 따라 직접 초기화 할 수 있는지 여부를 예로 들어 Select2 구성 요소를 예로 들어 봅시다.
페이지에서 초기화 된 JS 코드를 편집하기 위해 마지막 문장을 추가합니다.
<script type = "text/javaScript"> $ (function () {var model = @html.raw (newtonsoft.json.jsonconvert.serializeObject (model)); var viewModel = {cormid : "formedit", editModel : model, urls : {제출 : model.id == 0? " "/user/update"}, 유효성 검사기 : {fields : {name : {validator : {message : '이름은 비어있을 수 없습니다!'}}}}}};추가 및 편집을 통해 이것은 실제로 실현 가능합니다! 이유 분석, Page HTML이 SELECT2 구성 요소를 초기화 한 후에 페이지 HTML이 변경되지만 구성 요소는 결국 원래 선택 컨트롤에서 선택된 값을 나타냅니다. Select2를 제외하고 다른 선택 초기화 구성 요소가 다음과 같은지 모르겠습니다. 그러나 여기에는 설명해야 할 사항이 있습니다. Select2를 초기화하기 전에 드롭 다운 박스의 옵션은 값에 바인딩되어야합니다. 즉, 구성 요소의 초기화는 KO.AppLyBinding () 후에 배치되어야합니다.
4. 요약
이 시점에서 KO는 부트 스트랩 가능한 템플릿 생성과 결합 된 일부 컨트롤 사용을 기본적으로 사용할 수 있으며 물론 여전히 개선해야합니다. 나중에 시간이 있다면 블로거는 가장 일반적인 날짜 제어와 같은 다른 프론트 엔드 구성 요소와 KO의 조합을 분류합니다. 궁금한 점이 있으면 메시지를 남겨 주시면 편집자가 제 시간에 모든 사람에게 답장을 드리겠습니다. Wulin.com 웹 사이트를 지원해 주셔서 대단히 감사합니다!