20210315のJavaScriptに関する記事は22件です。

【初心者でもわかる】RSSの配信方法と・jQueryでのRSS取得方法のいろは

どうも7noteです。jQueryを使ったRSS配信と取得方法を解説

「そもそもRSS配信とは?」

RSSとは「Webサイトの新着情報を配信するフォーマット」

RSSとは「Really Simple Syndication」、または「Rich Site Summary」の略語※で、Webサイトのニュースやブログなどの、更新情報の日付やタイトル、その内容の要約などを配信するため技術のことです。RSSは、XML形式で記述されており、RSSリーダーと呼ばれるツールを使用することで、様々なサイトの更新情報や新着情報を自動的に取得することができます。
引用元:https://www.asobou.co.jp/blog/life/rss-2

RSSでできることは配信と取得の2つ。

こんな風につかえます。↓↓↓

  • 自分のサイトからRSSを配信して、誰でも自分のブログの最新情報を取得して使えるようにする
  • 他のサイトの最新情報を取得して、自分のサイトに情報を掲載する。

自分一人で「配信」も「取得」もすれば、「サイトAの最新情報をサイトBにも掲載する。」なんてことができます。

jQueryを使ったRSSの設定方法

■ RSSを「配信」するための設定

今回はRSSの配信元にWordpressが入っている場合で解説します。
Wordpressは標準でRSSの配信設定がされているので、URLに/feed/を追加するだけで簡単に配信している内容が確認できる。

ちなみに天下のwordpress様の日本語版の内容はこんなかんじ。

image.png
https://wordpress.com/ja/blog/feed/

(これがXHTMLの書き方です。)

URLの末尾に/feed/を付けて上記の画面を確認できればこれで基本的な準備OKです。
Wordpressさえ入れていればRSSの配信は自動でされます!

~カスタマイズしたい人は以下を設定~

▼ RSS配信する件数を制御したい

①wordpressの管理画面にログイン
②メニューの「設定」→「表示設定」から「RSS/Atom フィードで表示する最新の投稿数」を好きな数字に変更する。

image.png

▼ サムネイル画像も配信したい

FTPソフトを立ち上げて/wp-includes/feed-rss.phpのファイルを編集します。
以下のように<item></item>の好きな場所にソースを追加します。

feed-rss.php
<item>

~~~~(他のソース)~~~~~~

<?php /* ここから追加 */
  if ( has_post_thumbnail() ) :
    $image_url = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'large');
    $thumb_url = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'thumbnail');
?>
    <image><url><?php echo $image_url[0] ; ?></url></image>
    <thumb><url><?php echo $thumb_url[0] ; ?></url></thumb>
<?php endif;
/* ここまで追加 */ ?>

~~~~(他のソース)~~~~~~

</item>

以上で準備完了です。続きは配信方法へ。

※feed-rss.phpはwordpresのアップデートなどで上書きされてしまう可能性があるようなので、feed-rss2.php等を作って読み込む方が安全らしい。その場合は以下の設定も。

/wp-includes/にfeed-rss.phpをコピーしてfeed-rss2.phpを作成。
②テーマファイルのfunction.phpに以下のソースを追記。

function.php
remove_filter('do_feed_rss2', 'do_feed_rss2', 10);
function custom_feed_rss2(){
  $template_file = '/feed-rss2.php';
  load_template(get_template_directory() . $template_file);
}
add_action('do_feed_rss2', 'custom_feed_rss2', 10);

▼ カスタム投稿タイプも配信したい

RSSは標準のままだとデフォルトの投稿タイプのみの配信になるので、カスタム投稿タイプの内容を配信するには以下の設定が必要です。
テンプレートファイルのfunction.phpに以下のソースを追加します。

function.php
<?php
function mysite_feed_request($vars) {
    if ( isset( $vars['feed'] ) && !isset( $vars['post_type'] ) ) {
        $vars['post_type'] = array(
 'post',
 '投稿タイプ名1',
 '投稿タイプ名2',
 '投稿タイプ名3'
 );
    }
    return $vars;
}
add_filter( 'request', 'mysite_feed_request' );
?>

これで準備完了です。

ちなみに/feed/に引数を付けることで、特定の投稿タイプのみのRSS配信を見ることができます。

http://ドメイン/feed/?post_type=投稿タイプ名
http://ドメイン/?feed=rss2&post_type=投稿タイプ名

■ RSSを「取得」するための設定

RSSを取得して表示したいページに以下のソースを記述します。

sample.html
<article class="new">
  <div class="XMLRequest">
    <!-- ここに書き出される -->
  </div>
</article>

<script>
$(document).ready(function () {
  $.ajax({
  type: "get",
  url: "http://hogehoge.com/feed/" //(ここにxmlがあるhogehoge.com/feed/を記述)
  }).done(function(result) {
  $(result).find("item").each(function() {
  $(".XMLRequest").append('<h3>' + $(this).find('title').text() + '</h3>' + '<p>' + $(this).find('link').text() + '</p>');
  });
  console.log(result);
  });
});
</script>

すると以下のような形でタグが吐き出されるはずです。

sample.html
<article class="new">
  <div class="XMLRequest">
    <h3>(記事1のタイトル)</h3>
    <p>(記事1のリンクURL)</p>
    <h3>(記事2のタイトル)</h3>
    <p>(記事2のリンクURL)</p>
    <h3>(記事3のタイトル)</h3>
    <p>(記事3のリンクURL)</p>
    ・
    ・
    ・
  </div>
</article>

うまく表示されていれば成功です!
もしうまくいかなければ以下の点を確認してみてください。

【うまくいかない時のチェックポイント】

・「http://xxxx.com/feed/にアクセスして、XMLファイルが見れるか。」
・「スペルミスはないか。」
・「検証ツールのコンソールには記事情報が読みこめているか。」
・「検証ツールで何かrssに関するっぽいエラーが出ていないか。」

~カスタマイズした人は以下を設定~

▼サムネイル画像を表示する

$(this).find('image url').text()で通常サイズの画像を取得
$(this).find('thumb url').text()でサムネイル画像を取得

sample.html
<script>
// 通常サイズの画像の場合

$(document).ready(function () {
  $.ajax({
  type: "get",
  url: "http://hogehoge.com/feed/"
  }).done(function(result) {
  $(result).find("item").each(function() {
  $(".XMLRequest").append('<img src="' + $(this).find('image url').text() + '" alt="' + $(this).find('title').text() + '">'); //← ここの内容を変更してます
  });
  console.log(result);
  });
});
</script>

結果

sample.html
<article class="new">
  <div class="XMLRequest">
    <img src="(記事1の画像URL)" alt="(記事1のタイトル)">
    <img src="(記事2の画像URL)" alt="(記事2のタイトル)">
    <img src="(記事3の画像URL)" alt="(記事3のタイトル)">
    ・
    ・
    ・
  </div>
</article>

▼特定の投稿タイプのみ取得する場合

scriptのurlの部分を以下のように変更してください。

  url: "http://hogehoge.com/feed/"

  ↓↓↓

  url: "http://hogehoge.com/feed/?post_type=投稿タイプ名"

まとめ

一回目、はじめてRSSを読み込んで表示させるまでは、結構いろいろなファイルを触らないといけないので理解するまでに時間がかかるかもしれません。
しかし仕組み自体はシンプルなので、必要なカスタマイズ方法と一緒に理解していればそこまで難しいものではないです。

ほかのカスタマイズ方法についても必要に応じてまた追記していきたいと思います。

参考:
https://www.will3in.co.jp/frontend-blog/article/eyecatch-in-rss-and-view-another-site/
https://www.webantena.net/wordpress/functions-php-mysite-feed-request/

おそまつ!

~ Qiitaで毎日投稿中!! ~
【初心者向け】WEB制作のちょいテク詰め合わせ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript var let constの違い

JavaScriptでは変数を定義する際利用できるキーワードは三つあります。

  • var:全バージョン利用可能
  • const:ECMAScript 6以降から利用可能
  • let:ECMAScript 6以降から利用可能

※ECMAScript 6は2015年6月に公開 各バージョンの公開日はここから参照

var

var 文は関数スコープまたはグローバルスコープの変数を宣言し、任意でそれをある値に初期化します。

var message;    //初期化していないため [undefined]という特殊な値が設定される
var message2 = "Hello World!";

function showMessage(){
   console.info(message3);
   var message3 = "ShowMessage";
}

function showMessage2(){
   var message4;
   console.info(message4);
   message4 = "ShowMessage2";
}
showMessage();   //「undifined」が出力される
showMessage2();   //「undifined」が出力される
console.info(message);    //宣言して、値を設定されていないから「undifined」が出力される
console.info(message2);  //「Hello World!」が出力される
console.info(message3);  // 宣言されていないため、例外になる
console.info(message4);  // 宣言されていないため、例外になる

ShowMessageとShowMessage2はイコールです。原因は巻き上げと呼ばれる仕組みです。
varで宣言した変数は場所と関係なく、宣言した関数スコープ又はグローバルスコープの先頭に持っていかれるので、どこで宣言しても、同じスコープ内であればどこでも利用可能。

ちなみにvarなしで変数を宣言したら、グローバル変数になります

function show(){
    message = "global var";
}
show();
console.info(message);   //[global var]が出力される

※このようなグローバル変数宣言はお勧めしない、いろいろと複雑、面倒なことになりますので。

そしてvarの場合は同じ変数を複数回宣言してもエラーにはならない、かつ変数に新たな値をセットしない限り値も変わることはない。

var test=1;
var test;
console.info(test);//[1]が出力される

let

letはvarと似ている、一番重要かつ大きな違いは作用するスコープが違う、ブロックスコープになります。ローカル変数とも言える

if(true){
  let message = "hello";
  console.info(message);//[hello]が出力される
}
console.info(message);//例外発生

letは var キーワードのように、変数をブロックスコープに関係なく、グローバルや関数全体のローカルに定義するようなことはありません。
letは自身を定義したスコープとそこに含まれるサブブロックがスコープになります。

const

constはletと基本的に同じ、正しいconstでは宣言と同時に初期化しなければならない、しかも初期化した後は変更不可

const message1;  //例外
const message2 = "hello";
message2 = "hello2";//例外

グローバル宣言

var name="gold";
console.info(window.name);//[gold]が出力される

let age=20;
console.info(window.age);//[undifined]が出力される

letで宣言したグローバル変数はvarのようにwindowのプロパティにはならない。

思考

for(var i=0;i<5;i++){
  setTimeout(()=>console.info(i),0);
}
for(var j=0;j<5;j++){
  setTimeout((m)=>console.info(m),0,j);
}
for(let k=0;k<5;k++){
  setTimeout(()=>console.info(k),0);
}

上記の三つのforループのそれぞれの出力結果と原因を考えてください
1.「5,5,5,5,5」
2.「0,1,2,3,4」
3.「0,1,2,3,4」

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Lambda で返ってくる文字列でハマった

問題

Lambda、API Gateway を使って Web ブラウザからの入力結果を処理していた。Lambda 関数の戻り値に不要なダブルクォーテーションがついていた。

以下のような Lambda 関数を作成した。

lambda_function.py
if bool:
    return 'Exist'
else:
    return 'NotExist'

lambda_function.pyの戻り値がresponse.text()に格納されるのだが、bool が True であるにも関わらず、result === 'Exist' の結果が false になっていた。

main.js
fetch(url, requestOptions)
.then(response => response.text())
.then(result => {
  if (result === 'Exist') {
    alert('存在します。');
  } else {
    alert('存在しません。');
  }
})

ログを見ると、result の値が ""Exist"" となっていた。そこで replace メソッドを使った。

main.js
fetch(url, requestOptions)
.then(response => response.text())
.then(result => {
  if (result.replace(/"/g, '') === 'Exist') {
    alert('存在します。');
  } else {
    alert('存在しません。');
  }
})

replace

'Hello, WORLD!'.replace(/o/ig, '')
// 結果:"Hell, WRLD!"
  • i フラグ:大文字と小文字の違いを無視して置換
  • g フラグ:指定した正規表現にマッチするすべての文字列を置換(グローバルマッチ)

参考記事

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【GAS】①Classroomのコース一覧を取得する

目次

  1. 【GAS】①Classroomのコース一覧を取得する(このページ)
  2. 【GAS】②Classroomのコースを新規作成

はじめに

GASによるコーディングをする際、spreadsheetやgmail、drive等は基本サービスであるGoogle Workspaceサービス内に含まれているため、書籍も含めて情報が比較的豊富に存在している。その一方でClassroomはAdvanced Googleサービスに含まれるため情報が乏しく、公式マニュアルも現在は使えないメソッドがそのまま書かれていたりと整備が追いついていない状況も見受けられる。ここではそのような状況に鑑み、ClassroomをGASで扱うために必要な基本的な知識を整理していく。

筆者のGAS開発歴は3ヶ月にも満たないため、表現や説明も適切ではない部分が多々あるだろうがご容赦願いたい。

サービスの追加

GASでClassroomに関するものを扱うためには、スクリプトエディタで「Google Classroom API」サービスを追加する必要がある。最新のIDEでは「サービス」→「Google Classroom API」を選択→「追加」で設定可能。

Classroomの一覧を取得

バインドされていないスプレッドシートをGAS内で指定して扱う際にはシートIDを指定する必要があり、IDはそのスプレッドシートを示すURLで確認できる。

残念ながらClassroomでは同じ方法で各コースのIDを知ることができないため、既存のコースに修正を加えるためには、まずコース一覧を取得してコースIDを調べる必要がある。そのための構文は以下の通り。

Classroom.Courses.list()

実際には各コースが多くの情報を含んでいるため、以下のコードでは全てのコースをログで表示できない場合が起こり得る。

function myFunction() {
  Logger.log(Classroom.Courses.list());
}

公式ページ(Manage Courses)にある以下のコードを用いれば"コース名(コースID)"の形式で出力されるので活用すると良い。optionalArgsで指定できる項目はMethod: courses.listを参照のこと。

/**
 * Lists all course names and ids. 
 */
function listCourses() {
  let courses = [];
  let pageToken = null;
  let optionalArgs = {
    pageToken: pageToken,
    pageSize: 100
  };
  while (true) {
    let response = Classroom.Courses.list(optionalArgs);
    let courses = response.courses;
    if (!pageToken) {
       break;
    }
  }
  if (courses.length === 0) {
    Logger.log("No courses found.");
  } else {
    Logger.log("Courses:");
    for (course in courses) {
      Logger.log('%s (%s)', courses[course].name, courses[course].id);
    }
  }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【GAS】①Classroomの一覧を取得する

はじめに

GASによるコーディングをする際、spreadsheetやgmail、drive等は基本サービスであるGoogle Workspaceサービス内に含まれているため、書籍も含めて情報が比較的豊富に存在している。その一方でClassroomはAdvanced Googleサービスに含まれるため情報が乏しく、公式マニュアルも現在は使えないメソッドがそのまま書かれていたりと整備が追いついていない状況も見受けられる。ここではそのような状況に鑑み、ClassroomをGASで扱うために必要な基本的な知識を整理していく。

筆者のGAS開発歴は3ヶ月にも満たないため、表現や説明も適切ではない部分が多々あるだろうがご容赦願いたい。

サービスの追加

GASでClassroomに関するものを扱うためには、スクリプトエディタで「Google Classroom API」サービスを追加する必要がある。最新のIDEでは「サービス」→「Google Classroom API」を選択→「追加」で設定可能。

Classroomの一覧を取得

バインドされていないスプレッドシートをGAS内で指定して扱う際にはシートIDを指定する必要があり、IDはそのスプレッドシートを示すURLで確認できる。

残念ながらClassroomでは同じ方法で各コースのIDを知ることができないため、既存のコースに修正を加えるためには、まずコース一覧を取得してコースIDを調べる必要がある。そのための構文は以下の通り。

Classroom.Courses.list()

実際には各コースが多くの情報を含んでいるため、以下のコードでは全てのコースをログで表示できない場合が起こり得る。

function myFunction() {
  Logger.log(Classroom.Courses.list());
}

公式ページ(Manage Courses)にある以下のコードを用いれば"コース名(コースID)"の形式で出力されるので活用すると良い。optionalArgsで指定できる項目はMethod: courses.listを参照のこと。

/**
 * Lists all course names and ids. 
 */
function listCourses() {
  let courses = [];
  let pageToken = null;
  let optionalArgs = {
    pageToken: pageToken,
    pageSize: 100
  };
  while (true) {
    let response = Classroom.Courses.list(optionalArgs);
    let courses = response.courses;
    if (!pageToken) {
       break;
    }
  }
  if (courses.length === 0) {
    Logger.log("No courses found.");
  } else {
    Logger.log("Courses:");
    for (course in courses) {
      Logger.log('%s (%s)', courses[course].name, courses[course].id);
    }
  }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reduxの基本をまとめてみた

はじめに

主に公式のチュートリアルを参照しながらReduxを勉強したので簡単に記事にまとめようと思います。
(React公式もそうですが、フロント系の公式ドキュメントは記載がとても丁寧で助かりますね。)
もし誤り等ありましたらコメントでご指摘いただけますと助かります :bow:

Reduxとは?

UIが持つ状態(state)を管理するためのJSのライブラリです。(VueやAngularに使うこともできますが、Reactと最も相性が良いです。)
Reactのようなフロントのフレームワークにおいてコンポーネントのstateをどのように管理するかは、パフォーマンスやメンテナンス性にも関わる重要な命題であると思います。(僕自身よく頭を悩ませます。。)
Hooks(useReducer)を使用した管理方法などもありますが、Reduxはstoreというコンポーネントとは独立した場所でグローバルにstateを管理するライブラリです。基本的にstateの管理はローカルに行い、異なるコンポーネント間でstateを共有するときは共通の祖先コンポーネントまで遡るのが一般的なやり方かと思いますが、規模の大きなアプリケーションでstate管理がつらくなってきたときに導入を検討する類のライブラリのようです。
公式も「様々な場所に複雑な処理を行うstateが散りばめられた大きなアプリケーションで効果を発揮するライブラリである」みたいなことを言っており、Not all apps need Redux とドキュメントに明記されています。

基本的な流れ

Reduxでは、stateを管理するstoreに対し、処理に関する情報を持ったactionをdispatch(「送り込む/割り当てる」みたいなイメージ持っています)することにより、stateを更新します。
storeの中では、reducerという関数がdispatchされたactionを解釈し、更新した新しいstateを返します。

action

アプリケーションに対する何かしらのイベントを表すもので、ユーザーによる操作をトリガーに生成されます。
実態はオブジェクトで、イベントの性質を表すtypeプロパティを持ちます。例えば、countというstateの数字に1を追加するようなactionであった場合、 { type: 'increment_count' } のようなイメージです。

store

stateをオブジェクトとして管理します。後述のreducerを渡して生成します。
既存のstateには、getStateメソッドをかけることでアクセスすることができます。
そしてこのstoreがdispatchメソッドを持っており、actionを引数にdispatchすることでstateの操作を行うことができます。その具体的な処理については、後述のreducerで行います。

reducer

現在のstateとactionを引数として受け取り、stateを返す関数です。storeの中で機能します。
actionを解釈してstateの更新が必要であれば新しいstateを生成して返し、更新が必要なければ既存のstateをそのまま返すのが基本動作です。

上述の要素がどのように関連しあってstateを更新しているかの流れは公式のフロー図がとっても分かりやすいです。

①ユーザーからの入力(ボタンを押すなど)がある
②actionがstoreにdispatchされる
③storeの中ではreducerが渡されたactionに基づいてstateを更新する
④新しいstateに基づいてUIが再レンダリングされる

といった流れです。

簡単な実例

create-react-app で作ったReactプロジェクトの簡単な実例です。
Upボタンを押せば表示の数字がカウントアップされ、Resetボタンを押せば0に初期化されるだけのごくごくシンプルなアプリケーションです。

まずはsrc/index.jsファイルです。
ルートコンポーネントであるAppコンポーネントをreact-redux提供のProviderコンポーネントでラップし、Providerコンポーネントにインポートしたstoreを渡しております。このstoreに対して、既存stateの取得なりactionのdispatchなりをしていくことになります。

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './app/store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

次に、そのstoreを定義しているsrc/app/store.jsファイルです。
簡略的にreducerをここで定義し、store作成時に渡しています。
reducerではaction.typeを見て処理を判断し、stateを更新する必要がある場合は、新たにstateオブジェクトを生成して返しています。(既存のstate自体を変更するのでなく、新しいstateオブジェクトを生成して返すことがreducer関数では重要です。)

src/app/store.js
import { createStore } from 'redux';

const initialState = {
  count: 0,
};

const reducer = (state = initialState, action) => {
  switch(action.type) {
    case 'increment_count':
      return {
        count: state.count + 1,
      };
    case 'reset_count':
      return {
        count: 0,
      };
    default:
      return state;
  }
};

const store = createStore(reducer);

export default store;

次に、このように作成してReactと紐づけたstoreに対してどのようにアクセスするかですが、src/App.jsを見てみましょう。
storeへのアクセスの方法のひとつとして、useSelectorとuseDispatchというHooksを利用することができます。
storeのstateの取得にはuseSelectorが使えます。引数ではどのstateが欲しいか指定する関数(selector)を渡します。またこのuseSelectorはstoreのstateの更新/差分を感知し、再レンダリングを行なってくれます。
useDispatchはstoreへのdispatchメソッドを提供してくれます。actionを引数にこれを呼べば、storeへdispatchすることができます。

src/App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';

function App() {
  const count = useSelector((state) => state.count);
  const dispach = useDispatch();

  const increment = () => {
    dispach({ type: 'increment_count' });
  };
  const reset = () => {
    dispach({ type: 'reset_count' });
  };

  return (
    <div className="App">
      <p>Counter: {count}</p>
      <button onClick={increment}>Up</button>
      <button onClick={reset}>Reset</button>
    </div>
  );
}

export default App;

まとめ

Reduxの基本的な処理の流れを理解する良い機会になりました。React経験をもっと積んでケースに応じた適切なstate管理方法を選択できるようになりたいものです。

参考

https://redux.js.org
https://ics.media/entry/200409/
https://reffect.co.jp/react/react-redux-for-beginner

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【配列】forEach・map・filter・find・some・reduce

処理概要

forEach

  • 配列中のそれぞれの要素について関数を実行する
const numbers = [1, 2, 3, 4];

numbers.forEach(num=> console.log(num));

// 出力
// 1
// 2
// 3
// 4

map

  • 配列内のすべての要素に指定した関数を実行する
  • 関数の結果を格納した新しい配列を生成する
const numbers = [1, 2, 3, 4];
const squares = numbers.map((num) => {
  return num * num;
});

console.log(numbers); // [1, 2, 3, 4]
console.log(squares); // [1, 4, 9, 16]

filter

  • 指定した関数の結果が true を返す配列中の要素を格納した新しい配列を生成する
const numbers = [1, 2, 3, 4];
const evenNumbers = numbers.filter((num) => num % 2 === 0);

console.log(numbers); // [1, 2, 3, 4]
console.log(evenNumbers); // [2, 4]

find

  • 指定した関数を満たす配列内の最初の要素の値を返す
const numbers = [1, 2, 3, 4];
const firstEvenNumber = numbers.find((num) => num % 2 === 0);

console.log(numbers); // [1, 2, 3, 4]
console.log(firstEvenNumber); // 2
  • 1つも見つからない場合は undefined を返す
const numbers = [1, 3, 9];
const firstEvenNumber = numbers.find((num) => num % 2 === 0);

console.log(numbers); // [1, 3, 9]
console.log(firstEvenNumber); // undefined

some

  • 指定した関数を配列中の少なくとも1つの要素が満たした場合に true を返す
const numbers = [1, 2, 3, 4];
const isEvenNumbers = numbers.some((num) => num % 2 === 0);

console.log(numbers); // [1, 2, 3, 4]
console.log(isEvenNumbers); // true
const numbers = [1, 3, 9];
const isEvenNumbers = numbers.some((num) => num % 2 === 0);

console.log(numbers); // [1, 3, 9]
console.log(isEvenNumbers); // false

reduce

  • 配列のすべての要素に対して指定した関数を(左から右の順で)実行し、単一の出力値を生成する
const numbers = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(numbers.reduce(reducer)); // 10

// 5 + 1 + 2 + 3 + 4
console.log(numbers.reduce(reducer, 5)); // 15

上記を全て forEach で実現するのはだめなのか

結論

  • forEach は極力使用しない

理由

  • 適切なメソッドを選択することで可読性が上がるため

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】axiosでCSVを受け取りブラウザでファイルダウンロードに移行させる方法。

前提

サーバーサイドはLaravel、フロントはVue.jsです。
今回はJavaScriptの話がメインなのでPHPやLaravelが分からない方でも支障なく読んでいただけると思います。

やりたかったこと

ユーザー目線:ブラウザに表示されているダウンロードボタンをクリックすると、CSVファイルをダウンロードできる。

僕目線:LaravelでCSVを吐き出すAPIを用意し、axiosを使ってAPIを叩きCSVをダウンロードできるようにする。

起こった問題

ブラウザの検索タブでエンドポイントに直接アクセスするとうまくダウンロードできるが、axiosを使ってエンドポイントにアクセスするとダウンロードできない。(CSVの内容はデータとして返ってくるが、ブラウザがダウンロード画面に移行しない。)

失敗した方法

CSVを返すAPIを単純に叩いてダウンロードできると思ったのですが、うまくいきませんでした。
※関係ない部分は色々省略してます。

sample.js
downloadCsv() {
    axios
      .get("/api/download/csv", {
      })
      .catch((error) => {
        console.log(error.messagae);
      });
  },

CSVのデータはちゃんと返ってきますが、ブラウザがダウンロードに移行しません。(ユーザー目線だと何も起こらない。)

うまくいった方法

コードを下記のようにかえるとうまくダウンロードできました。

sample.js
import saveAs from "file-saver";
// 省略
downloadCsv() {
  axios
    .get("/api/download/csv", {
      responseType: "blob",
    })
    .then((res) => {
      let mineType = res.headers["content-type"];
      const name = res.headers["content-disposition"];
      const blob = new Blob([res.data], { type: mineType });
      saveAs(blob, name);
    })
    .catch((error) => {
      console.log(error.messagae);
    });
};

追記部分を解説していきます。

リクエスト時の処理

sample.js
.get("/api/download/csv", {
  responseType: "blob",
})

データをBLOBとして受け取ります。
BLOBとはBinary Large OBjectの略で、IT用語辞典では以下のように解説されています。

BLOBとは、データベースのフィールド定義などで用いられるデータ型の一つで、テキスト(文字列)や整数のように既存のデータ型としては用意されていない任意のバイナリデータを格納するためのもの。

つまり、BlOBはテキストファイルだけではなく画像やPDFなどいろいろな形式のファイルを扱うことができる訳です。

そしてJavaScriptでは受け取ったデータをBOLBにするとこで、ファイルにすることが可能になります。

CSVはテキストデータなのでBLOBにする必要はないのでは?と思ったのですが、データをファイルにするために必要なようです。

レスポンスを受け取った後の処理

sample.js
.then((res) => {
  let mineType = res.headers["content-type"];
  const name = res.headers["content-disposition"];
  const blob = new Blob([res.data], { type: mineType });
  saveAs(blob, name);
})

res.headers["content-type"]にはLaravel側で設定した'text/csv'が格納されています。今回は必ず'text/csv'が返るようになっていますが、ダウンロード用のメソッドを色々な形式に対応できるようにするためにこのように書く必要がありますね。

res.headers["content-disposition"]にはLaravel側で設定したファイル名が格納されています。

new Blob([res.data], { type: mineType });
JavaScriptのBlobオブジェクトのインスタンスを生成しています。
BlobオブジェクトはBLOBをJavaScriptで扱うためのオブジェクトです。
第一引数にファイルの内容の配列、第二引数にファイルの種類を指定して使います。

saveAs(blob, "file");
'file-server'というライブラリを使ってファイルを保存しています。
詳しくは割愛しますが、ブラウザ間で異なるファイル保存の処理を1行で書けます。

文字化けを修正

無事CSVをダウンロードすることができましたが、ファイルの内容が文字化けしていました。
はっきりとした原因は分かりませんでしたが、Laravel側でSJIS形式に変換していた部分をUTF-8に変換するように変更すると文字化けしなくなりました。

sample.php
// mb_convert_encoding($content, 'SJIS', 'auto');
mb_convert_encoding($content, 'UTF-8', 'auto');

HTMLのmetaタグでUTF-8に指定しているのが原因なのか?
とりあえず、これで内容も分かるCSVファイルをダウンロードできるようになりました。めでたしめでたし。

最後に

aixosを使ってファイルをダウンロードするにはひと手間いることが分かりました。
BLOBについては恥ずかしながら全然知らなかったです。

今回はLaravel側でCSVを作成しましたが、データをJSON形式で送るようにしてVue側でCSVを作成することもできそうです。

他にもこんな方法があるとか、ここ間違ってるよとかあればご指摘等よろしくお願いします!
ではでは。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Mixで環境に応じて複数の.envで環境変数を管理する

はじめに

こんにちは。先日、ランニングシューズ以外でいい靴を買ってしまいました、筆者です:smile:

さて、LaravelでWebpack使っているので、Laravel Mixを使用しております。

その際に.envで環境変数を分ける機会がありましたので、共有します。

結論

急いでいる方はこちらご参照くださいませ。Laravel Mixのドキュメントの書いてあるんです:ok_hand:
(ただ、スター:star:が超少ないのが気になります...:thinking:)

解説

1. mix-env-file をインストールする。

$ npm install mix-env-file

2. dotenv をインストールする。

あとでコンパイルするときにインストールしろと怒られるのでこちらもインストールします。
(ドキュメントには書いてないんです:sob:)

$ npm install dotenv

3. package.jsonを編集する。

サンプルはこちら↓

package.json
"scripts": {
  "dev": "cross-env ENV_FILE=./.env.dev npm run development",
  "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
  "watch": "npm run development -- --watch",
  "watch-poll": "npm run watch -- --watch-poll",
  "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
  "prod": "cross-env ENV_FILE=./.env.prod npm run production",
  "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}

上記の場合、以下の動きをします。
npm run devしたときは、./.env.devを読みます。
npm run prodしたときは、./.env.prodを読みます。

4. webpack.mix.js を編集する。

webpack.mix.js
let mix = require('laravel-mix');
require('mix-env-file');

// Then pass your file to this plugin
// If this is not set, this plugin won't do anything and the default .env variables will remain
mix.env(process.env.ENV_FILE);

以上です:ok_hand:

おわりに

.env便利でした:smile:
それでは!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】別ファイルに関数をまとめてexportsを利用して呼び出す。

開発環境

React.js

概要

JavaScriptで関数を共通化して別ファイルにまとめたときに、HTMLのscriptタグを使い呼び出すのは面倒だと思いました。JavaScriptのexportsを使い呼び出すことができることを知りましたので記事にしておきます。

import.jsとexport.jsファイルを作成

import.jsからexport.jsの関数を呼び出していきます。

export.js
exports.criminalIsKogoro = function () {
  console.log("犯人は毛利小五郎");
}

exports.detectiveCriminal = function (name) {
  console.log("犯人は" + name);
}

const criminalIsAgasa = function () {
  console.log("犯人は阿笠だ");
}

比較するためにcriminalIsAgasaだけはexportsしないようにしておきます。

import.js
import exportFunction from 'export.jsのパスを記述'
// または
// var exportFunction = require('export.jsのパスを記述');

exportFunction.criminalIsKogoro; // "犯人は毛利小五郎"
exportFunction.detectiveCriminal("元太"); //"犯人は元太"
exportFunction.criminalIsAgasa; // error. exportFunction.criminalIsAgasa is not a function

このようにexportsをしておかないと外部のファイルから読み込むことができないことが分かりました。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React.js】別ファイルに関数をまとめてexportsを利用して呼び出す。

開発環境

React.js

概要

React.jsで関数を共通化して別ファイルにまとめたときに、HTMLのscriptタグを使い呼び出すのは面倒だと思いました。JavaScriptのexportsを使い呼び出すことができることを知りましたので、備忘録として記事に残しておきます。

import.jsとexport.jsファイルを作成

import.jsからexport.jsの関数を呼び出していきます。

export.js
exports.criminalIsKogoro = function () {
  console.log("犯人は毛利小五郎");
}

exports.detectiveCriminal = function (name) {
  console.log("犯人は" + name);
}

const criminalIsAgasa = function () {
  console.log("犯人は阿笠だ");
}

比較するためにcriminalIsAgasaだけはexportsしないようにしておきます。

import.js
import exportFunction from 'export.jsのパスを記述'
// または
// var exportFunction = require('export.jsのパスを記述');

exportFunction.criminalIsKogoro; // "犯人は毛利小五郎"
exportFunction.detectiveCriminal("元太"); //"犯人は元太"
exportFunction.criminalIsAgasa; // error. exportFunction.criminalIsAgasa is not a function

このようにexportsをしておかないと外部のファイルから読み込むことができないことが分かりました。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React 入門 (#2) ~Babel&JSX~

1,Babelとは

2021-03-14_14h24_31.png

ES6以降のスクリプトを、ES2015基準のスクリプトにトランスパイルする機能です。

下記のタグをheadタグに記述すれば準備完了です。

index.html
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

Babelリンク

2,JSXを使う理由

Reactはマークアップとロジックを両方含む疎結合の「コンポーネント」という単位で構成されます。
コンポーネント」は、次回説明します。
そこで活躍するのが、JSX(「JavaScript XML」の略)です。
Reactのコンポーネント内で、マークアップ言語を記述するためのXML風の構文です。

3、ソースコードを記述

前回からの続きになります。
まず、index.htmlの準備です。
code6.png

index.jsに移動して記述します。
code7.png

toUpperCase()は、すべて大文字にするメソッドです。

4,ブラウザ表示

2021-03-14_21h51_55.png
リストが登場していますね。

次回は、

コンポーネントについて扱っていきます。
次回はここへ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js開発者なら知っておきたい便利なパッケージ12選

本記事は、Indrek Lasn氏による「12 Useful Packages Every Node.js Developer Should Know」(2020年9月2日公開)の和訳を、著者の許可を得て掲載しているものです。

Node.js開発者なら知っておきたい便利なパッケージ12選

毎日の生産性を上げるNodeパッケージ

Image for post

はじめに

Node.jsはコードの再利用にぴったりです。コードを再利用するための根幹となるのはNPMパッケージです。

NPMパッケージは、時間と労力を大幅に節約してくれます。日付ライブラリが必要ですか?パッケージがあります。ユーティリティライブラリが必要ですか?問題ありません。コードの問題解決が必要な時はいつでも、必要に応じたパッケージがあるでしょう。

これは、すべてのNode.js開発者が知っておくべきパッケージのリストです。このNPMパッケージは、時間を節約し、魔法のように解決する助っ人のようなものです。

1. husky

huskyはgitフックの実装を簡単にしてくれます。チームで仕事をしていて、チーム全体にコーディング規約を適用したいと思うことはありませんか?問題ありません!huskyを使えば、リポジトリにコミットしたりプッシュしたりする前に、コードを自動的にlintしてテストするように全員に要求できます。

Image for post
husky ― https://github.com/typicode/husky

インストール方法

yarn add husky

使い方

huskyフックの実装例です。

// package.json
{
   "husky": {
      "hooks": {
         "pre-commit": "npm lint",
         "pre-push": "npm test"
      }
   }
}

huskyexample.json
huskyフック例

pre-commitフックは、リポジトリにコミットする前に実行されます。

pre-pushフックは、コードをリポジトリにプッシュする前に実行されます。

2. dotenv

dotenvは、環境変数を.envファイルからprocess.envにロードするゼロ依存モジュールです。コードとは別の環境に設定を保存することは、The Twelve-Factor Appの方法論に基づいています。
dotenv

インストール方法

yarn add dotenv

使い方

アプリケーションのできる限り早い段階で、dotenvを要求して設定します。

require('dotenv').config()

プロジェクトのルートディレクトリに.envファイルを作成します。NAME=VALUEの形式で、新しい行に環境固有の変数を追加します。

例:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

process.envで、.envファイルで定義したキーと値が使えるようになりました。

const db = require('db')
db.connect({
   host: process.env.DB_HOST,
   username: process.env.DB_USER,
   password: process.env.DB_PASS
})

3. date-fns

lodashに似ていますが、date-fnsは日付のためのものです。日付の操作をもっと簡単にするユーティリティ関数がたくさんあります。

date-fnsは、ブラウザやNode.jsでJavaScriptの日付を操作するため、総合的かつシンプルで一貫性のあるツールセットを提供します。
date-fns

Image for post
date-fns ― https://github.com/date-fns/date-fns

インストール方法

yarn add date-fns

使い方

date-fnsライブラリの簡単な例です。

import { compareAsc, format } from 'date-fns'

format(new Date(2014, 1, 11), 'yyyy-MM-dd')
//=> '2014-02-11'

const dates = [
   new Date(1995, 6, 2),
   new Date(1987, 1, 11),
   new Date(1989, 6, 10),
]
dates.sort(compareAsc)
//=> [
//    Wed Feb 11 1987 00:00:00,
//    Mon Jul 10 1989 00:00:00,
//    Sun Jul 02 1995 00:00:00
// ]

その他の事例や使用例については、ドキュメントを確認してください。

4. bunyan

bunyan は、分かりやすくてパフォーマンスが高いNode用のJSONロギングライブラリです。

Image for post
bunyan ― https://github.com/trentm/node-bunyan

インストール方法

yarn add bunyan

コツbunyan CLIツールは、すべてのバージョンのbunyanのログと(合理的な範囲内で)互換性があるようになっています。そのため、yarn add global bunyanでグローバルbunyanをインストールしてbunyan CLIをPATHに追加してから、ローカルbunyanをインストールして、アプリでbunyanのNode.jsライブラリを使うと良いでしょう。

使い方

bunyanはシンプルで高速なNode.jsサービス用のJSONロギングライブラリです。

// hi.js
const bunyan = require('bunyan');
const log = bunyan.createLogger({name: "myapp"});
log.info("hi");

node hi.jsを実行するとコンソールに返される内容は、次の通りです。

Image for post

5. ramda

rambda は JavaScript プログラマ向けの実用的で機能的なユーティリティライブラリです。rambdaは、より純粋な機能性を重視しています。

不変性と副作用のない関数は、rambdaの設計哲学の中心です。これにより、シンプルで洗練されたコードで仕事を成し遂げられます。

Image for post
rambda ― https://github.com/ramda/ramda

インストール方法

$ yarn add ramda

使い方

import * as R from 'ramda'
const greet = R.replace('{name}', R.__, 'Hello, {name}!');
greet('Alice'); //=> 'Hello, Alice!'

上のコードの例です。

6. debug

debugはNode.jsコアのデバッグ手法をモデルにした、小さなJavaScriptデバッグユーティリティです。

Image for post
debug ― https://github.com/visionmedia/debug

インストール方法

$ yarn add debug

使い方

debugには、モジュール名を渡すだけでconsole.errorの装飾版を返し、debugステートメントを渡す関数があります。

const debug = require('debug');
const log = debug('http:server');
const http = require('http');

const name = 'My App name';

log('booting %o', name);

http.createServer((req, res) => {
   log(req.method + ' ' + req.url);
   res.end('debug examplen');
}).listen(3200, () => {
   log('listening');
});

// run this command in the terminal
// DEBUG=http:server node app.js

app-debug-example.js
debug例

これによりデバッグ出力を、モジュール全体だけでなく、モジュールのさまざまな部分で切り替えられます。

Image for post

7. flat

flat は、ネストされたJavascriptオブジェクトを取得して平坦化します。区切りキーを使って、オブジェクトの平坦化を解除することもできます。

Image for post
flat ― https://github.com/hughsk/flat

インストール方法

$ yarn add flat

使い方

const flatten = require('flat')

flatten({
   key1: {
      keyA: 'valueI'
   },
   key2: {
      keyB: 'valueII'
   },
   key3: { a: { b: { c: 2 } } }
})

// {
//    'key1.keyA': 'valueI',
//    'key2.keyB': 'valueII',
//    'key3.a.b.c': 2
// }

8. JSON5

JSON5 データ交換フォーマットはJSON* のスーパーセットで、ECMAScript 5.1のプロダクションの一部を含めるために構文を拡張し、JSONの制限の一部を緩和します。
JSON5

Image for post
json5 ― https://github.com/json5/json5

インストール方法

yarn add json5
const JSON5 = require('json5')

使い方

ファイル拡張子に注意してください。JSON5は、JSONの拡張機能とスーパーセットです。

{
   // comments
   unquoted: 'and you can quote me on that',
   singleQuotes: 'I can use "double quotes" here',
   lineBreaks: "Look, Mom! \

No \\n's!",
   hexadecimal: 0xdecaf,
   leadingDecimalPoint: .8675309, andTrailing: 8675309.,
   positiveSign: +1,
   trailingComma: 'in objects', andIn: ['arrays',],
   "backwardsCompatible": "with JSON",
}

example.json5

9. ESLint

ESLintは、バグを回避し、開発チームにコーディング規約を適用する素晴らしいツールです。ECMAScript/JavaScriptコードで見つかったパターンを識別して報告します。

Image for post
ESLint ― https://github.com/eslint/eslint

インストール方法・使い方

$ yarn add eslint

次に、設定ファイルの作成が必要です。

$ ./node_modules/.bin/eslint --init

その後、任意のファイルやディレクトリでESLintを実行できます。

$ ./node_modules/.bin/eslint yourfile.js

詳しくは、公式ドキュメントを確認してください。始め方と設定の例がたくさんあります。

10. PM2

PM2は、Node.jsアプリケーション用のプロダクションプロセスマネージャーで、ロードバランサーを内蔵しています。これにより、アプリケーションを永続化させ、ダウンタイムなしでリロードし、一般的なシステム管理タスクを容易にできます。

Image for post
pm2 ― https://github.com/Unitech/pm2

インストール方法

$ yarn add global pm2

使い方

任意のアプリケーション(Node.js、Python、Ruby、$PATHのバイナリ等)を起動できます。

$ pm2 start app.js

アプリはデーモン化され、監視され、永続化します。プロセス管理の詳細はこちら

アプリケーション管理

起動したアプリケーションを簡単に管理できます。実行中のすべてのアプリケーションを一覧表示する方法は次の通りです。

$ pm2 ls

Image for post
pm2 ls

機能と活用方法の全リストは、公式ドキュメントを確認してください。

11. helmet

helmetライブラリは、さまざまなHTTPヘッダを設定することでExpressアプリを保護するのに役立ちます。「特効薬ではないが、助けにはなる!」

Image for post
helmet ― https://github.com/helmetjs/helmet

インストール方法

yarn add helmet

使い方

helmet はConnectスタイルのミドルウェアで、Expressなどのフレームワークと互換性があります(Koaのサポートが必要な場合は、koa-helmetを確認してください)。

const express = require("express");
const helmet = require("helmet");

const app = express();

app.use(helmet());

トップレベルのhelmetの関数は、11個の小さなミドルウェアのラッパーです。言い換えれば、この2つは同等です。

// This...
app.use(helmet());

// ...is equivalent to this:
app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());

12. compression

compressionライブラリはNode.jsの圧縮ミドルウェアです。

Image for post
compression ― https://github.com/expressjs/compression

インストール方法

$ yarn add compression

使い方

このモジュールをexpressやconnectで使うには、expressミドルウェアでcompressionを呼び出すだけです。ミドルウェアを通過したリクエストは圧縮されます。

const compression = require('compression')
const express = require('express')

const app = express()

// compress all responses
app.use(compression())

// ...

おわりに

私のニュースレターでは、コンテンツの最新情報の通知を、いち早く受け取ることができます。ぜひ登録してください。

Zack Shapiroに謝意を表します。

翻訳協力

この記事は以下の方々のご協力により公開する事ができました。改めて感謝致します。

Original Author: Indrek Lasn (@lasnindrek)
Original Article: 12 Useful Packages Every Node.js Developer Should Know
Thank you for letting us share your knowledge!

選定担当: @gracen
翻訳担当: @gracen
監査担当: -
公開担当: @gracen

ご意見・ご感想をお待ちしております

今回の記事はいかがでしたか?
・こういう記事が読みたい
・こういうところが良かった
・こうした方が良いのではないか
などなど、率直なご意見を募集しております。
頂いたお声は、今後の記事の質向上に役立たせて頂きますので、お気軽に
コメント欄にてご投稿ください。Twitterでもご意見を受け付けております。
皆様のメッセージをお待ちしております。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Material-UIで一覧画面を作ってみる(React)

はじめに

今回は、Material-UIの使い方や使ってみた所感を書いていきたいと思います。

Material-UIとは

Material-UIとは、Googleのマテリアルデザインの仕様を取り入れているReact用のUIコンポーネントライブラリです。Material-UIを利用することで手軽に見栄えの良いコンポーネントを作成することができます。

Material-UI

マテリアルデザインとは

マテリアルデザインとは、Googleが提唱している物質的なデザインのガイドラインです。スマートフォンやタブレットなどのタッチデバイスの普及により直感的に操作ができるUIへの需要が高まってきた中で生まれた概念です。

Material Design

環境

今回の使用バージョンはそれぞれ以下の通りです。

  • Node.js v12.19.0
  • React v16.13.1
  • @material-ui/core v4.11.0

Material-UIの導入

次のコマンドを実行し、Material-UIをインストールします。

# npmの場合
npm install @material-ui/core

# yarnの場合
yarn add @material-ui/core

ディレクトリ構成

ディレクトリ構成は以下のようになります。今回はあくまでも簡単なページを作成することを目的としているため、Reactを使用しシステムを作成する場合は、様々な構成を調査し作成したいシステムに合った構成を探してみてください!

Reactのファイル構成について

src/
 ├ components/
 │ └ header.js   
 │ └ card.js     
 ├ pages/
 │ └ _app.js     
 │ └ _document.js     
 │ └ index.js     
 └ public/
 │ └ image/
 │   └ ika.png
 └ package.json

早速使ってみる

今回は公式ドキュメントのソースコードを参考に一覧画面を作成しながら、Material-UIによって作成できるコンポーネントを紹介していきます。

ページの骨組みを用意する

これから作成するコンポーネント達を配置するために、ページの骨組みを用意します。

pages/index.js
import { Header } from '../components/header';
import { Card } from '../components/card';

const Index = () => (
  <div>
    <Header />
    <Card />
  </div>
)

export default Index

表示させてもまだ何もないので真っ白のページが表示されますが、確認方法を説明します。
以下のコマンドでローカルホストを立ち上げ、http://localhost:3000/にアクセスすることで確認できます。

# npmの場合
npm run dev

# yarnの場合
yarn dev

components/header.jsなどインポート宣言しているファイルを作成していないとエラーになるのでご注意ください。

ヘッダーを作成してみる

まずはWebサイトには欠かせないヘッダーを作成していきます。早速書いてみましょう!
実際のコードは以下になります。

components/header.js
export const Header = () => {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <AppBar position="static">
        <Toolbar>
          <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" className={classes.title}>
            TOP
          </Typography>
          <Button color="inherit">Login</Button>
        </Toolbar>
      </AppBar> 
    </div>
  );
}

AppbarTypographyなどのタグはインポートをすることで使用できます。
className={classes.root}の記述ではタグにクラス属性を付与し、見た目を調整することができます。

結果は以下になります。シンプルなヘッダーを作成することができました。
image.png

せっかくなのでメニューアイコンを動くようにしてみましょう!以下のように書いていきます。

components/header.js
export const Header = () => {
  const classes = useStyles();
  const theme = useTheme();
  // stateとstateを更新するための関数を宣言
  const [open, setOpen] = React.useState(false);

  // メニューを開く関数
  const handleDrawerOpen = () => {
    setOpen(true);
  };

  // メニューを閉じる関数
  const handleDrawerClose = () => {
    setOpen(false);
  };

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar
        position="fixed"
        className={clsx(classes.appBar, {
          [classes.appBarShift]: open,
        })}
      >
        <Toolbar>
          {/* メニューアイコンクリック時に呼び出す関数を定義 */}
          <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            edge="start"
            className={clsx(classes.menuButton, open && classes.hide)}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            TOP
          </Typography>
        </Toolbar>
      </AppBar>
      {/* メニュー部分 */}
      <Drawer
        className={classes.drawer}
        variant="persistent"
        anchor="left"
        open={open}
        classes={{
          paper: classes.drawerPaper,
        }}
      >
        <div className={classes.drawerHeader}>
          {/* 閉じるアイコンクリック時に呼び出す関数を定義 */}
          <IconButton onClick={handleDrawerClose}>
            {theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
          </IconButton>
        </div>
        <Divider />
        <List>
          {links.map((link) => (
            <ListItemLink href={link.link} key={link.id}>
              <ListItemText primary={link.label} />
            </ListItemLink>
          ))}
        </List>
      </Drawer>
      <main
        className={clsx(classes.content, {
          [classes.contentShift]: open,
        })}
      >
      </main>
    </div>
  );
}

先ほどのシンプルなヘッダーに比べて記述量は増えましたが、簡単ですね。
Reactではコンポーネントの状態を管理するためにstateを使用します。stateの更新にはsetStateを使用します。この例ではメニューアイコンをクリックしたときにメニューを開くために、openというstateで状態を管理しています。

無事動かすことができました!

header.gif

コンテンツを作成する

続いてコンテンツを作成します。今回はカードを並べるような感じでコンテンツを一覧表示させますので、カードのコンポーネントを作成していきます。

components/card.js
export const Card = () => {
  const classes = useStyles();

  return (
    <div className={classes.main}>
      <Card className={classes.root}>
        <CardActionArea>
          <CardMedia
            className={classes.media}
            image="イメージパス"
            title="Contemplative Reptile"
          />
          <CardContent>
            <Typography gutterBottom variant="h5" component="h2">
              タイトル
          </Typography>
            <Typography variant="body2" color="textSecondary" component="p">
              説明
          </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small" color="primary">
            Share
        </Button>
          <Button size="small" color="primary">
            Learn More
        </Button>
        </CardActions>
      </Card>
    </div>
  );
}

以下のような一覧画面ができました。(上記のコードは1枚のカードを生成するコードです。)
image.png

レスポンシブ対応について

ちなみに今回作成したページはレスポンシブ対応になっています。スマートフォンで表示したときは以下のような表示になります。驚きなのが、特にレスポンシブ対応のための実装はしていないことです。便利ですね:clap:
SP.gif

今回はMaterial-UIを使用し、このような一覧画面を作成することができました。簡単に見た目の良いページを作成でき扱いやすさを感じました!

あとがき

Webシステムのクオリティを上げるには処理の精度を上げることと並行してデザインも重要ですよね。私自身、最近の業務でデザイナーさんの力を全力で感じています。
ただ、システム作成の際に見栄えを良くしたいと思ってもデザインに割く時間が無かったり、デザイナーさんに頼めないという場面もあるかと思います。そんな時は今回紹介したMaterial-UIなどのUIフレームワークを利用してみるのもいいかもしれません。Material-UI以外にも多種多様なUIフレームワークが用意されていますので気になった方はぜひ一度使ってみてください。

最後までお読みいただき、ありがとうございました:slight_smile::sunflower:

参考資料

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptで配列に使えるメソッドまとめ

配列を作成したい

// 配列リテラルを使う
const array1 = [1,2,3]

// Arrayコンストラクタを使う
const array2 = new Array(4,5,6)
const array3 = Array(7,8,9)

// Array.fromを使う
const arrayLike = { length:3, '0':'Tokyo', '1':'Osaka', '2':'Fukuoka' }
const cities = Array.from(arrayLike)

// ファクトリー関数Array.ofを使う
const array4 = Array.of('USA', 'Japan', 'China')

配列かどうか確認したい

const str = 'string'
const num = 2021
const array = [1,2,3]

Array.isArray(array) // => true
Array.isArray(str) // => false
Array.isArray(num) // => false

配列の長さを取得したい

// Array.prototype.lengthを使う
const array = [1,2,3]
array.length // => 3

配列の要素を追加したい

1. Array.prototype.push() (配列の末尾に要素を追加する)

let array = [1,2,3,4,5]
const arrayLength = array.push(6) // => 6
console.log(array) // => [1,2,3,4,5,6]

// Array.prototype.push()は複数の引数を取ることもできる
let array2 = [1,2,3]
let array3 = [4,5,6]
array2.push(...array3)
console.log(array2) // => [1,2,3,4,5,6]

Array.prototype.push()は
- 破壊的 (レシーバになった配列を変更する)
- 戻り値は配列に要素を追加したあとの配列の長さ
- メソッドの引数は追加したい要素

2. 要素を追加するインデックスに配列の長さを指定する

あまり使わないとは思いますが、要素を追加したいインデックスを直接指定してあげることもできます。

let array = [1,2,3,4,5]
array[array.length] = 6
console.log(array) // => [1,2,3,4,5,6]

// 配列の末尾よりも大きいインデックスを指定すると、要素は指定されたインデックスに入る
// 間の要素はundefinedで埋められる
array[array.length + 1] = 8
console.log(array) // => [1, 2, 3, 4, 5, 6, undefined, 8]

3. Array.prototype.unshift() (配列の先頭に要素を追加する)

let array = [1,2,3]
array.unshift(-2,-1,0) // => 6
console.log(array) // => [-2,-1,0,1,2,3]

Array.prototype.unshift()は
- 破壊的
- 戻り値は配列に要素を追加したあとの配列の長さ
- メソッドの引数は追加したい要素

配列の要素を削除したい

1. Array.prototype.pop() (配列の最後の要素を削除する)

const array = [1,2,3,4,5]
array.pop() // => 5
console.log(array) // => [1,2,3,4]

Array.prototype.pop()は
- 破壊的
- 戻り値は削除した要素、つまり元の配列の最後の要素
- メソッドの引数は追加したい要素

配列を結合したい

1. スプレッド構文を使う

const array1 = [1,4,9]
const array2 = [16,25,36]
const array3 = [...array1, ...array2] // => [1,4,9,16,25,36]

// pushを使ってもできる
array1.push(array2) // => [1,4,9,16,25,36]

2. Array.prototype.concat()

const array1 = [1,4,9]
const array2 = [16,25,36]
const array3 = array1.concat(array2) // => [1,4,9,16,25,36]

Array.prototype.concat()は
- 非破壊的
- 戻り値は結合した配列のコピー
- メソッドの引数は結合したい配列

3. Array.prototype.push.apply()

array1.push(...array2)で連結できる以上これを使うことはないと思いますが、このやり方でも配列を結合することができます。

const array1 = [1,4,9]
const array2 = [16,25,36]
Array.prototype.push.apply(array1, array2) // => 6
console.log(array1) // => [1,4,9,16,25,36]

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

実務でよく使うVueのv-bind:classの使い方4つ

v-bind:classはVueで使えるv-bindディレクティブの一つです。
公式で紹介されてるものより、個人的には使い勝手がいいなと思う方法など、自分がよく使う4パターンを紹介します。

1.真偽値に対して複数クラス

例:アクティブの時はテキストを青くして背景をグレーにしたい

sample.vue
<div :class="{'text-blue bg-grey': isActive}"></div>

2.複数の真偽値

例:アクティブの時はテキストを青くして、選ばれている時は背景をグレーにしたい

sample.vue
<div :class="{ 'text-blue' : isActive , 'bg-grey' : isSelected }"></div>

3.式(演算子)を使う

比較演算子や論理演算子を使って真偽値をかえします。

sample.vue
<div :class="{'text-blue':  apple == sale }"></div>
<div :class="{'text-blue': apple > 3}"></div>
<div :class="{'text-blue': apple && banana}"></div>
<div :class="{'text-blue': apple || banana}"></div>

4.三項演算子(条件分岐)

例:アクティブの時はテキストを青くしてそうじゃなかったらテキストを黒くしたい

sample.vue
<div :class="isActive?'text-blue':'text-black'"></div>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

M1 MacでLIFFとReactを使う際の環境構築

初めに

2021年3月の現在、Open Hack U 2020 Online Vol.4に挑戦しています。
チームの制作物で、LIFF (LINE Front-end Framework)を使ったものを作成することにしました。
M1 Macbook AirでLIFFを使うのは、初めてです。
そこで、環境構築などで詰まったところを書いておき、再度M1 MacでLIFFを使うときにつまらないようにするための備忘録です。

本記事の目的

本記事は、ハッカソンなどで、M1 Macbookを使う人のために書きました。
色々なアプリを作る時の候補として、LIFFを使ったアプリ開発に挑戦してみては、いかがでしょうか?

詰まったところ

参考記事1を進めていたところ、yarnがうまく使えないことがわかりました。
そのため、現時点でのM1チップのMacでは、yarnを使うのをやめましょう。

最終的なコード

最終的に作成したアプリは、こちらです。
メッセージを送信し、GoogleをChrome(デフォルトに設定してあるアプリ)で開き、友達に
メッセージを送ることができるようにしています。

進める中でインストールしたアプリ

https://dashboard.ngrok.com/get-started/setup
デプロイ先

作成したアプリ

+IMG_2395.gif

参考記事

  1. React + TypeScriptを使ってLIFFを作る
  2. 【M1 Mac】React開発環境の構築
  3. nodebrewの「Warning: Failed to create the file」への対処
  4. npmとyarnのコマンド早見表
  5. MacにngrokをインストールしてローカルWebサーバを外から接続できるようにする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript: いつものAlertを簡単に、少しだけおしゃれにするSweet Alert

Sweet Alert

流行っているらしいのでやってみた。
10 Trending projects on GitHub for web developers - 12th March 2021

GitHub

お試し

See the Pen SweetAlert by YAMADA Nobuko (@e99h2121) on CodePen.

<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>

<button type=“button” onclick="basicSample()">やさしいアラート</button>

<button type=“button” onclick="amazingSample()">すばらしいアラート</button>
function basicSample(){
  swal("きをつけてね。");
}

function amazingSample() {
  swal({
    title: "すばらしい!!",
    text: "You clicked the button!",
    icon: "success",
 });
}

自分用に使いたいときが来たらと思うメモ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React 入門 (#1) ~DOM操作とReactライブラリ導入~

この記事では、Reactの基礎について学んでいきます。

2021-03-14_12h56_17.png

ソースコードブラウザ表示を中心に進めていきます。
ソースコードには、そのコードが何を表しているのかを話し口調(下の赤枠)で書いているので
そこに注目して読むとより理解が深まると思います。

例)
2021-03-14_13h23_51.png

楽しんで学習をすすめていきましょう。

1,JavaScriptを記述してDOMの操作を行ってみます。

基本的なHTMLのソースコードです。
code.png

index.htmlにリンクしているindex.js(JavaScript)です。
code2.png

2,実際に上のソースコードの動きを確認してみましょう。

2021-03-14_12h37_47.gif

とてもシンプルな動きですね。
これが、JavaScript によるDOM操作になります。

3,Reactライブラリの導入

書き換えたindex.htmlのソースコード
code4.png

上のサイトから、追記したソースコードをコピーしてください。
もしくは、こちらをコピーしてください。

index.html
  //追記 ReactライブラリとReactDOMライブラリ
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

Reactを使うには、
ReactライブラリReactDOMライブラリを使います。
これで、準備完了です。

index.jsファイルに移動して次のコードを記述します。
code5.png

4,ブラウザ表示

index.htmlにはdivタグしかないですが、ちゃんと表示されていますね。
2021-03-14_13h43_54.png

次回は、

今回は、Reactの機能の部分を簡単に紹介しました。
次回は、Reactを学ぶうえで大事なBabelJSXに触れたいと思います。
リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

追加ボタンを押したときにulタグにliタグが追加される処理を実装してみた!

//list要素を取得
const list = document.getElementById('list');

//addボタン取得
const addButton = document.getElementById('add');

//removeボタン取得
const removeButton = document.getElementById('remove');

//追加ボタンの処理
addButton.addEventListener('click', () => {
    const newItem = document.createElement('li');
    const listItemLength = list.children.length;
    newItem.textContent = `アイテム${listItemLength + 1}`
    list.appendChild(newItem);
});

//削除ボタンの処理
removeButton.addEventListener('click', () => {

    //アイテムがない時の処理
    if (list.lastElementChild === null) {
        alert('削除できる項目がありません');
        return null;
    }

    list.removeChild(list.lastElementChild);

});

const listItemLength = list.children.length;
この1行がなかなか書けずに手こずりました。
最初は
newItem.lengthと書いてしまったが、これはダメ!

console.log();の大切さを学びました、、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

追加ボタンを押したときにulタグにliタグが追加される処理を実装してみた!

//list要素を取得
const list = document.getElementById('list');

//addボタン取得
const addButton = document.getElementById('add');

//removeボタン取得
const removeButton = document.getElementById('remove');

//追加ボタンの処理
addButton.addEventListener('click', () => {
const newItem = document.createElement('li');
const listItemLength = list.children.length;
newItem.textContent = アイテム${listItemLength + 1}
list.appendChild(newItem);
});

//削除ボタンの処理
removeButton.addEventListener('click', () => {

//アイテムがない時の処理
if (list.lastElementChild === null) {
    alert('削除できる項目がありません');
    return null;
}

list.removeChild(list.lastElementChild);

});

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript学習記録】Objectをsortしたい

 いつものように、.sort( )で並び替えをし、console.logで確認したところ、中身に変化がない・・・。
 どうやらObjectは、.sort( )では並び替えできないようです。
 どうしたら並び替えることができるのか調べましたので、自分用に記録しておきます。

 ・今回sortしたいデータ

// {'entryNum': time}
finalGameResult = { '1': 870, '2': 855 }; 

 ・これをタイムが早い順で並び替えしたい・・・

 実現する為に、以下のサイトを参考にさせて頂きました:relaxed::tulip:
https://kinocolog.com/javascript_sort/

 同じように当てはめてみる。

let ranking = Object.keys(finalGameResult).map((k) => ({ entryNum: k, time: finalGameResult[k] }));
ranking.sort((a, b) => a.time - b.time);
console.log(ranking);
⇒ [ { entryNum: '2', time: 855 }, { entryNum: '1', time: 870 } ]

 無事に並び替えることができました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む