近
最近の学校採用シーズンでは、インターンシップ部門が学校採用ソフトウェア サービスを提供していますが、オンライン ユーザーが多く、オンラインに移行するための新機能はあまり多くありません。Ledi は主に再構築を担当しています。今年卒業し、すでに独立して事業開発に取り組むことができる新しい同僚のことを考えてください。 Leti は最近 MVC アーキテクチャについての理解を深め、同僚の Xinsheng からフロントエンドの開発仕様についてもある程度学びました。改めて Xinsheng に感謝したいと思います。教えと無私の援助。
Leti と Xinsheng の最大の違いは、Xinsheng は問題の処理と解決に関して深い理論的基礎を持っていることです。つまり、彼は理由を知っており、単なるプログラマーではなく、独自の思考を持ち、最適化する方法を知っています。コードとパフォーマンス。楽迪は新生から彼の理論体系と問題解決方法を学びました。新生の例で急速に差を縮めます。
この記事で説明するビューは、採用プロジェクトのユニットの応募者機能の下にあります。では、なぜリファクタリングが必要なのでしょうか?
この再構築作業では、次の 2 つの理由があると考えています:
テンプレート内の処理ロジックが複雑すぎる、構造と処理ロジックの分離に準拠していない、コードの可読性が低い高い。
上に示したように、テンプレートは複数の if-else ネストを使用し、さまざまな <% %> を組み合わせて HTML と JS コードを分離しています。性比が低く、改造には適さない。
同じ種類の複数のビューのロジックと構造にはわずかな違いがありますが、ソース コードには独自のロジックとビューのセットがあり、コードの冗長性が高くなります。後のメンテナンスに役立ちません。
Ledi の元の解決策は、各ビューに渡されたモデル値をデバッグすることであり、ビューの構築の違いはモデル値の Ctype 属性にあることがわかりました。
<select data-name="<%=Name%>" data-obj="<%=controlData.Object%>" class="souce_name search_view width130"> <option value="">不限</option> <%if(typeof searchItems !="undefined"){%> <%if(searchItems.Value!=null){%> <%_.each(dataSource, function(item){%> <%if(searchItems.Value.length>0){%> <%_.each(searchItems.Value, function(item1){%> <%if(item1!=item.Value){%> <option value="<%=item.Value%>"><%=item.Text%></option> <%}else{%> <option value="<%=item.Value%>" selected="selected"><%=item.Text%></option> <%}%> <%})%> <%}else{%> <option value="<%=item.Value%>"><%=item.Text%></option> <%}%> <%})%> <%}else{%> <%_.each(dataSource, function(item){%> <option value="<%=item.Value%>" title="<%=item.Text%>"><%=item.Text%></option> <%})%> <%}%> <%}else{%> <%_.each(dataSource, function(item){%> <option value="<%=item.Value%>"><%=item.Text%></option> <%})%> <%}%></select>
上記の考え方で、次の作業は、前のテキスト比較で得られた差分に基づいてブロック処理を実行することです。つまり、アトミック関数を構築し、どのアトミック ブロックが存在するかを判断し、それらをまとめて一般クラスに書き込むことです。違いはアトミック クラスの空のメソッドの形式に存在し、一般的なクラスの空の関数はサブ関数でオーバーライドされ、パーソナライズされたカスタマイズを実現します。
textInputAttr:function(){ var isDefault = this.model.get("IsDefault"); var searchItems = this.model.get("searchItems"); var defaultVal = this.model.get("DefaultVal"); var cType =this.model.get("Ctype"); if(cType==1){ this.$el.find("input[type='text']").addClass("search_box_prev"); this.$el.find("input[type='text']").attr("data-rule-maxlength",300); }else{ this.$el.find("input[type='text']").addClass("souce_name"); this.$el.find("input[type='text']").attr("data-rule-maxlength",100); if(cType==23){ this.$el.find("input[type='text']").addClass("default_word"); } }//针对不同ctype设置input不同属性及值 if(cType==1){ if(typeof isDefault !="undefined"&&isDefault==1) { this.$el.find("input[type='text']").attr("defaultValue",defaultVal); };// 设置defaultValue属性 } if(typeof searchItems !="undefined") { if(searchItems.Value!=null) { this.$el.find("input[type='text']").attr("value",searchItems.Value[0]); } } else{ if(cType==1){ if(typeof isDefault !="undefined"&&isDefault==1){ this.$el.find("input[type='text']").attr("value",defaultVal); } } }//设置value属性值 }, checkInputAttr:function(){ var searchItems = this.model.get("searchItems"); var cType =this.model.get("Ctype"); if(cType==1){ this.$el.find("input[type='checkbox']").addClass("search_box_any"); }else{ this.$el.find("input[type='checkbox']").addClass("souce_name"); } if((typeof searchItems !="undefined")&&(searchItems.Value!=null)&&(searchItems.Value.length>0)){ _.each(searchItems.Value,function(item,value){ var valLength = (cType==1)?(searchItems.Value.length):(searchItems.Value.length-1);//判断采用何种表达式 if(valLength==value){ if(item){ this.$el.find("input[type='checkbox']").attr("value",item); if(searchItems.Value[value]=="true") this.$el.find("input[type='checkbox']").attr("checked","checked"); }else{ this.$el.find("input[type='checkbox']").attr("value",""); } } }); }else{ this.$el.find("input[type='checkbox']").attr("value",""); } }//checkbox设置
一部の論理コードは、異なるビューを持つ異なる変数のみを持ち、親クラスで変数を含むメソッドを構築し、サブクラスで属性値を設定し、それを親クラスのメソッドに渡します。 :
var SingleInputView = Talent.ItemView.extend({ onBeforeRender:function(){ this.standLabel();//标准化标签 }, onRender:function(){ this.textMaxlen(this.maxlength); this.setCheckboxVal(this.minus); this.SetTextInput(); this.SetCheckboxInput(); }, standLabel:function(){ var label = this.model.get("Label"); if((label.length != 7)&&(label.length>6)) { this.model.set({"Label":label.substring(0,6)+"…"}); } }, textAddClass:function(){ }, textMaxlen:function(length){ this.$el.find("input[type='text']").attr("data-rule-maxlength",length); }, setTextDefaultVal:function(){ }, setTextVal:function(){ var isDefault = this.model.get("IsDefault"); var searchItems = this.model.get("searchItems"); var defaultVal = this.model.get("DefaultVal"); if(typeof searchItems !="undefined") { if(searchItems.Value!=null) { this.$el.find("input[type='text']").val(searchItems.Value[0]); } } }, checkboxAddClass:function(){ }, setCheckboxVal:function(minus){ var searchItems = this.model.get("searchItems"); if((typeof searchItems !="undefined")&&(searchItems.Value!=null)&&(searchItems.Value.length>0)){ _.each(searchItems.Value,function(item,value){ var valLength =searchItems.Value.length-minus;//判断采用何种表达式 if(valLength==value){ if(item){ this.$el.find("input[type='checkbox']").val(item); if(searchItems.Value[value]=="true") this.$el.find("input[type='checkbox']").attr("checked","checked"); }else{ this.$el.find("input[type='checkbox']").val(""); } } }); }else{ this.$el.find("input[type='checkbox']").val(""); } }, });
一般クラスとサブビュー メソッドを自動的に呼び出すために、親クラスでレンダリング後の onRender コールバック関数を構築しました:
setCheckboxVal:function(minus){ var searchItems = this.model.get("searchItems"); if((typeof searchItems !="undefined")&&(searchItems.Value!=null)&&(searchItems.Value.length>0)){ _.each(searchItems.Value,function(item,value){ var valLength =searchItems.Value.length-minus;//判断采用何种表达式 if(valLength==value){ if(item){ this.$el.find("input[type='checkbox']").val(item); if(searchItems.Value[value]=="true") this.$el.find("input[type='checkbox']").attr("checked","checked"); }else{ this.$el.find("input[type='checkbox']").val(""); } } });
ここで 2 つの this が使用されています .SetTextInput() と this .SetCheckboxInput() の両方のメソッド、それぞれが子クラス内で実行され、異なる子クラス関数を追加実行します:
onRender:function(){ this.textMaxlen(this.maxlength); this.setCheckboxVal(this.minus); this.SetTextInput(); this.SetCheckboxInput(); }
通用クラス、また一つに使用されますBeforeRender回调方法,用データをテンプレートにレンダリングする前に処理します。
onBeforeRender:function(){ this.standLabel();//标准化标签 }
通过对以上重构分析,我们可以得出重构的大体方向: