![画像](https://habrastorage.org/getpro/habr/post_images/27d/210/ba8/27d210ba8f21f85641c982fd89c4722a.jpg)
免責事項 :この記事は批判( ハブに落ちた)への応答であり、人気のあるToDo MVCアプリケーションの例でのIMLの可能性を明らかにしています。
袖口を得た
批判は、私の前の記事で生じた議論に関連して非常にソフトな言葉です。なぜなら、それは非常に不愉快なコメントがあったphoto打に似ていたからです(写真では妄想的です)。
- AngularJsコードは噴水ではありません -公式サイトと人気ガイドからのものでしたが、反論するのは難しいです
- 弱い例 -スクリプトではなくタスクに重点が置かれましたが、より包括的なソリューションが可能性をより完全に明らかにすることに同意します(オープンソースのプロジェクトの一部を提案しましたが、無視されました)
- AngularJsを知りませんか? -明らかな理由で、これはAngularJsの開発者に大打撃を与えました
- JSトピックは重大な間違いです。asp.netmvcを使用しないと、入力されたTextBoxForやその他の拡張機能の魅力を理解するのが難しいからです。
どうして?
コメントでは、IMLの機能の証明として「Todo MVC」を実装しようとすることを提案しましたが、今度はその結果を確認します。 まず、jsフレームワーク用に提示されたものと1つの違いがあるデモ版は、ストレージがローカルストレージではなくデータベースとソースコードを使用していることです。 実装の過程で、クライアントにすべてのロジック(地下室の計算、要素の非表示など)を構築しましたが、実際のタスクでは、IMLコードを持ち、計算方法と表示方法を知っている「ポイントワイズ」要素を更新する方が簡単です(必要な場合があります) 。
コードレビュー
今回のストーリーテリングスタイルは、あるソリューションと別のソリューションを比較するものではありません(そうでない場合、資料の量は多くなります)が、todoアプリケーションの実装時に取得されるコードのレビューです。 IMLの実装にはサーバーパーツもありますが、より客観的な比較のために解決するタスクを均等化するために、クライアントパーツのみに焦点を当てます。
何で構成されていますか
コードは3つのビューに分割されました
- インデックス -メインページ(および実際にはブラウザ用の唯一のページ)
- Todo_List_Tmpl-中央リストを作成するためのテンプレート
- Todo_Footer_Tmpl-インジケーター付きの地下室を構築するためのテンプレート
![画像](https://habrastorage.org/getpro/habr/post_images/0e9/e3e/3f0/0e9e3e3f020f9c79887570c846c5d4be.png)
インデックス(3つの要素で構成されます)
TODOフォームを追加
@using (Html.When(JqueryBind.Submit) .DoWithPreventDefault() .Submit(options => { options.Url = Url.Dispatcher() .Push(new AddTodoCommand { ClientId = Selector.Incoding.Cookie(CookieManager.ClientId) }); }) .OnSuccess(dsl => { dsl.WithId(containerId).Core().Trigger.Incoding(); dsl.Self().Core().Form.Reset(); }) .AsHtmlAttributes() .ToBeginTag(Html, HtmlTag.Form)) { @Html.TextBoxFor(r => r.Title, new { placeholder = "What needs to be done?", autofocus = "" }) }
注:私はすぐに、「はい、深刻ではありません。もっと多くのコードがあります。どこにでもコピーして、人々がどうするかを確認してください!!!」というスタイルのフレーズを期待しています-これに対して、C#拡張機能に直面して、IML構造をラップできる引数があります。 記事の後半では、C#拡張機能を使用して、問題に対する代替ソリューション( GibHubのリポジトリと再設計されたコード)が提供されます。
何に?
- When(JqueryBind.Submit) -ターゲットイベントを示します
- DoWithPreventDefault-イベントの動作(ブラウザーハンドラーをキャンセル)
- 送信 -ajax経由でフォームを送信します
注:提示された実装に関するコメント:
- フォームが送信されるURLは、オプションで指定されます(フォームのaction属性を介してではありません)
- ClientIdはフォームを非表示としてレンダリングできます。これは、InitIncodingによると、Cookieから値を入力して、パラメーターなしでSubmitを呼び出します。
- OnSuccess-送信成功後に実行
- containerIdへのIncodingのトリガー-Container要素のすべてのIMLコードを実行します(以下の説明)
注:複数のWhenを使用できます。これにより、異なるイベント(異なるIMLコード)にバインドできるため、トリガーインコーディングはすべてのチェーンを開始します。
- フォームのリセット -フォーム要素の値をリセットします
- containerIdへのIncodingのトリガー-Container要素のすべてのIMLコードを実行します(以下の説明)
- AsHtmlAttributes-asp.net mvc形式(RouteValueDictionary)でIMLコードを収集します
- ToBeginTag-受信した属性をフォームタグにパックします(Html.BeginFormとしての動作原理)
注:Html.BeginForm(“action”,”controller”,Post,iml.AsHtmlAttributes())
を使用できますHtml.BeginForm(“action”,”controller”,Post,iml.AsHtmlAttributes())
TODO追加フォーム(代替)
@using (Html.Todo().BeginForm(setting => { setting.TargetId = containerId; setting.Routes = new { ClientId = Selector.Incoding.Cookie(CookieManager.ClientId) }; })) { @Html.TextBoxFor(r => r.Title, new { placeholder = "What needs to be done?", autofocus = "" }) }
注:コードが少なくなり、最も重要なこととして、特定のプロジェクトのニーズに合わせてメソッドを拡張(検証、送信後のリダイレクトなど)できるようになりました。
ボンネットの下
注:コードはほとんどのasp.net mvc開発者に馴染みがありますが、「通常の」パラメータの代わりに、設定クラスを受け入れる匿名メソッドを渡すことに注意してください。
public class BeginFormSetting { public string TargetId { get; set; } public object Routes { get; set; } } public BeginTag BeginForm(Action configure) { var setting = new BeginFormSetting(); configure(setting); var url = new UrlHelper(HttpContext.Current.Request.RequestContext); return this.helper.When(JqueryBind.Submit) .DoWithPreventDefault() .Submit(options => { options.Url = url.Dispatcher() .Push(setting.Routes); }) .OnSuccess(dsl => { dsl.WithId(setting.TargetId).Core().Trigger.Incoding(); dsl.Self().Core().Form.Reset(); }) .AsHtmlAttributes() .ToBeginTag(this.helper, HtmlTag.Form); }
注:コードはほとんどのasp.net mvc開発者に馴染みがありますが、「通常の」パラメータの代わりに、設定クラスを受け入れる匿名メソッドを渡すことに注意してください。
コンテナ
@(Html.When(JqueryBind.InitIncoding | JqueryBind.IncChangeUrl) .Do() .AjaxGet(Url.Dispatcher() .Query(new { ClientId = Selector.Incoding.Cookie(CookieManager.ClientId), Type = Selector.Incoding.HashQueryString(r => r.Type) }) .AsJson()) .OnSuccess(dsl => { string urlTmpl = Url.Dispatcher() .Model(new GetTodoByClientQuery.Tmpl { FooterId = footerId }) .AsView("~/Views/Home/Todo_List_Tmpl.cshtml"); dsl.Self().Core().Insert.WithTemplateByUrl(urlTmpl).Html(); dsl.WithId(footerId).Core().Trigger.Incoding(); }) .AsHtmlAttributes(new { id = containerId }) .ToDiv())
何に?
- When(JqueryBind.InitIncoding | IncChangeUrl) -ターゲットイベントを指定します
- InitIncoding-要素がページに最初に表示されたときに発生します(ajaxや通常は関係ありません)
- IncChangeUrl-ハッシュが変更されるとトリガーされます
- 実行 -イベントの動作
- AjaxGet -ajaxリクエストが実行されるURLを指定します
- ClientId-Cookieから値を取得します
- タイプ-ハッシュクエリ文字列から値を取得
- OnSuccess - AjaxGetが正常に完了した後に実行する
- テンプレートによって自分自身にデータを挿入 -リクエスト(json)から受け取ったデータをテンプレート(以下のTodo_List_Tmpl)を介して現在の要素に挿入します。
注:テンプレートは使用可能なセレクターから取得できます。たとえば、以前は、メインのセレクターはJquery.Idでしたが、ajaxロードが望ましい
- footerIdへのインコーディングのトリガー -フッター要素のすべてのIMLコードを実行します(以下の説明)
- テンプレートによって自分自身にデータを挿入 -リクエスト(json)から受け取ったデータをテンプレート(以下のTodo_List_Tmpl)を介して現在の要素に挿入します。
- AsHtmlAttributes -IMLコードを収集し、値containerId(guid)をId属性に設定します
注:idとしてguidを使用すると、ページ上の要素の一意性が保証されます。特に、単一ページのアプリケーションに当てはまります
- ToDiv-受信した属性をdivタグにパックします
注:ToDivはRouteValueDictionaryのC#拡張であるため、独自のオプションを簡単に記述できます。
コンテナ(代替方法)
@Html.Todo().Container(setting => { setting.Id = containerId; setting.Url = Url.Dispatcher() .Query(new { ClientId = Selector.Incoding.Cookie(CookieManager.ClientId), Type = Selector.Incoding.HashQueryString(r => r.Type) }) .AsJson(); setting.Tmpl = Url.Dispatcher() .Model(new GetTodoByClientQuery.Tmpl { FooterId = footerId }) .AsView("~/Views/Home/Todo_List_Tmpl.cshtml"); setting.DependencyId = footerId; })
注:将来、ブロックuiまたは他のアクションを追加する必要がある場合、一元的に実行できるようになりました
ボンネットの下
public class ContainerSetting { public string Id { get; set; } public string Url { get; set; } public string Tmpl { get; set; } public string DependencyId { get; set; } } public MvcHtmlString Container(Action configure) { var setting = new ContainerSetting(); configure(setting); return helper.When(JqueryBind.InitIncoding | JqueryBind.IncChangeUrl) .Do() .AjaxGet(setting.Url) .OnSuccess(dsl => { dsl.Self().Core().Insert.WithTemplateByUrl(setting.Tmpl).Html(); dsl.WithId(setting.DependencyId).Core().Trigger.Incoding(); }) .AsHtmlAttributes(new { id = setting.Id }) .ToDiv(); }
フッター
@(Html.When(JqueryBind.None) .Do() .Direct(new FooterVm { AllCount = Selector.Jquery.Class("toggle").Length(), IsCompleted = Selector.Jquery.Class("toggle").Is(JqueryExpression.Checked), CompletedCount = Selector.Jquery.Class("toggle") .Expression(JqueryExpression.Checked) .Length(), })) .OnSuccess(dsl => { string urlTmpl = Url.Dispatcher() .Model(new TodoFooterTmplVm { ContainerId = containerId }) .AsView("~/Views/Home/Todo_Footer_Tmpl.cshtml"); dsl.Self().Core().Insert.Prepare().WithTemplateByUrl(urlTmpl).Html(); }) .AsHtmlAttributes(new { id = footerId }) .ToDiv())
- When(JqueryBind.None) -ターゲットイベントを指定します
- なし -カスタムイベントを文字列「MySpecialEvent」として指定できる場合、多くのシナリオで十分であることが実際に示されています。
- 実行 -イベントの動作
- 直接 -アクションを実行しないが、データを処理できるアクションスタブと見なすことができます
- AllCount- 「トグル」クラスでオブジェクトの数を取得します
注:(長さの代わりに)メソッド拡張を使用してjqueryメソッドを呼び出すことができ、JquerySelectorExtendを介してC#拡張を記述することもできます。
- IsCompleted- 「toggle」クラスでマークされたオブジェクトの存在を確認します
注:既製のjqueryセレクターの十分な機能がない場合は、Selector.Jquery.Custom(「jqueryセレクター」)を使用できます
- CompletedCount- 「toggle」クラスでマークされたオブジェクトの数を取得します
- AllCount- 「トグル」クラスでオブジェクトの数を取得します
- OnSuccess - AjaxGetが正常に完了した後に実行する
- テンプレートによって準備データを自分自身に挿入する -準備されたデータをテンプレートから直接(以下のTodo_Footer_Tmpl)から現在の要素に挿入する
注:データを挿入する前に準備すると、フィールドにあるセレクターが実行されます。
- AsHtmlAttributes -IMLコードの収集
- ToDiv-受信した属性をdivタグにパックします
Todoリストtmpl
ToDoリストを作成するためのレイアウトテンプレート
@using (var template = Html.Incoding().Template()) { <ul> @using (var each = template.ForEach()) { @using (each.Is(r => r.Active)) { @createCheckBox(true) } @using (each.Not(r => r.Active)) { @createCheckBox(false) } <li class="@each.IsInline(r=>r.Active,"completed")"> <label>@each.For(r=>r.Title)</label> </li> </ul> }
注:ソースコードは、たとえば表示されているものよりも大きい(要素のリモートロジック)が、これはテンプレートの説明の便宜上作成されている
何に?
- Html.Incoding()。Template() -テンプレートを構築するコンテキストを(使用中に)開きます
- template.ForEach() -(使用中の)要素の列挙を開始します
- using(each.Is(r => r.Active)) -条件の以前のバージョンは「1行」でしたが、より複雑なアクションを実行する必要があることがよくあります。
- createCheckBox-チェックボックスを作成するための匿名C#関数(以下の説明)
- each.IsInline(r => r.Active、「completed」) -Activeフィールドがtrueの場合、「completed」を返します
注:IsNotLineおよびIsLineも使用できます。
- each.For(r => r.Title)-Titleフィールドの値を出力します
注:フィールドへのすべての呼び出しは、指定されたモデルに基づいています(はい、もう一度入力することについて話している)
その他のアイテム
ボタンデル
@(Html.When(JqueryBind.Click) .Do() .AjaxPost(Url.Dispatcher().Push(new DeleteEntityByIdCommand { Id = each.For(r => r.Id), AssemblyQualifiedName = typeof(Todo).AssemblyQualifiedName })) .OnBegin(r => { r.WithSelf(s => s.Closest(HtmlTag.Li)).Core().JQuery.Manipulation.Remove(); r.WithId(Model.FooterId).Core().Trigger.Incoding(); r.WithId(toggleAllId).Core().Trigger.None(); }) .AsHtmlAttributes(new { @class = "destroy" }) .ToButton(""))
何に?
- When(JqueryBind.Click) -ターゲットイベントを示します
- 実行 -イベントの動作
- AjaxPost -ajaxリクエストを行うURLを示します
- Id -Todoからの値
- AssemblyQualifiedName-要素タイプ(または他のC#コード)の名前を取得します
- OnBegin-アクションの前に実行(AjaxPost)
注:もちろん、サーバーでエラー(タイムアウトなど)が発生し、AjaxPostを呼び出す前にOnBeginが動作するためトランザクションが完了しないため、OnSuccessを使用する方が適切ですが、jsフレームワークのTodoMVCの例ではローカルストレージ(これはajaxよりも高速です)、したがって、私は多くのチートはしませんでしたが、速度を落とさないようにしました
- 最も近いLIを削除 - 最も近いLIを削除
- フッターIDへのインコーディングのトリガー -フッター要素のすべてのIMLコードを実行します(上記の説明)
- すべてを切り替えるにはnoneをトリガーします -Toggle All要素に対してIMLコード(Noneチェーンのみ)を実行します(以下の説明)
注:両方(フッターとすべてを切り替える)で同じトリガーを呼び出す必要がある場合は、次のオプションを使用できます。
dsl.WithId(Model.FooterId, toggleAllId).Core().Trigger.Incoding();
- AsHtmlAttributes -IMLコードの収集
- ToButton-受信した属性をボタンタグにパックします
注:ToButtonを使用すると、コンテンツを指定できますが、この場合、CSSを介して画像が設定されるため、必要ありません。
Button Del(代替)
@Html.Todo().Verb(setting => { setting.Url = Url.Dispatcher().Push(new DeleteEntityByIdCommand { Id = each.For(r => r.Id), AssemblyQualifiedName = typeof(Todo).AssemblyQualifiedName }); setting.OnBegin = dsl => { dsl.WithSelf(s => s.Closest(HtmlTag.Li)).Core().JQuery.Manipulation.Remove(); dsl.WithId(Model.FooterId).Core().Trigger.Incoding(); dsl.WithId(toggleAllId).Core().Trigger.None(); }; setting.Attr = new { @class = "destroy" }; })
注:OnBeginはActionを受け入れます。これにより、IMLを実装することで拡張機能を簡単に拡張できます。 (さらに例があります)
ボンネットの下
注:Verbはいくつかのシナリオで使用するため、オプションのパラメーターを作成し、nullをチェックし、デフォルト値を設定することも簡単です
public class VerbSetting { public string Url { get; set; } public Action<IIncodingMetaLanguageCallbackBodyDsl> OnBegin { get; set; } public Action<IIncodingMetaLanguageCallbackBodyDsl> OnSuccess { get; set; } public object Attr { get; set; } public string Content { get; set; } } public MvcHtmlString Verb(Action<VerbSetting> configure) { var setting = new VerbSetting(); configure(setting); return this.helper.When(JqueryBind.Click) .Do() .AjaxPost(setting.Url) .OnBegin(dsl => { if (setting.OnBegin != null) setting.OnBegin(dsl); }) .OnSuccess(dsl => { if (setting.OnSuccess != null) setting.OnSuccess(dsl); }) .AsHtmlAttributes(setting.Attr) .ToButton(setting.Content); }
注:Verbはいくつかのシナリオで使用するため、オプションのパラメーターを作成し、nullをチェックし、デフォルト値を設定することも簡単です
チェックボックスが完了しました
var createCheckBox = isValue => Html.When(JqueryBind.Change) .Do() .AjaxPost(Url.Dispatcher().Push(new ToggleTodoCommand { Id = each.For(r => r.Id) })) .OnBegin(dsl => { dsl.WithSelf(r => r.Closest(HtmlTag.Li)) .Behaviors(inDsl => { inDsl.Core().JQuery.Attributes.RemoveClass("completed"); inDsl.Core().JQuery.Attributes.AddClass("completed") .If(builder => builder.Is(() => Selector.Jquery.Self())); }); dsl.WithId(Model.FooterId).Core().Trigger.Incoding(); dsl.WithId(toggleAllId).Core().Trigger.None(); }) .AsHtmlAttributes(new {@class="toggle" }) .ToCheckBox(isValue);
注:razorページ内では、匿名のC#関数またはRazorヘルパーを使用できます。これにより、同じタイプのタスクを集約できます。
何に?
- When(JqueryBind.Change)-ターゲットイベントを示します
- 実行-イベントの動作
- AjaxPost-ajaxリクエストを行うURLを示します
注:AjaxPostとAjaxGetは、多くの高度な設定を持つ「名前付き」バージョンのAjaxです。
- OnBegin-アクションの前に実行(AjaxPost)
- 最も近いLIのクラスを削除 - 最も近いLIから「完成した」クラスを削除します
- selfがtrueの場合、最も近いLIにクラスを追加します -クラス「完了」を追加
注:IMLでは実装されていませんが、バージョン2.0では計画されています
- AsHtmlAttributes-IMLコードを収集し、クラス属性に「トグル」値を設定します
- ToCheckBox-受信した属性を入力[type = checkbox]タグにパックします
タイプtodoでフィルター
@{ const string classSelected = "selected"; var createLi = (typeOfTodo,isFirst) => Html.When(JqueryBind.InitIncoding) .Do() .Direct() .OnSuccess(dsl => { var type = Selector.Incoding.HashQueryString(r => r.Type); if (isFirst) dsl.Self().Core().JQuery.Attributes.AddClass(classSelected).If(s => s.Is(() => type == "")); dsl.Self().Core().JQuery.Attributes.AddClass(classSelected).If(s => s.Is(() => type == typeOfTodo.ToString())); }) .When(JqueryBind.Click) .Do() .Direct() .OnSuccess(dsl => { dsl.WithSelf(r => r.Closest(HtmlTag.Ul).Find(HtmlTag.A)).Core().JQuery.Attributes.RemoveClass(classSelected); dsl.Self().Core().JQuery.Attributes.AddClass(classSelected); }) .AsHtmlAttributes(new { href = "#!".AppendToHashQueryString(new { Type = typeOfTodo }) }) .ToLink(typeOfTodo.ToString()); } <li> @createLi(GetTodoByClientQuery.TypeOfTodo.All,true) </li> <li> @createLi(GetTodoByClientQuery.TypeOfTodo.Active,false) </li> <li> @createLi(GetTodoByClientQuery.TypeOfTodo.Completed,false) </li>
注:カミソリビューの一部としての匿名関数の実装の別の例
何に?
- When(JqueryBind.InitIncoding) -ターゲットイベントを示します
- 実行 -イベントの動作
- 直接 -何もしない
- OnSuccess-正常終了後に実行
注:Directの場合、OnBeginとOnSuccessの違いはありませんが、OnErrorとOnBreakは他と同様に機能します
- var type-変数を宣言し、それを式で使用します
- IsFirstがtrueで、タイプが空の場合、selfにクラスを追加します -現在の要素が最初でタイプが空の場合、クラスを追加します
- タイプが現在のタイプである場合、selfにクラスを追加します -タイプがtypeOfTodo引数と等しい場合、現在の要素にクラスを追加します
- When(JqueryBind.Click) -ターゲットイベントを示します
- 実行 -イベントの動作
注:場所を更新するにはブラウザが必要なので、リンクの動作をキャンセルしません
- 直接 -何もしない
- クラスの削除 -最も近いULにあるすべてのAから選択したクラスを削除します
- クラスをselfに追加-選択したクラスを現在の要素に追加します
- AsHtmlAttributes -IMLコードを収集し、href属性も設定します
タイプtodoによるフィルター(代替方法)
<li> @Html.Todo().LiHash(setting => { setting.IsFirst = true; setting.SelectedClass = classSelected; setting.Type = GetTodoByClientQuery.TypeOfTodo.All; }) </li>
無条件の利点!
IMLの利点は何ですか、前の記事で開示しようとしましたが、説得力がなかったので、もう一度試してみます。
- タイピング -もちろん、誰もがプリズムを通してタイピングを調べ、誰かがあなたがより多くのコードを書かなければならないと考える(これは本当です)、他の人は型付けされていない言語に固有の柔軟性に欠けていますが、IMLは主にC#ですので、それを選んだ開発者彼らはこのプラスに感謝すると思う。
- 強力な拡張機能 -記事ではいくつか説明しましたが、実際にはもっと多くの拡張機能があります。私の言葉をバックアップするために、さらにいくつか説明します。
- ドロップダウン
@Html.For(r=>r.HcsId).DropDown(control => { control.Url = Url.Action("HealthCareSystems", "Shared"); control.OnInit = dsl => dsl.Self().Core().Rap().DropDown(); control.Attr(new { @class = "selectInput", style = "width:375px" }); })
注:OnInitはActionを受け入れます。これにより、IMLを実装することで拡張機能を簡単に拡張できます。
対話
@Html.ProjectName().OpenDialog(setting => { setting.Url = Url.Dispatcher() .Model<GroupEditProviderOrderCommand>() .AsView("~/Views/ProviderOrder/Edit.cshtml"); setting.Content = "Edit"; setting.Options = options => { options.Title = "Edit Order"; }; })
注:柔軟性を高めるために、Actionをフィールドとして使用できます。たとえば、setting.OptionsはActionです。
リストはどんどん増えていきますが、主なアイデアは、IMLを使用するとあらゆるタスクを実行でき、html拡張機能が再利用の問題を解決するということです。
- より強力な拡張機能
- グリッド -IMLに完全に構築(近い将来、ドキュメントが作成されます)
@(Html.ProjectName() .Grid<CTRPrintLogModel>() .Columns(dsl => { dsl.Template(@<text> <span>@item.For(r=>r.Comment)</span> </text>) .Title("Comment"); const string classVerticalTop = "vertical_top"; dsl.Bound(r => r.Time).Title("Time").HtmlAttributes(new { @class = classVerticalTop }); dsl.Bound(r => r.Version).Title("Type").HtmlAttributes(new { @class = classVerticalTop }); dsl.Bound(r => r.PrintDate).Title("Date"); dsl.Bound(r => r.Comment).Raw(); }) .AjaxGet(Url.RootAction("GetCTRPrintLogModel", "CTR")))
- タブ
@(Html.Rap() .Tabs<Enums.CarePlanTabs>() .Items(dsl => { dsl.AddTab(Url.Action("RedFlags", "PatientRedFlag"), Enums.CarePlanTabs.RedFlags); dsl.AddTab(Url.Action("Goals", "IncGoal"), Enums.CarePlanTabs.SelfCareGoals); dsl.AddTab(Url.Action("Index", "IncAppointment"), Enums.CarePlanTabs.Appointments); }))
注:HTML拡張機能に精通している開発者であれば、プロジェクトのニーズに合わせてこのような要素を構築できます。
- グリッド -IMLに完全に構築(近い将来、ドキュメントが作成されます)
- ハッシュの操作 -この記事では、IncChangeUrlレベルでのみ検討されましたが、
- Hash.Fetch-ハッシュの値を要素に入れます(サンドボックス)
- Hash.Insert / Update-要素からの値をハッシュに入れます
- Hash.Manipulate-現在のハッシュを微調整 (キーで設定/削除)できます
- AjaxHashはSubmitの類似物ですが、フォーム用ではなく、Hash用です。
- 挿入の操作 -TODOを使用して実装する必要はありませんでしたが、実際のプロジェクトのどこでも
- ジェネリックの挿入 -上記の例はすべて同じモデルで作成されましたが、受信データが「コンテナー」である場合がよくあります。これらの目的のため、挿入には、Forを介して作業するモデルの部分と、それぞれのテンプレートを指定する機能があります
Html.When(JqueryBind.InitIncoding) .Do() .AjaxGet(Url.Action("FetchComplex", "Data")) .OnSuccess(dsl => { dsl.WithId(newsDivId).Core().Insert.For<ComplexVm>(r => r.News).WithTemplateByUrl(urlNewsTmpl).Html(); dsl.WithId(contactDivId).Core().Insert.For<ComplexVm>(r => r.Contacts).WithTemplateByUrl(urlContactsTmpl).Html(); }) .AsHtmlAttributes() .ToDiv()
- ジェネリックの挿入 -上記の例はすべて同じモデルで作成されましたが、受信データが「コンテナー」である場合がよくあります。これらの目的のため、挿入には、Forを介して作業するモデルの部分と、それぞれのテンプレートを指定する機能があります
- 検証の操作(クライアントとしてのサーバー) -多くのjsフレームワークには検証用のツールがありますが、IMLは何度も述べたように、サーバーと統合され、追加のコードを書くことなく検証エンジン(FluentValidation、標準MVC)をサポートします。
- コマンドコード
if (device != null) throw IncWebException.For<AddDeviceCommand>(r => r.Pin, "Device with same pin is already exist");
- コードを表示
.OnError(dsl => dsl.Self().Core().Form.Validation.Refresh())
注:OnErrorハンドラーは、アクション(送信、ajaxpostなど)を呼び出す要素に添付する必要があります
- コマンドコード
- 少ないスクリプト -jsフレームワークプロジェクトへの情熱により、多くのjsファイルを書く必要がありますが、IMLには固定された(プラグインはカウントしません)ライブラリセットがあります
- 型付きテンプレート -私は一般的に型付けについて話しますが、テンプレートを構築するためにこれは特に重要です
- テンプレートエンジンの置換 -任意を選択しますが、構文は同じです
- 既製のインフラストラクチャ -IMLはIncoding Frameworkの一部であり、jsフレームワークとは異なり、プロジェクト開発用の完全な(サーバー/クライアント/ユニットテスト)インフラストラクチャがあり、相互に密接に統合されています。
おわりに
IMLでtodoを実装するとき、私はルールに固執しました:ページの更新が少ない、つまり、クライアント上のすべてを再カウントしましたが、(プロジェクトの)実践は、多くのアクションがクライアント上で不可能または優先されないため、多くの場合、サーバーがボトルネックであることを示しています
不可能(パフォーマンスのため):
- ページ分割 -データベースに数十万のレコードがある場合、この量はクライアントに正しく転送されません
- 注文は同じ理由です
- 同じ理由はどこですか
フィールド値に基づいて複雑な計算(税を含む注文の合計金額)などの計算を行うことは望ましくない場合があります。サーバーに要求を送信して(フィールドデータを使用して)結果を挿入する方が便利です。
再びIML))IML内では、次の方法で計算を解決できます。
- 単一の値
var val = Selector.Incoding.AjaxGet(url); dsl.WithId(yourId).Core().JQuery.Attributes.Val(val);
- データセット
dsl.With(r => r.Name(s => s.Last)).Core().Insert.For<ContactVm>(r => r.Last).Val(); dsl.With(r => r.Name(s => s.First)).Core().Insert.For<ContactVm>(r => r.First).Val(); dsl.With(r => r.Name(s => s.City)).Core().Insert.For<ContactVm>(r => r.City).Val();
IML(およびIncoding Framework)の機能については長い間話すことができますが、記事は大きくなることが判明したため、ツールの研究を続けたい人はネットワーク上の資料を見つけることができます。 IMLが一般的なjsフレームワークよりも悪くない問題を解決できることを証明することは非常に難しいことを理解していますが、次の記事では、オートコンプリート、ツリービュー、グリッド、さらに多くの機能を示す他の複雑なタスクの実装の概要があります。
PS批判やコメントにいつも満足しているように))) - ドロップダウン