美しいJavaScriptコード構造のためのオブジェクトの使用

エントリー


すべての良い一日。 祝日おめでとうございます。トピックに進みます。
単純なjQueryスニペットの作成を超えて、より複雑なユーザーインタラクションの開発を開始すると、コードはすぐに面倒でデバッグが困難になる可能性があります。 この記事では、オブジェクトリテラルデザインパターンを使用して、「動作の粒子」の観点からこれらの相互作用について考え始める方法を示します。

過去数年間、JavaScriptライブラリは、初心者の開発者にサイトとの対話機能を追加する機能を提供しました。 jQueryなどの一部の構文は非常に単純であるため、プログラミングの経験がゼロのユーザーは、ページに「添えもの」をすばやく追加する方法を学びました。 プラグインをグーグルで検索し、ユーザーコードから数十行をコピーして貼り付けるだけです。 結果-クライアントは感心し、履歴書にjQueryを追加します。

しかし、待ってください。 今、要件が変更されたとします。 これで、3つの要素で機能するコードは10で機能するはずです。 または、すべての識別子が異なるわずかに異なるアプリケーションでコードを再利用する必要があります。 プラグインの呼び出しやshow()やhide()のような2、3の行ではなく、コードで迷子にならないようにするにはどうすればよいですか?

オブジェクトリテラルの紹介


ロシア語でこの用語の定義を見つけようとして、 次のウィキペディアの記事に出会いました。 誰かがもっと正確な定義を与えるのを手伝ってくれたらありがたいです。

Object Literalプログラミングパターンは、コードを整理するための方法であり、最初に、コードが何をするのか、これを行うためにどの部分を配置する必要があるのか​​を考えさせます。 これは、コードが「グローバルネームスペースを汚染する」のを防ぐ良い方法でもあります。これは、すべてのプロジェクト(特に大きなプロジェクト)にとっては良い習慣です。 オブジェクトリテラルは、動作をカプセル化する方法でもあります。
var myObjectLiteral = {
myBehavior1 : function () {
/* - */
},

myBehavior2 : function () {
/* */
}
};


* This source code was highlighted with Source Code Highlighter .

人為的に単純化した例として、リストアイテムをクリックしたときにコンテンツを表示または非表示にするjQueryピースを提供します。
$( document ).ready( function () {
$( '#myFeature li' )
.append( '<div/>' )
.each( function () {
$( this ).find( 'div' )
.load( 'foo.php?item=' + $( this ).attr( 'id' ));
})
.click( function () {
$( this ).find( 'div' ).show();
$( this ).siblings().find( 'div' ).hide();
});
});


* This source code was highlighted with Source Code Highlighter .

簡単です。 それでも、この例でも、後で変更したいことがいくつかあります。たとえば、コンテンツをダウンロードするためのURLの設定方法、結果のコンテンツのダウンロード先などです。 オブジェクトリテラルビューでは、関数がこれらの側面を明確に区別します。 次のようになります。
var myFeature = {
config : {
wrapper : '#myFeature' ,
container : 'div' ,
urlBase : 'foo.php?item='
},

init : function (config) {
$.extend(myFeature.config, config);
$(myFeature.config.wrapper).find( 'li' ).
each( function () {
myFeature.getContent($( this ));
}).
click( function () {
myFeature.showContent($( this ));
});
},

buildUrl : function ($li) {
return myFeature.config.urlBase + $li.attr( 'id' );
},

getContent : function ($li) {
$li.append(myFeature.config.container);
var url = myFeature.buildUrl($li);
$li.find(myFeature.config.container).load(url);
},

showContent : function ($li) {
$li.find( 'div' ).show();
myFeature.hideContent($li.siblings());
},

hideContent : function ($elements) {
$elements.find( 'div' ).hide();
}
};

$( document ).ready( function () { myFeature.init(); });


* This source code was highlighted with Source Code Highlighter .

最初の例は非常に単純なので、オブジェクトリテラルオプションの方が大きくなっています。 実際、Object Literalメソッドはコードの行を保存するのに役立ちませんが、頭痛を回避するのに役立ちます。 Object Literalを使用して、コードを論理的な部分に分割し、将来変更する可能性のあるものをより簡単に見つけられるようにします。 コードを拡張可能にし、オーバーライドをデフォルト構成に渡す機能を提供しました。 また、何らかの自己文書化を行いました。今では、コードの一部を「簡単に」把握できるようになりました。 ニーズがこの例の範囲を超えて拡大するにつれて、オブジェクトリテラルアプローチの利点がより明確になります(以下を参照)。

別の例


私たちの仕事は、コンテンツをセクションに分割したユ​​ーザーインターフェイス要素を作成することです。 セクションをクリックすると、サブセクションのリストが表示されます。 ナビゲーションメニューのサブセクションをクリックすると、対応するコンテンツがコンテンツ領域に表示されます。 セクションをクリックすると、最初のサブセクションが表示されます。 最初のセクションは、ページのロード時に表示される必要があります( これが起こるべきです )。

ステップ1:HTML構造

優れたセマンティックHTMLを記述することは、優れたJavaScriptコードを記述するために不可欠です。したがって、タスクでHTMLがどのように見えるかを考えてみましょう。 HTMLは以下を行う必要があります。

これらの原則を考えると:
< div id ="myFeature" >
< ul class ="sections" >
< li >
< h2 >< a href ="/section/1" > Section 1 </ a ></ h2 >
< ul >
< li >
< h3 >< a href ="/section/1/content/1" > Section 1 Title 1 </ a ></ h3 >
< p > The excerpt content for Content Item 1 </ p >
</ li >
< li >
< h3 >< a href ="/section/1/content/2" > Section 1 Title 2 </ a ></ h3 >
< p > The excerpt content for Content Item 2 </ p >
</ li >
< li >
< h3 >< a href ="/section/1/content/3" > Section 1 Title 3 </ a ></ h3 >
< p > The excerpt content for Content Item 3 </ p >
</ li >
</ ul >
</ li >

< li >
< h2 >< a href ="/section/2" > Section 2 </ a ></ h2 >
< ul >
< li >
< h3 >< a href ="/section/2/content/1" > Section 2 Title 1 </ a ></ h3 >
< p > The excerpt content for Content Item 1 </ p >
</ li >
< li >
< h3 >< a href ="/section/2/content/2" > Section 2 Title 2 </ a ></ h3 >
< p > The excerpt content for Content Item 2 </ p >
</ li >
< li >
< h3 >< a href ="/section/2/content/3" > Section 2 Title 3 </ a ></ h3 >
< p > The excerpt content for Content Item 3 </ p >
</ li >
</ ul >
</ li >

< li >
< h2 >< a href ="/section/3" > Section 3 </ a ></ h2 >
< ul >
< li >
< h3 >< a href ="/section/3/content/1" > Section 3 Title 1 </ a ></ h3 >
< p > The excerpt content for Content Item 1 </ p >
</ li >
< li >
< h3 >< a href ="/section/3/content/2" > Section 3 Title 2 </ a ></ h3 >
< p > The excerpt content for Content Item 2 </ p >
</ li >
< li >
< h3 >< a href ="/section/3/content/3" > Section 3 Title 3 </ a ></ h3 >
< p > The excerpt content for Content Item 3 </ p >
</ li >
</ ul >
</ li >

</ ul >
</ div >


* This source code was highlighted with Source Code Highlighter .

セクションナビゲーションを表示するマークアップを有効にしていないことに注意してください。これらの部分はjQueryでのみ機能するため、jQueryによって追加されます。 JavaScriptを使用しないユーザーは、美しいセマンティックマークアップを取得できます。 (ここから何かが驚くべきまたは紛らわしいと思われる場合は、POSH(平凡なセマンティックHTML)およびプログレッシブ拡張をGoogleで検索できます)。

ステップ2:施設を準備する

タスクのオブジェクトを作成する最初のステップは、オブジェクトのスタブを作成することです。 スタブは、コード構造の計画に役立つプレースホルダーです。 オブジェクトには次のメソッドがあります。
var myFeature = {
'config' : { },
'init' : function () { },
'buildSectionNav' : function () { },
'buildItemNav' : function () { },
'showSection' : function () { },
'showContentItem' : function () { }
};


* This source code was highlighted with Source Code Highlighter .


myFeature.configは、 myFeature.configで言及myFeature.config価値があり、デフォルト値を1か所に保存します。 myFeature.init ()メソッドを定義するときに、デフォルト値をオーバーライドする機能を追加します。

ステップ3:コード

このスケルトンを構築したら、コードの記述を開始できます。 簡単なmyFeature.configオブジェクトとmyFeature.init ()メソッドを作成することから始めましょう。
'config' : {
// #myFeature
'container' : $( '#myFeature' )
},

'init' : function (config) {
// init()
if (config && typeof (config) == 'object' ) {
$.extend(myFeature.config, config);
}

// / DOM
//
myFeature.$container = myFeature.config.container;

myFeature.$sections = myFeature.$container.
//
find( 'ul.sections > li' );

myFeature.$section_nav = $( '<p/>' )
.attr( 'id' , 'section_nav' )
.prependTo(myFeature.$container);

myFeature.$item_nav = $( '<p/>' )
.attr( 'id' , 'item_nav' )
.insertAfter(myFeature.$section_nav);

myFeature.$content = $( '<p/>' )
.attr( 'id' , 'content' )
. insertAfter(myFeature.$item_nav);

//
// ""
myFeature.buildSectionNav(myFeature.$sections);
myFeature.$section_nav.find( 'li:first' ).click();

// HTML
myFeature.$container.find( 'ul.sections' ).hide();

// ( )
myFeature.initialized = true ;
}


* This source code was highlighted with Source Code Highlighter .

次に、 myFeature.buildSectionNav ()メソッドを作成します。
'buildSectionNav' : function ($sections) {

//
$sections.each( function () {

var $section = $( this );

//
$( '<li/>' )
// h2
//
.text($section.find( 'h2:first' ).text())

//
.appendTo(myFeature.$section_nav)

// data()
.data( 'section' , $section)

// click
.click(myFeature.showSection);
});


* This source code was highlighted with Source Code Highlighter .

次に、 myFeature.buildItemNav()メソッドを作成します。
'buildItemNav' : function ($items) {
$items.each( function () {

var $item = $( this );

//
$( '<li>' )

// h3
//
.text($item.find( 'h3:first' ).text())

// add the list item to the item navigation
.appendTo(myFeature.$item.nav)

// data()
.data( 'item' , $item)

// click
.click(myFeature.showContentItem);
});

* This source code was highlighted with Source Code Highlighter .

最後に、セクションとコンテンツ要素を表示するメソッドを作成します。
'showSection' : function () {
var $li = $( this );

//
myFeature.$item_nav.empty();
myFeature.$content.empty();

// jQuery
// data() buildSectionNav
var $section = $li.data( 'section' );

//
$li.addClass( 'current' )
.siblings().removeClass( 'current' );

//
var $items = $section.find( 'ul li' );

//
myFeature.buildItemNav($items);

// ""
myFeature.$item_nav.find( 'li:first' ).click();

},

'showContentItem' : function () {
var $li = $( this );

//
$li.addClass( 'current' )
.siblings().removeClass( 'current' );

// jQuery
// data() buildSectionNav
var $item = $li.data( 'item' );

//
myFeature.$content.html($item.html());
}


* This source code was highlighted with Source Code Highlighter .


myFeature.init()myFeature.init()呼び出すmyFeature.init()です:
$( document ).ready(myFeature.init);

* This source code was highlighted with Source Code Highlighter .

ここで全体像を見ることができます(ビュー用のいくつかのCSS)。

ステップ4:要件を変更する

直前に要件を変更しなければ、単一のプロジェクトでできることはありませんか? オブジェクトリテラルアプローチは、必要な変更を迅速かつ簡単に行うのに役立ちます。

HTMLからではなく、AJAXを使用して抜粋のコンテンツを取得する必要がある場合はどうなりますか? バックエンド設定を除外する:
var myFeature = {

'config' : {
'container' : $( '#myFeature' ),

//
// URL
'getItemURL' : function ($item) {
return $item.find( 'a:first' ).attr( 'href' );
}

},

'init' : function (config) {
//
},

'buildSectionNav' : function ($sections) {
//
},

'buildItemNav' : function ($items) {
//
},

'showSection' : function () {
//
},

'showContentItem' : function () {

var $li = $( this );

$li.addClass( 'current' ).
siblings().removeClass( 'current' );

var $item = $li.data( 'item' );
var url = myFeature.config.getItemURL($item);

// myFeature.$content.html($item.html());
myFeature.$content.load(url);

}

};


* This source code was highlighted with Source Code Highlighter .

さらに柔軟性が必要ですか? 構成(および再定義)できるものは多数あります。 たとえば、myFeature.configを使用して、各ナビゲーションアイテムのタイトルテキストを検索および処理する方法を指定できます。
var myFeature = {
'config' : {
'container' : $( '#myFeature' ),

'itemNavSelector' : 'h3' ,

'itemNavProcessor' : function ($selection) {
return 'Preview of ' +
$selection.eq(0).text();
}
},

'init' : function (config) {
//
},

'buildSectionNav' : function ($sections) {
//
},

'buildItemNav' : function ($items) {

$items.each( function () {
var $item = $( this );

var myText = myFeature.config.itemNavProcessor(
$item.find(myFeature.config.itemNavSelector)
);

$( '<li/>' )

.text(myText)
.appendTo(myFeature.$item_nav)
.data( 'item' , $item)
.click(myFeature.showContentItem);
});
},

'showSection' : function () {
//
},

'showContentItem' : function () {
//
}

};


* This source code was highlighted with Source Code Highlighter .

デフォルトの構成オブジェクトを追加した後、 myFeature.init ()呼び出してオーバーライドできます。
$( document ).ready( function () {
myFeature.init({ 'itemNavSelector' : 'h2' });
});


* This source code was highlighted with Source Code Highlighter .

おわりに


この記事のコード例を見ると、オブジェクトリテラルの基本的な理解と、このアプローチを使用してより複雑な対話を作成する方法を理解しているはずです。

ここから例を取り上げます

さらに読む

Source: https://habr.com/ru/post/J111290/


All Articles