Labs

<< 最初 < 前ページ 次ページ > 最後 >>
icon [脱jQuery]始める前に (2019/03/15)

「脱jQuery」を始める前に


近年「脱jQuery」のワードが出ているが、手法を間違えると「jQuery」で良かったということにも・・・
「jQueryのここが便利だったのか」と痛感することも結構あります。

何のために「脱jQuery」をするのか?目的が明確である


周りが発言しているからという曖昧な理由でなく、「脱jQuery」した未来予想図を作っておきます。
(JavaScript、フレームワーク知識向上、半自動化などの開発効率化の目処など)
特にJSフレームワークを利用しない場合、jQueryの部分を全て自分で書き直す覚悟が必要でしょう。

代用するJSフレームワークで開発・設計が確立している


「Vue.js」「AngularJS」「React」の選択肢が決まっていて、バックエンドやテンプレート管理の設計ができている。
恐らく、これが今一番主流でしょう。
ただしフレームワークや設計方法の理解度が低いと、プロジェクトが破綻する可能性がある。

自分でライブラリ・フレームワーク・設計が確立できる


「脱jQuery」をしたことで、ソース管理が余計に複雑になってしまう事が多々ある。
特にjQuryライブラリに依存したプロジェクトを書き換えると相当な労力を要するので覚悟が必要である。

など、案件によってよく吟味して作業した方が良い。

「既存JSフレームワーク」を始める前に


現在は「Vue.js」「AngularJS」「React」が主流
「YUI」「Backbone.js」などフェイドアウトしていくフレームワークも多々あるので、選択を間違え内容にネイティブの知識の保険をかける必要がある。

個人的なロードマップとして、既存JSフレームワーク利用の前に、自作フレームワークを作成してある程度経験を積み、同時に「Vue.js(個人的にイチオシ)」「AngularJS」の情報も蓄積しつつ、効率的・自動化を踏まえて移行するつもりだ。

過去の経験から既存JSフレームワークを安易に利用すると、

・知識が浅いと構造がグチャグチャになる
・効率化するにはJSフレームワーク以外の設計知識も必要
・進化が早いので、圧倒的な仕様変更に対応できない

になるためだ。

現在(2019/03時点)は「ECMAscript 6」が主流であるので、「ECMAscript 7」は必要な時に利用していく。
更に「TypeScript」を併用するのが理想かもしれないが、まずはネイティブの知識を復習・蓄積していく。

個人的な目標


・JavaScriptネイティブ追求
・Dom操作追求
・MVC設計において他のフレームワークとの一般共通化
・View(テンプレートエンジン)の手法・管理
・バックエンドの親和性
・開発半自動化

などを目標とします。
icon Ajax非同期処理を実装 (2017/05/11)
JavaScriptでAPIからデータ取得・処理する際、ネスト地獄で複雑なコードになりがち。
かと言って、AngularやReactなどのフレームワークを使うと勉強コスト、スパゲティー設計など本末転倒な結果になりやすい。

フレームワークの最大のデメリットは、

中で何が行われているか?ソースを解読しないとわからない


と言うことで、こみいった実装をせずシンプルに実装してみる。

(1) APIリクエストの配列設定
(2) Ajax処理の抽象化
(3) 並列処理の抽象化
(4) コールバック処理の考慮
    $(document).on('click', '.action-api', function() {
        //API設定(抽象化する必要あり)
        var requests = [
            {
                url: 'https://xxxx/api/user',
                params: {'user_id': 394},
                callback: callbackUser
            },
            {
                url: 'https://xxxx/api/order',
                params: {'user_id': 394, 'item_id': 31},
                callback: callbackApplication
            },
        ];

        //並列処理実行
        parallelAjax(requests, doneCallback);

        //各APIリクエストのコールバック
        function callbackUser(results) {
            console.log(results);
        }
        function callbackApplication(results) {
            console.log(results);
        }
        //並列処理完了後のコールバック
        function doneCallback(results) {
            console.log(results);
        }
    });

var requestAjax = function(values){
    var $ajax = $.ajax(values);
    var defer = new $.Deferred();
    $ajax.done(function(data, status, $ajax){
        defer.resolveWith(this, arguments);
    });
    $ajax.fail(function(data, status, $ajax){
        defer.resolveWith(this, arguments);
    });
    return $.extend({}, $ajax, defer.promise());
};

function parallelAjax(requests, callback) {
    var results = [];
    $.each (requests, function(index, value) {
        var $ajax = requestAjax({url: value.url, data: value.params}).done(function(res, status) {
            if (value.callback) {
                value.callback(res);
            }
        });
        results.push($ajax);
    });
    $.when.apply(null, results).done(function(){
        if (callback) callback(results);
    });
    $.when.apply(null, results).fail(function(){
    });
}

APIリクエストの配列設定


並列処理は後々ループで実行ため、オブジェクト配列で設定しておく。
差し当たり以下の項目で設定
・URL
・URLパラメータ
・API処理後のコールバック
(その他、POST/GETやデータ型なども設定できると良い?)
        var requests = [
            {
                url: 'https://xxxx/api/user',
                params: {'user_id': 394},
                callback: callbackUser
            },
            {
                url: 'https://xxxx/api/application',
                params: {'user_id': 394},
                callback: callbackApplication
            },
        ];
こうすることで、callbackを別モデル、ファイルなどに分離して記述できるかと。
実用レベルだと、APIリクエスト設定も動的に抽象化が必要ですが。。。

Ajax処理の一般化


並列処理をする際「jQuery.Deferred」を利用
ざっとした流れは、
(1) Deferredオブジェクトを作成
(2) Ajaxリクエスト
(3) Ajax処理後返り値を Deferred.resolveWith() でコールバック

詳しくは、
「爆速でわかるjQuery.Deferred超入門」
「結局jQuery.Deferredの何が嬉しいのか分からない、という人向けの小話」を参照
var requestAjax = function(values) {
    var $ajax = $.ajax(values);
    var defer = new $.Deferred();
    $ajax.done(function(data, status, $ajax) {
        defer.resolveWith(this, arguments);
    });
    $ajax.fail(function(data, status, $ajax) {
        defer.resolveWith(this, arguments);
    });
    return $.extend({}, $ajax, defer.promise());
};

並列処理の一般化


(1) 配列化したリクエストをループで処理
(2) Ajax実行
(3) APIリクエストで設定したコールバックを実行
(3) $.whenで並列処理完了後の処理
function parallelAjax(requests, callback) {
    var results = [];
    $.each (requests, function(index, value) {
        var $ajax = requestAjax({url: value.url, data: value.params}).done(function(res, status) {
            if (value.callback) {
                value.callback(res);
            }
        });
        results.push($ajax);
    });
    $.when.apply(null, results).done(function(){
        if (callback) callback(results);
    });
    $.when.apply(null, results).fail(function(){
    });
}
icon form内データ取得 (2016/03/31)
form.submit()でなく、AjaxなどでPOSTするにはform内データを取得する必要があるが、
タグ毎に処理が異なる。
(もっと合理的な書き方はあるかと思うが・・・)

サンプル


サンプル


  <form id="form">
    <h1>result(JSON)</h1>
    <div id="result"></div>

    <h1>form</h1>
    <h2>title</h2>
    <input type="text" name="title" value="">

    <h2>select</h2>
    <select name="status">
      <option value="1">select1</option>
      <option value="2">select2</option>
      <option value="3">select3</option>
      <option value="4">select4</option>
    </select>

    <h2>radio</h2>
    <input type="radio" name="active" value="true">radio1
    <input type="radio" name="active" value="false">radio2

    <h2>checkbox</h2>
    <label for="reason_1"><input id="reason_1" type="checkbox" value="1" name="reason">check1</label>
    <label for="reason_2"><input id="reason_2" type="checkbox" value="2" name="reason">check2</label>
    <label for="reason_3"><input id="reason_3" type="checkbox" value="3" name="reason">check3</label>

    <h2>textarea</h2>
    <textarea id="note" name="note" rows="10" cols="50"></textarea>

    <div>
      <a class="action-update" href="#">UPDATE</a>
    </div>
  </form>

</select>

<input type="radio" name="active" value="true">
<input type="radio" name="active" value="false">

<label for="reason_1"><input id="reason_1" type="checkbox" value="1" name="reason">選択1</label>
<label for="reason_2"><input id="reason_1" type="checkbox" value="2" name="reason">選択2</label>
<label for="reason_3"><input id="reason_1" type="checkbox" value="3" name="reason">選択3</label>

<textarea id="note" name="waste[note]" rows="10" cols=""></textarea>
</form>

input


var posts = {};
$('#form input').each(function() {
    var type = $(this).attr('type');
    var name = $(this).attr('name');
    if (name) {
        if (type == 'checkbox') {
            //TODO 重複
            posts[name] = checkValues(name);
        } else if (type == 'radio') {
            var checked = $(this).prop('checked');
            if (checked)  {
                posts[name] = $(this).val();
            }
        } else {
            posts[name] = $(this).val();
        }
    }
});

function checkValues(name) {
    var column = '[name="' + name + '"]:checked';
    var checks = [];
    $(column).each(function() {
        var checked = $(this).prop('checked');
        if (checked) {
            checks.push($(this).val());
        }
    });
    return checks;
}
厄介なのが「checkbox」でチェックボックスの状態をスキャンしないといけない。
上記サンプルは、checkboxの数だけ無駄に処理してしまっている。

inputタグ毎に明示的にid指定すれば対応は簡単だが、コーディングが冗長的
(場合によってはその方が良い?)
改善策としては、ビジネスロジックやルールをjavascript側で作るのが良さそう。

select


var posts = {};
$('#form select option:selected').each(function() {
    var name = $(this).parent().attr('name');
    if (name) posts[name] = $(this).val();
});

textarea


var posts = {};
$('#form textarea').each(function() {
    var name = $(this).attr('name');
    if (name) {
       posts[name] = $(this).val();
    }
});
<< 最初 < 前ページ 次ページ > 最後 >>

このサイトについて

HTML5 & CSS3化しつつあるので、現在IEには対応してません。
できれば、Google Chromeやら Apple SafariのWebKit系をお勧めします。

DBからプログラムまで一応全て自作なので、バグってたらすいません。
実験でFlash版(Flex版)を先に作りましたが、ちょっと停止してます。

プロフィール

新宿近辺でSE & プログラマーしてます。
Webアプリの開発・設計とか、最近はiPhoneとか奮闘してます。
デザインはさっぱりです。

音楽は、昔からCubase打ち込み人間で、そっちの方が経歴は長いですが、最近はやる暇がないです。。。

今は、Gon's Privates ってバンドのキーボードやってます。
単発的に、なんちゃってジャズ系のライブもやってます。

名古屋生まれなのでドラゴンズ好きです。

Info && SNS

Gmail

 yohei.yoshikawa@gmail.com

Twitter

 http://twitter.com/yoo_yoo_yoo

あんまつぶやきませんが、一応技術系メインで使ってます。情報交換はこちらへ

FaceBook

 http://www.facebook.com/#!/profile.php?id=1439130626

海外の知り合いがいないので閑散としてます。

mixi

 http://mixi.jp/show_profile.pl?id=230072

音楽仲間とかはこっちメインでやってます。興味があればこちらへ