Skip to content

Instantly share code, notes, and snippets.

@k-hoshina
Created December 27, 2018 02:40
Show Gist options
  • Save k-hoshina/b07d5b197c398056168c9509ee676d33 to your computer and use it in GitHub Desktop.
Save k-hoshina/b07d5b197c398056168c9509ee676d33 to your computer and use it in GitHub Desktop.
JS今昔物語

フロントエンドへの要求

  • フロントのリッチ化
    • 高速なUI
    • アニメーション
    • 複雑な構造
  • ネイティブアプリの存在
    • 同様の体験

高速な変化

  • ブラウザの進歩が速い
    • 古いブラウザを捨てきれない
  • トランスパイル・ポリフィルで互換を保ちながら高度な機能を追加できるように
    • altJSの急速な拡大
      • babel
      • typescript
  • facebook/googleのUI開発手法が野に下る
    • UI構築の複雑化・規格化
      • react
      • angular
  • nodeの開発が爆速化
    • ツールチェインの発達
      • webpack
      • yarn
  • 理由はいろいろあるけどみんな必要にかられてそうなってる

歴史

太古

  • NetScapeにLiveScript誕生
  • JavaScriptに改名
  • IEにJScript, FlashにActionScript
  • ECMA標準化、そして失敗
  • DHTML

2005

  • ajax
  • prototype

2006

  • jQuery

2007

2008

  • chrome/V8

2009

  • ECMAScript5
  • node.js
  • AngularJS
  • coffee script

2010

  • Knockout.js

2011

  • CSS3
  • Ember.js
  • browserify

2012

  • grunt
  • webpack
  • typescript

2013

  • react
  • glup
  • Electron

2014

  • HTML5
  • io.js
  • vue

2015

  • ECMAScript2015
  • babel
  • react native
  • flow
  • nodejs2(io.js統合)

2016

  • ECMAScript2016
  • Angular
  • vue2
  • next.js
  • nuxt.js

2017

  • webworker
  • ECMAScript2017
  • Parcel

2018

  • ECMAScript2018
  • WebAssembly

フレームワーク史

  • ajax
    • ブラウザでステートフルなUIの実現
  • Prototype
    • オブジェクト指向の整理
  • jQuery
    • DOM操作
    • 簡単なイベントハンドリング
    • マルチブラウザ対応
  • backbone
    • MVCでの構造化
  • knockout/Angular1
    • MVVMでの構造化
    • 双方向データバインディング
  • react/vue2/Angular
    • 仮想DOM

ajax

httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
    if (httpRequest.readyState === XMLHttpRequest.DONE) {
      if (httpRequest.status === 200) {
        alert(httpRequest.responseText);
      } else {
        alert("リクエストに問題が発生しました");
      }
    }
  };
httpRequest.open("GET", "http://www.example.org/some.file", true);
httpRequest.send();
  • XMLHttpRequestによる画面遷移を伴わない非同期通信の実現

Prototype

var Person = Class.create();
Person.prototype = {
  initialize: function(name) {
    this.name = name;
  },
  say: function(message) {
    return this.name + ': ' + message;
  }
};

var Pirate = Class.create();
// Personから継承
Pirate.prototype = Object.extend(new Person(), {
  // メソッドオーバーライド
  say: function(message) {
    return this.name + ": " + message + ", yarr!";
  }
});
    
var john = new Pirate("Long John");
john.say("ahoy matey");
  • クラスベースの継承をシミュレート
  • セレクタやajaxのラッパーなども含まれていた

jQuery

var hiddenBox = $( "#banner-message" );
$( "#button-container>button" ).on( "click", function( event ) {
  $.ajax({
    url: "/api/getWeather",
    data: {
      zipcode: 97201
    },
    success: function( result ) {
      $( "#weather-temp" ).html( "<strong>" + result + "</strong> degrees" );
    }
  });
});
  • 高度なセレクタ・DOM操作
  • 簡易なインターフェース
  • プラグインによる拡張

backbone

var Todo = Backbone.Model.extend({
    defaults: function() {
      return {
        done: false
      };
    },
    toggle: function() {this.save({done: !this.get("done")});}
  });

  var TodoView = Backbone.View.extend({
    tagName:  "li",
    template: _.template($("#item-template").html()),
    events: {"click .toggle"   : "toggleDone"},
    render: function() {
      this.$el.html(this.template(this.model.toJSON()));
      this.$el.toggleClass("done", this.model.get("done"));
      this.input = this.$(".edit");
      return this;
    },
    toggleDone: function() {this.model.toggle();}
  });
  • フロントエンドでMVC(MVP)による構造化

knockout

<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
function ViewModel() {
    this.firstName = ko.observable("Planet");
    this.lastName = ko.observable("Earth");
    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);
}

ko.applyBindings(new ViewModel());
  • 双方向データバインディング
  • data-bindプロパティによる宣言型バインディング
  • MVVMのはしり

react

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      total: null,
      next: null,
      operation: null,
    };
  }

  handleClick = buttonName => {
    this.setState(calculate(this.state, buttonName));
  };

  render() {
    return (
      <div className="component-app">
        <Display value={this.state.next || this.state.total || "0"} />
        <ButtonPanel clickHandler={this.handleClick} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
  • コンポーネント志向なViewのみを提供
  • JSXによる記述
  • 単方向データバインディング

vue

<div id="editor">
  <textarea :value="input" @input="update"></textarea>
  <div v-html="compiledMarkdown"></div>
</div>
new Vue({
  el: "#editor",
  data: {
    input: "# hello"
  },
  computed: {
    compiledMarkdown: function () {
      return marked(this.input, { sanitize: true })
    }
  },
  methods: {
    update: _.debounce(function (e) {
      this.input = e.target.value
    }, 300)
  }
})
  • 双方向データバインディング
  • コンポーネント志向な単方向データバインディングなパラダイムにも対応
  • ルーターとかCSS操作とか割と自前(or公式ライブラリ)で揃ってる

reactとvueとangular

  • 2017年くらいから3大jsフレームワーク
  • 人気はvue>react>>>>angular
  • エコシステムはreact>>vue>>angular
  • 機能はangular>vue>react

共通する概念

  • 仮想DOM
  • コンポーネント志向

仮想DOMとは

  • JSのオブジェクトとしてDOMをシミュレート
  • 差分を検出して描画

コンポーネント志向

  • 構造・見た目・振る舞いをセット
  • 従来はHTML・CSS・JSで分離していたが現実問題としていろいろしんどい
  • WebComponentsが標準化されようとしてる(されるとは言ってない)

どれを選べばいいの?

  • 好み
  • vueが簡単
    • 書き方のパターンがあるので荒れやすい面もある
  • reactはシンプル
    • 思想に厳格過ぎて面倒な点もある
    • 関連ライブラリも選定する必要がある
  • angularはフルスタック
    • typescriptフレンドリー
    • ツールセットもオールインワン
  • vanillaJSはさすがに…

未来を見据える

  • ブラウザの発達で陳腐化する物はある
    • ES module/Web componentの本格化でわりと大きく変わりそう
  • まだしばらくはwebpack依存せざるを得ない
  • typescriptが勢力を増している
    • reactはtypescriptで書かれるケースが増えてる
    • vue3はtypescript
  • コンポーネントでの設計技法は腐りにくい

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment