質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

4652閲覧

jQueryでクラス名を定数にすべきか?見やすい管理は?

kumakuma112

総合スコア21

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

1グッド

1クリップ

投稿2018/05/17 12:56

編集2018/05/18 00:49

最近、変数名の命名規則を勉強しだして、セレクターやクラス名の管理方法に悩んでます。
Bootstrap4のソース真似てみたりいろいろ試してるのですが、何が一般的かイマイチピンときてないです。

メンテしやすい&見やすいコードにするためには?

プラグインではないのですが、クラス名を毎回書くのがなんかしっくり来てないです。
いざ、定数のように扱おうと思うと、

$(〜〜)とaddClassでドットありなしが混在するため、
うまくまとめられないくてどうしたものかと考えてました。
メンテしやすい&見やすいソースコードになるのか、わからないです。

Selectorに$("#slider").find(".slider_control")とかをまとめて書くのがスッキリするのですが、
ドットやコントロール系を自動生成にしたいため、最初に書くとfindで見つからなくて怒られます。

JS

1"use strict"; 2/* ======================================================== 3// NOTE スライダー04 4======================================================== */ 5$(function(){ 6 7 8 // NOTE セレクター 9 // jQueryオブジェクトをキャッシュ 10 var Selector = { 11 TARGET : $('#slider') 12 } 13 14 15 // NOTE クラス名 16 var ClassName = { 17 ACTIVE : 'is-active', 18 CONTAINER : 'slider', 19 VIEW : 'slider_view', 20 ITEM : 'slider_view_item', 21 NAV : 'slider_nav', 22 DOT : 'slider_nav_item', 23 CONTROL : 'slider_control', 24 BUTTON : 'slider_control_item', 25 PREV : 'slider_control_item-prev', 26 NEXT : 'slider_control_item-next' 27 } 28 29 30 // NOTE テンプレート 31 var Html = { 32 DOT : '<button class="' + ClassName.DOT + '" type="button" data-role="none" role="button"></button>', 33 PREV : '<button class="' + ClassName.BUTTON + ClassName.PREV + '" type="button" data-role="none" role="button"></button>', 34 NEXT : '<button class="' + ClassName.BUTTON + ClassName.NEXT + '" type="button" data-role="none" role="button"></button>' 35 } 36 37 38 // NOTE 現在地を確認する変数 39 var index = 1; 40 41 42 // NOTE スライダーの数 43 var count = $(ClassName.ITEM).length; 44 45 46 // NOTE 設定 47 function init(){ 48 49 // NOTE スライド要素にクラスを追加 50 Selector.TARGET.children().each(function(){ 51 $(this).addClass(ClassName.ITEM); 52 }); 53 54 // NOTE #sliderにクラスを追加と親タグを用意 55 Selector.TARGET 56 .addClass(ClassName.CONTAINER) 57 .wrapInner('<div class="' + ClassName.VIEW + '">') 58 .append('<div class="' + ClassName.NAV + '"/>') 59 .append('<div class="' + ClassName.CONTROL + '"/>'); 60 61 // NOTE ドットナビを生成 62 console.log(Selector.TARGET.find(ClassName.ITEM)); 63 Selector.TARGET.find(ClassName.ITEM).each(function(i){ 64 Selector.TARGET.find(ClassName.NAV).append(Html.DOT); 65 $(ClassName.DOT).on("click",function(){ 66 view(i + 1); 67 }); 68 }); 69 70 // NOTE 矢印コントローラーを生成 71 Selector.TARGET 72 .find(ClassName.CONTROL) 73 .append(Html.PREV) 74 .append(Html.NEXT); 75 76 $(ClassName.BUTTON).each(function(i){ 77 $(ClassName.PREV).on("click",function(){ 78 view(i - 1); 79 }); 80 $(ClassName.NEXT).on("click",function(){ 81 view(i + 1); 82 }); 83 84 }); 85 86 // NOTE 最初に1回だけ実行 87 view(index); 88 89 } 90 91 92 93 // NOTE 更新が必要なモジュールをアップデート 94 function view(val){ 95 96 index = val; 97 98 // スライド画像を更新 99 console.log($(ClassName.ITEM)); 100 $(ClassName.ITEM) 101 .hide() 102 .each(function(i){ 103 if(index == i + 1){ 104 $(this).show(); 105 return false; 106 } 107 }); 108 109 // ドットのナビを更新 110 $(ClassName.DOT) 111 .removeClass(ClassName.ACTIVE) 112 .each(function(i){ 113 if(index == i + 1){ 114 $(this).addClass(ClassName.ACTIVE); 115 return false; 116 } 117 }); 118 119 // 矢印ボタンを更新 120 if(index <= 1){ 121 $(ClassName.PREV).hide(); 122 } else { 123 $(ClassName.PREV).show(); 124 } 125 if(index >= count){ 126 $(ClassName.NEXT).hide(); 127 } else { 128 $(ClassName.NEXT).show(); 129 } 130 131 } 132 133 134 135 136 //NOTE 実行 137 init(); 138 139 140});

html

1 <div id="slider"> 2 <a href="#"><img src="img/thumb-01.jpg" alt=""></a> 3 <a href="#"><img src="img/thumb-02.jpg" alt=""></a> 4 <a href="#"><img src="img/thumb-03.jpg" alt=""></a> 5 <a href="#"><img src="img/thumb-04.jpg" alt=""></a> 6 <a href="#"><img src="img/thumb-05.jpg" alt=""></a> 7 </div>

最終的なhtmlのイメージ

<div id="slider" class="slider"> <div class="slider_view"> <a class="slider_view_item" href="#"><img src="img/thumb-01.jpg" alt=""></a> <a class="slider_view_item" href="#"><img src="img/thumb-02.jpg" alt=""></a> <a class="slider_view_item" href="#"><img src="img/thumb-03.jpg" alt=""></a> <a class="slider_view_item" href="#"><img src="img/thumb-04.jpg" alt=""></a> <a class="slider_view_item" href="#"><img src="img/thumb-05.jpg" alt=""></a> </div> <div class="slider_nav"> <button class="slider_nav_item dotButton" type="button" data-role="none" role="button"></button> <button class="slider_nav_item dotButton" type="button" data-role="none" role="button"></button> <button class="slider_nav_item dotButton" type="button" data-role="none" role="button"></button> <button class="slider_nav_item dotButton" type="button" data-role="none" role="button"></button> <button class="slider_nav_item dotButton" type="button" data-role="none" role="button"></button> </div> <div class="slider_control"> <button class="slider_control_item slider_control_item-prev" type="button" data-role="none" role="button">prev</button> <button class="slider_control_item slider_control_item-next" type="button" data-role="none" role="button">next</button> </div> </div>

参考にしたもの

Lhankor_Mhy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

注釈

質問内容が編集され当初の質問と前提が変わっているため、
以下、現在の質問内容に対する回答としては成立していません。

編集前の質問内容に対する回答

クラス名を毎回書くのがなんかしっくり来てないです。

いざ、定数のように扱おうと思うと、

「クラス名を毎回書くのがなんかしっくり来てないです」までは良いのですが、
その後の方向性が少しズレているように感じます。

var TARGET = '#slider'; $(TARGET).hide(); $(TARGET).text('hello'); $(TARGET).show();

例えば、質問文のコードを簡略した上記のようなコードがあるとします。

このコードがやっていることは、

  1. domツリーからIDがsliderの要素を見つけてjQueryオブジェクトにして非表示にする
  2. domツリーからIDがsliderの要素を見つけてjQueryオブジェクトにしてテキストを変更する
  3. domツリーからIDがsliderの要素を見つけてjQueryオブジェクトにして表示する

といったことをしています。

毎回、「domツリーからIDがsliderの要素を見つけてjQueryオブジェクトにして」が繰り返されている訳ですが、これって非効率ですよね?

var $slider = $('#slider'); $slider.hide(); $slider.text('hello'); $slider.show();

なので、一般的にはこのようにjqueryオブジェクトに変換された要素をキャッシュさせて、それを使いまわすということをします。

そうすると、

  1. domツリーからIDがsliderの要素を見つけてjQueryオブジェクトにして変数$sliderに入れておく
  2. それを使いまわして非表示にする
  3. それを使いまわしてテキストを変更する
  4. それを使いまわして表示する

というかたちになり、パフォーマンスの向上に繋がります。

ということでまとめると、クラス名を定数化するというよりは、jQueryのセレクターを変数に入れて使いまわすということになります。

その上で、例えば、少し古い本ですが「シングルページWebアプリケーション ―Node.js、MongoDBを活用したJavaScript SPA」のコードをみてみると、以下のようにjQueryセクレターを管理していますので参考にしてみるのも良いかもしれません。

jqueryMap = { $slider : $slider, $head : $slider.find( '.spa-chat-head' ), $toggle : $slider.find( '.spa-chat-head-toggle' ), $title : $slider.find( '.spa-chat-head-title' ), $sizer : $slider.find( '.spa-chat-sizer' ), $msgs : $slider.find( '.spa-chat-msgs' ), $box : $slider.find( '.spa-chat-box' ), $input : $slider.find( '.spa-chat-input input[type=text]') };

https://github.com/mmikowski/spa/blob/master/listings/ch05_06/5.2/js/spa.chat.js#L94

追記(変更された質問内容に合わせた回答)

コメント欄でLhankor_Mhyさんが書いておられたlazy gettersをベースに書いてみました。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/get#Smart_self-overwriting_lazy_getters

var obj = { get element() { console.log('1度だけ呼ばれる') delete this.element; return this.element = 'キャッシュ対象'; } } console.log(obj.element) // 初回アクセス console.log(obj.element) // 2回目以降はキャッシュが使われる

まずは、簡単なコードで動作確認。

var selectors = { $slider: $('#slider'), get $items() { delete this.$items; this.$items = this.$slider.find('.item'); return this.$items; } } selectors.$slider.children().each(function(){ $(this).addClass('item'); }); selectors.$items.first().text('hello')

後からクラス名が追加される場合でも大丈夫。

https://codepen.io/anon/pen/pVQOXd

追記2

var obj = { get element() { console.log('1度だけ呼ばれる') delete this.element; return this.element = 'キャッシュ対象'; } } console.log(obj.element) // 初回アクセス console.log(obj.element) // 2回目以降はキャッシュが使われる obj.element = 'hoge'; console.log(obj.element) // 書き換わってしまう

これだと上書き出来てしまうので、上書き出来ない版も追加。

var obj = { get element() { console.log('1度だけ呼ばれる') delete this.element; Object.defineProperty(this, "element", { value: 'キャッシュ対象', writable: false, configurable: true}) return this.element; } } console.log(obj.element) // 初回アクセス console.log(obj.element) // 2回目以降はキャッシュが使われる obj.element = 'hoge'; console.log(obj.element) // 書き換わらない

投稿2018/05/17 14:50

編集2018/05/18 11:10
HayatoKamono

総合スコア2415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kumakuma112

2018/05/17 23:39

勉強不足でした。確かにキャッシュしないと無駄な作業が増えますね。 ソースコードに入れてなかったのですが、 例えばスライダーでドットナビや矢印のコントローラーを動的に吐き出す場合に、 DOM操作があとになるため最初に変数で親からfindって入れられないと思って、 今回のような書き方しておりました。 ``` var ClassName = { VIEW_ITEM : 'slider_view_item' } //まだクラスが振られてないから見つからない var VIEW_ITEM = $("#slider").find(".slider_view_item"); function init(){ $("#slider").children().each(function(i){ $(this).addClass(className.VIEW_ITEM); }); } init(); ``` Bootstrap4ではセレクターとクラスをオブジェクト?で管理してるようです。 ``` $(Selector.FIXED_CONTENT).each((index, element) => { ``` https://github.com/twbs/bootstrap/blob/v4-dev/js/src/modal.js#L464 何がベストか混乱してます。 そもそも何でもかんでもクラス名を変数にするのってWEBアプリやサイトのJS実装では、余りやらないのでしょうか?
HayatoKamono

2018/05/18 01:46

複数回使うようなクラス名などの文字列を毎回手打ちしてるとタイプミスも起こりやすいですし、IDEの入力補完で楽も出来ないので、変数にいれて使い回すというのは良いことです。例えば、リンク先コードだと、$(this._element).hasClass(ClassName.FADE)のところなど。ただ、回答欄で書いた通り、同じセレクターに対するjqueryオブジェクトはキャッシュさせて使いまわした方が良いですね。
HayatoKamono

2018/05/18 04:37

変更された質問に合わせた回答も追記しました。Lhankor_Mhyさんがコメントされていたlazy getterを参考にさせて頂きました。情報ありがとうございます。
Lhankor_Mhy

2018/05/18 04:54

おお、こちらこそ取り上げていただきありがとうございます。 実際には、関数を返すラッパ関数なんかを使って書くんでしょうね。 デコレータが欲しくなりますね。
kumakuma112

2018/05/18 09:40

勉強になりました。ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問