読者です 読者をやめる 読者になる 読者になる

もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

「脱 jQueryプラグイン ~プロのJavaScriptコードを書くために~」感想

jQuery JavaScript セミナー

jQueryプラグイン ~プロのJavaScriptコードを書くために~
http://www.zusaar.com/event/3547008

■内容
本セミナーでは一般的に使われるユーザーインターフェースjQueryプラグインを使わずに実装する過程をご紹介し、Web制作の現場で制作者に求められるJavaScript実装の技術をお伝えします。

■講師
田中 邦典さん (株式会社LeiHau'oli)
小枝 優駿さん (株式会社LeiHau'oli)

という勉強会に行ってきました(なお遅刻で参加。。。)。内容からてっきり脱jQueryかと思ったら脱jQueryプラグインだったのでちょっと拍子抜け・・・ですが、話されていた内容はためになるので、自戒の意味もこめておさらい。

スタイルの変更について

jQueryでスタイルを変更する際はcssメソッドを使うのではなく、addClass、removeClassメソッドを使用してスタイルを変えるべし。これは普段からやらないですけど、cssメソッドを使うと可読性が下がるしスタイルをいじる時にJSをいじらにゃならんので避けた方が無難ですね。スライドショーとかを自前で作ったりするときはエレメントの位置を動的にいじったりするので、そのような場合のみポイントでcssメソッドを使います。

オブジェクトのキャッシュについて

複数回使うオブジェクトは変数に突っ込んでから使う事。イベントハンドラ内でjQueryオブジェクトを使用しない事。これはjQueryオブジェクトは生成の都度、セレクタによってDom操作が行われているので、同じエレメントを操作する場合は、一旦、作成したjQueryオブジェクト=エレメントの参照をキャッシュしておいて使い回すのがベストという話です。この辺はパフォーマンスについて突っ込むとIDセレクタは早いとかclassセレクタは遅いとか独自セレクタは超遅いとかいろいろあるのですが、いずれにせよ複数回使うものはキャッシュした方がよいです。

課題

課題が何個か出たので最後にやった奴だけ紹介。5分くらいしか解く時間なかったけど。。。タイポに気づかずタイムオーバーでしたw

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <style type="text/css">
        body{
            margin: 0;
        }
        .content{
            position: relative;
            height: 1000px;
        }
        .content a{
            display: inline-block;
            font-size: 30px;
            font-weight: bold;
            color: #FFFFFF;
            padding: 30px;
        }
        .background1{
            background-color: #2ECC71;
        }
        .background2{
            background-color: #3498DB;
        }
        .background3{
            background-color: #F39C12;
        }
        .navigator{
            position: fixed;
            top: 0px;
            right: 0px;
            margin: 0px;
            padding: 0px;
            list-style: none;
            z-index: 100;
        }
        .navigator:after{
            content: ".";
            display: block;
            height: 0;
            font-size:0;
            clear: both;
            visibility:hidden;
        }
        .navigator li{
            float: left;
            text-align:center;
            border: solid 1px #808080;
            width: 100px;
            margin: 10px;
            font-size: 13px;
            line-height: 20px;
            background-color: #FFFFFF;
        }
        .navigator li a{
            -moz-box-sizing: border-box;
            -webkit-box-sizing: border-box;
            display: inline-block;
            padding: 10px;
            width: 100%;
            height: 100%;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <ul class="navigator">
        <li><a href="#content1">要素1へ</a></li>
        <li><a href="#content2">要素2へ</a></li>
        <li><a href="#content3">要素3へ</a></li>
    </ul>
    <div class="content background1">
        <span><a name="content1">要素1</a></span>
    </div>
    <div class="content background2">
        <span><a name="content2">要素2</a></span>
    </div>
    <div class="content background3">
        <span><a name="content3">要素3</a></span>
    </div>
</body>
<script type="text/javascript">

  // ここを実装

</script>
</html>

タグだとちと分かりづらいですが、要素nへを押すとそれに対応したエレメントの位置までスクロールして移動するというコードを実装します。

で、勉強会の内容を踏まえた感じでこんな解答

  var _$cons = $('.content'),
       _$body = $('html,body');
  $('.navigator').find('li').each(function(_idx){
    var _top = _$cons.eq(_idx).offset().top;
    $(this).on('click', function(e){
      e.preventDefault();
      e.stopPropagation();
      _$body.animate({ scrollTop: _top}, 500);
    });
  });

別解。

  var _$nav = $('.navigator'),
    _$navs = _$nav.find('li');
    _$cons = $('.content'),
    _$body = $('html,body');
  _$nav.on('click', 'li', function(e){
    e.preventDefault();
    e.stopPropagation();
    var _idx = _$navs.index($(this)),
      _top = _$cons.eq(_idx).offset().top;
    _$body.animate({ scrollTop: _top}, 500);
  });

※前者の実物

前者はnavigator配下のli一個ずつに対してイベントをbindしています。後者はnavigatorに対してdelegateを設定しています。
後者はハンドラが設定されたliをnavigator内のエレメントがクリックされた際に毎回、セレクタがかかる+topの値をハンドラ内で取得している分、前者より遅いです。対して前者はエレメントの数が増えた場合にパフォーマンスが落ちるのでその場合は後者のdelegateの方がよいです。まあ場合に応じて使い分けないとですね。色々な書き方を覚えておいて損は無いと思います。