転職

退職

先週、会社をやめたいと上司に伝えた。
何の前触れもなく相談したので驚いた様子だった。
申し訳ないなと思ったが、相談しても気持ちは変わらなかっただろうなとも思った。
昔から人に相談することが苦手だ。

今の会社に入って11ヶ月、とても良い仕事を経験させてもらったし成長もできたと思う。
会社も人も良くて大きな不満はなかった。
でも、すこし引っかかるものがあったというか違和感が拭えなかった。(社内の体制とか業務内容とか)
欲を言えばもっとJSを書きたかった。

そんなとき、一通のスカウトを受け取った。
よくあるスパムのようなメールとは違い、非常に丁寧で、僕個人に興味を持ってくれていることが伝わってくる文章だった。(僕のプロフィールだけでなく、会社のブログなども見てくれていて、さすがだなあと感心した。)
この会社の話なら聞きに行ってもいいかな、と思った。
それと同時に、オファーがきても選考には通らないだろう、という気持ちもあった。(募集要項からかなりスキルの高い人を求めていると感じたからだ)

しかしトントン拍子にことが進んでしまい、あっという間に内定をいただくに至ってしまった。
(エンジニア、デザイナーの人とは趣味が合いそうな感じはあった)
正直なんで僕にオファーを出してくれたのかよくわからない。

そこから数日、僕はとても悩んだ。とても悩んだ。
今の会社も人が足りているというわけではないし、入社してからの日も浅い。
この会社でできることはまだたくさんあるんじゃないか、とも思った。
たしかに、自社サービスの開発に携わってみたいという希望はあった。しかしそれは今なのか?このタイミングなのか?焦って正しい判断ができていないんじゃないか?
そう思ったりもした。

まあでもタイミングが合っていたかどうかなんて後になってみないとわからないし、自分がやりたいなと思っている仕事ができる環境に身を置きたいなと考え、転職をすることを決めた。(彼女にそそのかされた感もあったけど)

前職は1年、今回も1年、着実にジョブホッパーへの道を歩んでいるな。次は何年になるのだろうか。
(祖母は「30歳までなら職を転々としてもかまわない」と言っていたし、まだ良いかなと思っている)

体調

最近天気が悪く体調がすぐれない。
気圧や天気に体調が左右されるのは辛いけど最近は少しずつ慣れてきた。
何事もうまく付き合う方法はあるものだな、と思う。

明日は晴れるだろうか。

再開

1年近くこのブログ放置していたけど、またなんとなく再開します。 日記みたいなものは別のところに書いたりしていたけど、こっちに書くようにしたいなと。

今日は低気圧のせいなのか肩こりと頭痛がひどくて仕事どころじゃない… 早く晴れてほしいなあ。

レスポンシブコーディングでの縦横比問題の解決策

最近レスポンシブコーディングやスマホリキッドデザインなんかで縦横比を保ちたいってことが多い。
そこで縦横比保つ方法のメモ
デモは下にあります。

HTML

まずは普通にHTMLを書きます。
ポイントはinnerをboxで囲んでいるところ。
innerが赤い部分でboxはその親要素になっています。

<div id="sample-box">
<div class="sample-inner">
<p>4:3</p>
</div>
</div>

CSS

続いてCSSを書きます。

#sample-box{
    position: relative;
    width: 100%;
    height: 100%;
    padding: 75% 0 0;
}

padding: 75% 0 0; ここがポイントです。

padding-top(%) = 高さ / 横幅 * 100

この式で求めた数値をpadding-topに設定します。

あとはinnerに下記のようなCSSを設定すれば縦横比が4:3になってくれます。

#sample-box .sample-inner{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
background:  #b40d0d;
}

DEMO

4:3

Vue.jsハンズオン@DeNA

DeNAで開催されていたVue.jsのハンズオンに行ってきました。

eventdots.jp

Vue.jsの詳細はこちら。 今回は簡単なTODOアプリを作りました。

Vue.jsについて

MVVMとは?

MVVMとはモデル(M)とビュー(V)間のやり取りをビューモデル(VM)を介して行うアーキテクチャのこと。 Vue.jsではリアクティブデータバインディングというシステムを利用している。

Model

Modelとはdataオブジェクトとmethodsオブジェクトのこと。 dataオブジェクトの属性はv-textやv-modelといったディレクティブによってバインドされる。 ディレクティブとはDOMを操作するための特殊な属性で、v-から始まる。

View

Viewとはelで指定されたDOM要素のこと。 elでDOM要素を指定することで、ViewModelの適用範囲を指定できる。

TODOアプリ

Result

See the Pen TODO by Vue.js by takanorioki (@takanorioki4) on CodePen.

HTML

まずはHTMLを書きます。 テキストの展開は{{}}によって行います。

<div id="myApp">
  <p>
    Task:
    <input type="text" v-model="newTask" v-on:keyup.enter="addTask()">
    <button v-on:click="addTask()">ADD</button>
  </p>

  <ul>
    <li v-for="todo in todos">
      <input type="checkbox" v-model="todo.isCompleted">
      <span v-bind:class="{ 'complete': todo.isCompleted }">{{ todo.task }}</span>
      <button v-on:click="deleteTask(todo)">Delete</button>
    </li>
  </ul>
  <p>Remaining Tasks: {{ remains }}/{{ todos.length }}</p>
</div>

それぞれのディレクティブについて簡単に解説します。

v-for

配列をレンダリングするディレクティブ。
形式は{{ item in items }} (itemsは配列、itemは配列の要素)

v-model

form input要素で双方向データバインディングをするためのディレクティブ。 checkboxで使用するとboolean値がかえってくる

v-bind

HTMLの属性値(classなど)をバインドするためのディレクティブ。 省略することも可能。

v-on

DOMをListenするためのディレクティブ。 キー修飾子(kyeup.~~~)などの修飾子がある。

JS

つづいてVue.jsで処理を記述していきます。

new Vue ({
  el: '#myApp',
  data: {
    newTask: '',
    todos: [
      { task: 'buy a book', isCompleted: false },
      { task: 'buy a cake', isCompleted: false },
      { task: 'buy a sugar', isCompleted: true }
    ]
  },
  methods: {
    addTask: function(){
      if(this.newTask==''){
        return;
      } else {
      this.todos.push({
        task: this.newTask,
        isCompleted: false
      });
      this.newTask = '';
      }
    },
    deleteTask: function(todo){
      this.todos.$remove(todo);
    }
  },
  computed: {
    remains: function(){
      var counter = 0;
      for(var i=0; i<this.todos.length; i++){
        if(!this.todos[i].isCompleted){
          counter ++;
        }
      }
      return counter;
    }
  }
});

computedプロパティ

動的なプロパティを生成するメソッドを持つオブジェクトで、複雑な計算が必要な場合computed プロパティを使用する。(methodsとの違いはgetやsetの定義ができるとこ)

CSS

最後にCSSを書きます。

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

ul li{
  margin: 5px;
  text-indent: 0;
}

ul li .complete{
  text-decoration:line-through;
  color: #ddd;
}

完成!

これで完成です。いい感じに便利ですね。 他のアプリも作っていこう。

クロージャ

今回はJavaScriptの難関、クロージャについて書こうと思います。

わかったようでわかってない感じがするクロージャ
今回はとりあえずメモ。もっと深く理解したい。

まずはMDNからの引用。

クロージャは、独立した (自由な) 変数を参照する関数です。言い換えるとクロージャ内で定義された関数は、自身が作成された環境を '覚えています'。(MDN)

何言ってるかさっぱりですね。ナンノコッチャッて感じです。心折れそうです。
言葉だけだとわかりにくいので、実際のコードを見ていくことにします。

スコープ

クロージャを理解するのに必要なものとして、スコープが挙げられます。スコープとは簡単に言うと「変数を参照できる範囲」のことです。

スコープについては後日詳しく書くかも。

JavaScriptでは関数ごとにローカルスコープが作られます。
下記関数の変数 nameは関数 intro()の中でのみ参照することができます。関数 displayName() はintro()の内部にあるのでnameを参照することができます。

function intro() {
  var name = "Taro";

  function displayName() {
    console.log(name);
  }
  displayName();
}

クロージャ

クロージャの例としてよく見る感じの関数を書きます。

function intro() {
  var name = "Taro";

  function displayName() {
    console.log(name);
  }
  return displayName;
}

var introFunc = intro();

introFunc();

これでも前の関数と同じくTaroが表示されます。
これは関数 introが「関数を返す関数」になっていることを示しています。
ここでは以下の様な処理が行われているようです。

  1. intro()内で関数が生成される
  2. 変数displayNameにその値が代入される
  3. displayNameが戻り値として返される
  4. introFuncに代入される

関数なのか変数なのかはっきりしなくて気持ち悪いですが、JavaScriptではこのように変数のように扱えるみたいです。

クロージャの使いドコロ

クロージャの概念はなんとなく理解できましたが、では一体どんなときに使うのでしょう?
参考にさせていただいたMDNには下記のように書いてあります。

クロージャを使うと、データ (環境) をそれを操作する関数と結びつける事が出来ます。 ・・・中略 したがって、メソッドを 1 つだけ持つオブジェクトを使いたくなるような状況ならば、どんな時でもクロージャを使う事ができます。

ここでは2つのサンプルを見ていきたいと思います。

1. 自身が呼び出された回数をカウントする

function count(){
    var x = 1;

    return function (){
        console.log(x);
    x += 1;
    };

}

var f =  count(); 
f();  // 1
f();  // 2

2. モジュールパターン

モジュールパターンとはオブジェクトにパブリックなプロパティ、メソッドと、プライベートなプロパティ、メソッドを用意し、処理を切り分ける考え方です。これによりリファクタリングや機能の追加・削除が容易になります。
クロージャを利用することでプライベートなプロパティ、メソッドを作ることができます。

var counter = (function() {
  var privateCounter = 0;

  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    show: function() {
      console.log(privateCounter);
    }
  }; 
})();

counter.show(); // 0
counter.increment();
counter.increment();
counter.show(); // 2
counter.decrement();
counter.show(); // 1

変数 privateCounterと関数 changeByは両方ともプライベートな変数なので外側からアクセスすることはできません。
しかし、これを包んでいる無名関数から返されるパブリックメソッドを経由することでアクセスすることができます。

まとめ

クロージャの50%くらい理解できました。 あとは実践あるのみ?かな

Reactでいいねボタン

このページを写経してみました。
ちょっとわかった気がするReact

導入

$ npm init
//babel-coreがないとだめ
$ npm install --save-dev webpack babel-loader babel-core
$ touch webpack.config.js

webpack.config.js

module.exports = {
    entry: __dirname + "/src/main.js",
    output: {
        path: __dirname + "/dist",
        filename: "like-button.js"
    },
    module: {
        loaders: [{
            test: /\.js$/,
            loader: "babel",
            query: {
                presets: ["react", "es2015", "stage-0"] 
//react入れないとエラー出るよ&書き方がES2015だと違うよ
            }
        }]

    }
};
$ mkdir src dist
$ touch ./src/main.js
$ touch dist/index.html

package.jsonにwebpackのビルドタスクを定義。

{
...
  "scripts": {
    ...
    "build": "rm -rf dist/*.js && webpack",
    "watch": "rm -rf dist/*.js && webpack -w"
  },
...
}

Reactインストール

npm install --save react react-dom

main.js

import React from "react";
import ReactDom from "react-dom";

//コンポーネント定義

class LikeButton extends React.Component {
  constructor(props) {
    super(props);

//ホバーの状態、カウント数、Likeの有無をstateで定義

    this.state = {
      hovered: false,
      count: 999,
      liked: false
    }
  }
  styles() {
    return {
      container: {
        fontFamily: "helvetica, arial, 'hiragino kaku gothic pro', meiryo, 'ms pgothic', sans-serif",
        fontSize: 11
      },
      like: {
        display: "inline-block",
        background: "#3b5998",
        padding: "0px 5px",
        borderRadius: 2,
        color: "#ffffff",
        cursor: "pointer",
        float: "left",
        height: 20,
        lineHeight: "20px"
      },
      likeHover: {
        background: "#444"
      },
      counterBefore: {
        display: "block",
        float: "left",
        width: 6,
        height: 6,
        background: "#fafafa",
        marginLeft: "-12px",
        borderRight: 10,
        transform: "rotate(45deg)",
        WebkitTransform: "rotate(45deg)",
        marginTop: 6,
        borderLeft: "1px solid #aaa",
        borderBottom: "1px solid #aaa"
      },
      counter: {
        display: "block",
        background: "#fafafa",
        boxSizing: "border-box",
        border: "1px solid #aaa",
        float: "left",
        padding: "0px 8px",
        borderRadius: 2,
        marginLeft: 8,
        height: 20,
        lineHeight: "20px"
      }
    };
  }

//マウスホバーのイベントハンドラ

  onMouseEnter() {
    this.setState({hovered: true});
  }

  onMouseLeave() {
    this.setState({hovered: false});
  }

//クリックのイベントハンドラ

  onClick(){
    this.setState({
      count: this.state.count + (this.state.liked ? -1 : 1),
      liked: !this.state.liked
    });
  }

  render() {
    const styles = this.styles();
 //ホバーの判定からのスタイル変更
 //{...styles.like, ...styles.likeHover}はES7でふたつのオブジェクトをマージする構文
    const likeStyle = this.state.hovered ? {...styles.like, ...styles.likeHover} : styles.like;
    
    return (
      <span style={styles.container}>
        <span
          style={likeStyle}
          onMouseEnter={::this.onMouseEnter}
          onMouseLeave={::this.onMouseLeave}
          onClick={::this.onClick}>{this.state.liked ? "✔" : ""}いいね!</span>
        <span style={styles.counter}>
          <span style={styles.counterBefore}>{" "}</span>
          {this.state.count}
        </span>
      </span>
    );
  }
}

ReactDom.render(
  <LikeButton / >, document.getElementById("like-button"));

index.html

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Reactで作った「いいねボタン」のデモ (Flux不使用)</title>
</head>
<body>
  <h1>Reactで作った「いいねボタン」のデモ (Flux不使用)</h1>
  <div id="like-button"></div><!-- ここにコンポーネントをマウント -->
  <script src="like-button.js"></script>
</body>
</html>

ポップアップウインドウ

Result

See the Pen ezJdrw by takanorioki (@takanorioki4) on CodePen.

main.js

window.onload = function() {

var box = document.getElementById("box");
var btn = document.getElementById("btn");
var close = document.getElementById("close");
var boxstyle = box.style;

btn.onclick = function(){
  if( boxstyle.display === "block" ) {
    boxstyle.display = "none";
  } else {
    boxstyle.display = "block";
  }
};

close.onclick = function(){
  
boxstyle.display = "none";
};

}

index.html

<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>PopUp</title>
    <link rel="stylesheet" type="text/css" href="main.css">
    <script src="main.js"></script>
  </head>
  <body>
    <input type="button" id="btn" value="押す">
    <div id="box">
      <p id="close">×</p>
      <h2>Box</h2>
    </div>
  </body>
</html>

style.css

@charset "UTF-8";

#box {
  background: #FFF;
  border: 1px solid #333;
  box-shadow: 0 10px 10px #999;
  display: none;
  font-family: serif;
  padding: 10px;
  position: relative;
  text-align: center;
  width: 200px;
}

#box > #close {
  background-color: #EEE;
  color: #333;
  cursor: pointer;
  height: 30px;
  line-height: 30px;
  margin: 0;
  position: absolute;
  right: 1px;
  text-align: center;
  top: 1px;
  width: 30px;
}

#box > #close:hover {
  background-color: #F9F9F9;
  color: #999;
}

#btn {
  background-color: #6C6;
  border: 0;
  color: #FFF;
  cursor: pointer;
  padding: 5px 20px;
}

#btn:hover {
  background-color: #9D9;
}

#btn:active {
  background-color: #4A4;
}