- 投稿日:2020-04-14T23:03:29+09:00
HTML / CSS から Nuxt.js で webアプリを開発するまでのロードマップ
はじめに
この記事では、HTML / CSS から学び、Nuxt.js で webアプリを開発するまでの過程を紹介します。
本記事は、以下のような方が対象です。同じ初学者を意識しています。
- web開発に興味がある。
- HTML / CSS を学んだが、そこからどうすれば良いか謎。不可思議。
- フレームワークとは何ぞや。フレームワークのフレームワーク?
- どこまでやれば、どういうものができるのか具体的に知りたい。
- とりあえず、web開発に興味はあるよ。
その道の方でも、「趣味で学ぼうとする人は、こういう学び方をしているんだな」と参考になるかもしれません。
筆者であるうたかたは、web開発を始めて早2ヶ月ですが、わからないことでいっぱいです。基本的に表面的な理解に終始しています。ただ「初学者でも、今あるものを使うと、こういうものができるよ」という具体例とその学習過程を紹介することで、何か少しでもお役に立てたらと思います。Qiita も利用し始めたばかりなので、何かありましたら色々とご指摘いただけると助かります。
開発中の音楽SNS「UTAKATA」の紹介・解説動画を YouTube に投稿しているので、「この記事で紹介しているもの(Vue.js・Vuetify.js・Nuxt.js・Firebase)を学ぶと、少なくともこういう webアプリを作ることができるよ」という具体例として参考にしていただければと思います。近日中にベータ版(?)を公開する予定です。
- 紹介・解説動画:UTAKATA - How to Use
最後に、本記事は各言語・フレームワークについて詳細な解説をするものではありません。「何を学べば良いかわからない」「何を学べば、何ができるかわからない」という方に、一つの指針を提供することが目的です。
少し前置きが長くなりましたが、最後までお読みいただけると嬉しいです。
ロードマップ
これまでの学習の軌跡を振り返りつつ、web開発のロードマップを紹介します。
学習の流れは、HTML / CSS → JavaScript → Vue.js & Firebase → Vuetify.js → Nuxt.js でした。
学習期間と内容は、概ね以下の通りです。
- 前半(1ヶ月):HTML / CSS / JavaScript の基本を学び、その後何を学べば良いか調べてた。もはや「web開発」とは何ぞや状態。そして今も。
- 後半(1ヶ月):Vue.js → Firebase → Vuetify.js → Nuxt.js の存在を辿り、動画を見て、公式ドキュメントを見ながらコードを書いた。
主に前半は The Net Ninja さんの動画(YouTube & Udemy)、後半は公式ドキュメントを頼りにしています。
The Net Ninja さんについては、偶然見つけただけで、特に深い理由はありません。運命の出会いでした。英語ですが、とてもわかりやすいです。このわかりやすさに慣れると、少しつらいものもあります。ストリートファイターの春麗(Chun Li)が好きみたい。マリオも出てくる。ほぼ全て無料で見ることができるのには、感謝しかないです。謝謝。
「どこまでやれば、どういうものができるのか」が想像もできなかったので、一度動画を(コードを書かないで)見るだけみて、Nuxt.js に行き着いてから、公式ドキュメントを参照しつつ、コードを書き始めました。
この記事を参考にする場合も、一度最後まで読み通して見通しをつけてから、各言語・フレームワークを学習し始めると良いと思います。知らない用語が出ても、「そういうものがあるんだね」と思って進んでください。知らないことばかりですもん。
学習項目は以下の通りです。
- HTML
- CSS
- JavaScript
- Vue.js:JavaScript のフレームワーク。
- Vuetify.js:Vue.js のデザイン担当。
- Nuxt.js:Vue.js の開発環境・機能強化担当。
- Firebase:ユーザー認証(登録・ログイン)やデータベースを管理。
1. HTML / CSS
- The Net Ninja - HTML & CSS Crash Course Tutorial
自分は「Flexbox とは何ぞや」という人間だったので、以下の動画も見ました。あとで紹介する Vuetify.js で採用されている Grid システムをそのまま理解することができます。
- The Net Ninja - CSS Flexbox Tutorial
動画が洗練されていくのを肌で感じることができるのは、複数見た人の特権です。
今回紹介している動画は有料(Udemy)2つを含みますが、それ以外はほぼ全て無料なので、ぜひ覗いてみてください。
最近では、Firebase Functions に関するシリーズ(無料)が投稿されていたようです。まだ見ていませんが、きっと参考になると思います。
2. JavaScript
- The Net Ninja - Modern JavaScript Tutorial
フルバージョンは Udemy(有料) で公開されています。動画の説明欄にクーポン付きのリンクがあるので、そちらからご利用ください。
基本的な文法(「こうやって書くよ」)・関数(「こういうことがしたい時、こういう機能があるよ」)・概念(「こういう考え方で、コードを組み立てるよ」)を一通り学ぶことができます。
学習の指針としては、動画を見て基本的な概念を理解しつつ、文法・関数(の存在)を何となく知っておきます。実際にコードを書く段階で、その関数名やしたいことで検索して、例を見ながら書きます。「検索できるようになる」こと、そして「書かれている内容を理解できるようになる」ことが大事だと思います。全てのコードを覚えておく必要はありません。未だに何でも調べてます。
この後も基本的に、動画を見て何となく理解する → ドキュメントを参照してコードを書くという流れです。
3. Vue.js & Firebase
- The Net Ninja - Build Apps with Vue & Firebase - Udemy Course
Udemy(有料)で公開されている動画の紹介動画です。動画の説明欄にクーポン付きのリンクがあるので、そちらからご利用ください。
web開発を学ぶのにかけた費用は、以上の動画2つ分(約2400円)です。
安いと思います。感謝しかないです。Vuex については、以下の動画(無料)を参考にしました。
- Vue School - Vuex for Everyone
Vue については、以下のサイトも参考になりました。Vuex についての記事を載せておきます。目を通せてはいないですが、初学者にも、とてもわかりやすい解説です。謝謝。
- REFFECT - 【vue.js】ショッピングカートを作ってVuexを理解
一応、Firebase [Firestore/Storage] セキュリティルールの具体例を以下の記事で紹介しています。とても参考になったブログ・記事についても触れているので、いつの日か覗いてみてください。喜びます。
4. Vuetify.js
- The Net Ninja - Vuetify Tutorial
使用しているコンポーネント(デザインを形作るパーツ。Buttonコンポーネントなど)や使い方が古い場合もありましたが、コメント欄で有志により全て補足されていました。
コードを書くときには公式ドキュメントの例を見ながら書くので、まずは動画で雰囲気を掴めれば良いと思います。その点で、とても参考になりました。
5. Nuxt.js
存在は Vuetify.js の公式ドキュメントで知りました。
Nuxt.js については、はじめから公式ドキュメントのガイドに沿って何となく理解していきました。一応、Vue School の動画も見たと思います。
- Vue School - Nuxt.js Fundamentals
Vue.js・Vuetify.js・Nuxt.js・Firebase は、いずれも日本語の公式ドキュメントが充実しているので、動画を見て雰囲気を掴んだら、そのまま公式ドキュメントを読むと何となく理解できます。どんなにわかりやすいサイトがあっても、参照しているのは最終的に公式ドキュメントのはずなので、それを読むことで安心感を得るのです。公式ドキュメントのわかりにくいところは、検索すれば先人が知恵を貸してくれます。
おわりに
この記事では、HTML / CSS から学び、Nuxt.js で webアプリを開発するまでの過程を紹介してきました。
「何があるかわからない」「何から手をつけていいかわからない」という方の参考になれたら幸いです。
web開発を学ぶ上で、数多くのサイト・記事を参考にさせていただいています。本記事では全て列挙することはできませんが、この場を借りてお礼申し上げます。いつもありがとう。謝謝。
趣味で NCS 等の和訳を YouTube に投稿しているので、よければそちらもご覧ください。
YouTube チャンネル:うたかた / UTAKATA少し長くなりましたが、ここまで読んでいただきありがとうございました。ではでは!
- 投稿日:2020-04-14T22:19:24+09:00
謎解き用メモ#1 パスワード
脱出ゲームの謎解きでよくある、3つの数字を入れると進めるやつ
nazotoki.html<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="nazotoki.css"> <title>謎解きWEB</title> </head> <body> <div id="app"> <input type="text" v-model="keyWord"> <button v-on:click="onclick">ボタン</button> {{message}} </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="nazotoki.js"></script> </body> </html>vue.jsnew Vue({ el: '#app', data: { message: 'hello', keyWord: '' }, methods: { onclick: function(){ if (this.keyWord === '000'){ this.message = 'good'; }else{ this.message = 'bad'; }; } } });
- 投稿日:2020-04-14T22:17:28+09:00
生JavaScriptでFizzBuzz問題とナベアツ問題を解く方法【jQuery未使用】
JavaScriptで分からないことを調べてもjQueryを使用した例ばかりしか出てこずに困った経験があったので、生のJavaScriptでナベアツ問題を解く方法についてまとめます。
FizzBuzz問題
JavaScriptを使って1から100までの数字を順番にconsole.logで出力する。
ただしその数が3で割り切れるなら"Fizz“、5で割り切れるなら"Buzz“、両方で割り切れるなら"FizzBuzz"をそれぞれ数字の代わりに出力する。FizzBuzz問題の解答コード
function fizzbuzz() { for (let i = 1; i <= 100; i++) { if(i % 3 === 0 && i % 5 === 0) { console.log("FizzBuzz"); } else if(i % 3 === 0) { console.log("Fizz"); } else if(i % 5 === 0) { console.log("Buzz"); } else { console.log(i); } } } fizzbuzz();ナベアツ問題
ナベアツ問題とは、FizzBuzz問題のように1-100までの数字で、3がつく数字と、3の倍数のときに「!」を表示させる学習のための練習問題です。
ナベアツ問題の解答コード
まずは解答となる生JavaScriptでのコードをお見せします。
なんでもそうですが、コード記述方法は他にもありますので、あくまでも一例としてご参考ください。
'use strict' const nabeatsu = () => { for (let i = 1; i <= 100; i++) { if(i % 3 === 0) { console.log(i + "!"); } else if(i.toString().match(/3/)) { console.log(i + "!"); } else { console.log(i); } } } nabeatsu();
- 投稿日:2020-04-14T21:50:43+09:00
ド素人がLINE botを公開してみた
プロトアウトスタジオという、プログラミングスクールではなく、プロトタイピングをアウトプットするというスクールに参加し始めた人の記事です。
授業にて、「heroku」というPaaSサービスにソースコードをのせて動かす体験をしました。
サーバとかOSとか、プログラムを動かすための環境づくりに必要な知識をすっ飛ばしていきなりサービスを無料で動かせる時代になっているのですね。今回の宿題は「HerokuでNode.jsの仕組みをURLを公開しチャットボットを移植しアウトプットする」です。以前の宿題「LINEbot+API」に挑戦した際のコードに少し手を加えて、「いぬ」とリクエストすると犬の画像をレスポンスするLINEbotをherokuに乗せて公開します。
'use strict'; const express = require('express'); const line = require('@line/bot-sdk'); const axios = require('axios'); const PORT = process.env.PORT || 3000; const config = { channelSecret: 'ここにはLINEbotのチャンネルシークレットを書く', channelAccessToken: 'ここにはLINEbotのチャンネルアクセストークンを書く' }; const app = express(); let requetText=''; app.post('/webhook', line.middleware(config), (req, res) => { requetText=req.body.events[0].message.text; Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)); }); const client = new line.Client(config); function handleEvent(event) { if (event.type !== 'message' || event.message.type !== 'text') { return Promise.resolve(null); } let mes = 'ちょっとまってね'; // 待ってねってメッセージだけ先に処理 getQiitaTag(event.source.userId , event.message.text); // スクレイピング処理が終わったらプッシュメッセージ return client.replyMessage(event.replyToken, { type: 'text', text: mes }); } const getQiitaTag = async (userId,tag) => { let mes = ''; try { if(requetText==="いぬ"){ const res = await axios.get('https://random.dog/woof.json'); const item = res.data.url; mes = item; }else if(requetText==="しばいぬ"){ const res = await axios.get('http://shibe.online/api/shibes?count=1&urls=true&httpsUrls=true'); const item = res.data[0]; mes = item; }else{ mes = "いぬしかわかりません"; } } catch (error) { // 該当しないものは404でエラーになる const { status, statusText } = error.response; console.log(`Error! HTTP Status: ${status} ${statusText}`); if( status == 404 ){ mes = 'Qiitaのタグ「' + tag + '」の記事はありませんでした'; } else { mes = `Error! HTTP Status: ${status} ${statusText}`; } } await client.pushMessage(userId, { type: 'text', text: mes, }); } app.listen(PORT); console.log(`Server running at ${PORT}`);リクエストが「しばいぬ」だった場合には柴犬APIを呼んで柴犬画像をレスポンスするif文も入れてみました。
今回授業にて、ExpressにおいてHTTPSのpostリクエストを投げる際の処理を学んだことから、LINE上で何か打ち込まれた際それがwebhookに対するpost通信であるため、
app.post('/webhook', line.middleware(config), (req, res) => { requetText=req.body.events[0].message.text; Promise .all(req.body.events.map(handleEvent)) .then((result) => res.json(result)); });という関数が実行されるのだと気づきました。
一方で「Promise~」以降のコードが何を表しているのかサッパリなので、Promiseについて調べてみます。
- 投稿日:2020-04-14T20:35:17+09:00
元に戻せるほうのカリー化入門
想定読者
高階関数、カリー化、部分適用、クロージャ
などの言葉を目にするたび不安になってしまい
それぞれの意味を何度も調べてしまう人へ1。カリー化の反対にあたる逆カリー化に焦点を当て、
もう忘れないように理解をまとめておきたい。高階関数
引数もしくは戻値が関数であるとき
その関数を高階関数と呼ぶらしい。高階関数const apply = f => x => f(x)関数
apply
は1引数関数f
を引数に取って
関数x => f(x)
を返すので高階関数と言える。関数の関数という構造は何となく神秘的で
特別な名前を付けたくなる気持ちは分かる。しかし、本質的に重要なのは
数値などと同じように関数を扱えること2
なのではないかと個人的には思う。
引数もしくは戻値が数値であるとき
その関数を数値関数と呼んでみよう。数値関数const succ = n => n + 1関数
succ
は数値n
を引数に取って
数値n + 1
を返すので数値関数と言える。それはそうであると感じるのではないだろうか。
高階関数もその程度の理解で良いと思われる。カリー化と逆カリー化
カリー化と逆カリー化は
変換と逆変換の関係に相当する。変換してから逆変換すると元に戻る3。
カリー化とは元に戻せる変換である。変換
カリー化とは次のような変換のことだ。
カリー化const curry = f => x => y => f(x, y)高階関数
curry
は2引数関数f
を
高階関数x => y => f(x, y)
に変換する。例として、次の2引数関数
add
を考える。足し算const add = (x, y) => x + y当然ではあるが
add(2,3)
$=$5
となる。
カリー化された高階関数curry(add)
は
同様にcurry(add)(2)(3)
$=$5
である。逆変換
逆カリー化とは次のような逆変換のことだ。
逆カリー化const uncurry = g => (x, y) => g(x)(y)高階関数
uncurry
は高階関数g
を
2引数関数(x, y) => g(x)(y)
に逆変換する。例として、次の高階関数
add
を考える。足し算const add = x => y => x + y当然ではあるが
add(2)(3)
$=$5
となる。
逆カリー化された2引数関数uncurry(add)
は
同様にuncurry(add)(2, 3)
$=$5
である。変換と逆変換
再び例として、次の2引数関数
add
を考える。足し算const add = (x, y) => x + y変換
curry
と逆変換uncurry
に対して
add(2, 3)
$=$uncurry(curry(add))(2, 3)
$=$5
が成り立つことを確認できるだろう。これは任意の引数
(x, y)
に対して成り立ち、
add
$=$uncurry(curry(add))
である4。
任意の2引数関数
f
に対して、
カリー化された関数curry(f)
は
逆変換uncurry
で元の関数f
に戻せる。2引数関数const add = (x, y) => x + y const mul = (x, y) => x * y const constant = (x, _) => x変換により
f
とcurry(f)
は1対1対応する。部分適用
部分適用とは次のような変換のことだ。
部分適用const papply = (f, x) => y => f(x, y)高階関数
papply
は2引数関数f
と引数x
の
組(f, x)
を1引数関数y => f(x, y)
に変換する。例として、次の2引数関数
mul
とconstant
を考えよう。掛け算と定数const mul = (x, y) => x * y const constant = (x, _) => x第1引数に
0
を部分適用すれば以下となる。部分適用const mul0 = papply(mul, 0) const constant0 = papply(constant, 0)この関数
mul0
は全てを0
にする。
[1, 2, 3].map(mul0)
$=$[0, 0, 0]
また関数
constant0
も全てを0
にする。
[1, 2, 3].map(constant0)
$=$[0, 0, 0]
上記の関数
mul0
とconstant0
は
変換curry
を用いて次のようにも書ける。部分適用const mul0 = curry(mul)(0) const constant0 = curry(constant)(0)変換
papply
とcurry
は、確かに似て見えて、
同じことをしていてるように感じるかもしれない。ここで注目すべきは
mul0
やconstant0
を
元の(mul, 0)
や(constant, 0)
に戻せるかどうかだ。
関数
mul0
とconstant0
は全てを0
にする。
つまりmul0
$=$constant0
であることに注意しよう。例えば部分適用された関数
mul0
の逆変換を試みても、
(mul, 0)
と(constant, 0)
のどちらに移せば良いか
分からないため、元の(mul, 0)
に戻せない。2引数関数const add = (x, y) => x + y const mul = (x, y) => x * y const constant = (x, _) => x変換と逆変換で見たような1対1対応こそが
元に戻せるという性質をあらわしている。クロージャ
環境とラムダ式(アロー関数)の両者を
合わせたものをクロージャと呼ぶらしい5。クロージャ{ let a = 2 let b = 1 const closure = x => a*x + b }関数
closure
の中では宣言されておらず
外の環境で宣言されているような変数a
とb
を
関数の宣言時に閉じ込めるイメージだろうか。変数
a
とb
をグローバル変数だと思えば、
次のような関数もクロージャと考えられるだろう。クロージャconst closure = x => a*x + b変数の数はいくつでも良いと思うので、
たまたま0個な次のような関数もクロージャだろう。クロージャconst closure = x => 2*x + 1クロージャと関数を同一視してしまっても
実用上はなんの問題もないような気がする。
狭義には次のような高階関数
enClosure
の戻値
すなわち関数closure
をクロージャと呼ぶだろう。エンクロージャとクロージャconst enClosure = (a, b) => { const closure = x => a*x + b return closure }これを次のように書けば、単なる高階関数に見える。
エンクロージャとクロージャconst enClosure = (a, b) => x => a*x + bやはりクロージャと関数を同一視しても良さそうだ。
クロージャの例としてよく見るカウンターを考えよう。
カウンターconst newCounter = count => { const counter = del => { count = count + del return count } return counter }これまでと異なり変数
count
は可変だが、
高階関数newCounter
の戻値counter
を
クロージャと呼んでいるに過ぎないだろう。少し苦しいが次のように書けば、単なる高階関数だ。
カウンターconst newCounter = count => del => count = count + delクロージャとは関数だと理解しておくことにする。
そのほうが覚えるべきことが減って簡単なはずだ。まとめ
カリー化と部分適用の違いについては
分かりやすい解説がたくさんあるけれど、
特に1対1対応を重視したような解説は
見つけることができなかったので書いてみた。タイトルに関しては次記事のリスペクトです。
「食べられないほうのカリー化入門」(2013-07-22)食べ物のカレーを元の材料には戻せないので、
元に戻せるかどうかでもカレー化とカリー化の
両者を区別することが可能だと思いました。
- 投稿日:2020-04-14T20:28:22+09:00
Webを使った新人研修 ~SQL基礎編・SELECTクエリでデータ検索~
Webを使った新人研修 ~SQL基礎編~
SELECTクエリでデータ検索
細かい説明をしていては果てしないので、「習うより慣れろ」の精神で
まずは、「実践」してみましょう。実践する
Ideoneをブラウザで開いてみましょう。
右下の緑色ボタン「Run」を押してみましょう。
create table tbl(str varchar(20)); insert into tbl values('Hello world!'); select * from tbl;これをforkしてみても良いです。
解説
例題を示して記憶の定着を図ってみます。
例題
1.〜
~本日はここまで
- 投稿日:2020-04-14T19:16:50+09:00
[超感覚C3講座] Webで掲示板を作ろう
新入生のみなさん.
こんにちは.
rkun( @rkunkunr )と申します.クルマとバイクとアニメが好きなキモオタです.よろしくおねがいいたします.あずにゃんぺろぺろ.
突然ですが
みなさん.2ちゃんねるって知ってますか?
掲示板ですね.まあ最近私もあんまり見ることないです.Twitterでいいよねってなります.
Twitterは「会員制交流サイト」と言われる通り,アカウントを作ってそのアカウントから投稿するというプロセスを取りますが,
掲示板はその都度名前を決め(というか決めずにランダム生成させることもある),ただただ投稿するというシンプルな構造をしていますね.Twitterみたいなアカウント制のWebアプリを作るのは手間がかかりますが,掲示板は比較的簡単に作ることができます.
というわけで,今回は皆さんに
JavaScriptを使って
C3超感覚掲示板の一部を作ってもらいたいと思います.JavaScriptのおべんつよ
JavaScriptとはプログラミング言語です.Web上で動かせるやつで,阿部寛のホームページみたいな骨董品じゃなければ大体どんなサイトでも使われています.
とりあえずちょっと簡単に書き方を説明したいと思います.
コードの中の行頭が
//
のやつはコメントというやつで,実行するときには無視されるやつです!文字や数字の表現の仕方
// 整数 123 // 小数 123.456 // 文字列 "今日も一日,がんばるぞい!!"変数の宣言・代入
変数とは,値を入れる箱です.
// 変数の宣言 var text; // 変数への値の代入 text = "hogehoge"; // 宣言と代入を同時に var text = "hogehoge"if文
if文は,条件分岐をするときの書き方です.
var age = 18; if(age >= 20) { // 20歳以上 console.log("飲酒OK!!"); }else{ // 20歳未満 console.log("飲酒NG!!"); } // Console: 飲酒NG!!この
today >= 20
は,「todayが20以上」という意味です.関数
関数とは,引数を受け取り,返り値を返す(返さなくてもいいよ)処理の塊である.
// 関数を作る function add(a, b) { console.log("Called!!"); return a + b; } // 関数を利用する var result = add(4, 5); console.log(result); // Console: 9配列
配列とは,変数がいっぱい列になって入っているもの
// 作り方(a, b, cを入れておく場合) var array = ["a", "b", "c"]; // 作り方(何も入れておかない場合) var emptyArray = []; // (注意!!) 最初は0から始まる array[0]; > "a" array[1]; > "b" array[2]; > "c"配列のforEach()
JavaScriptの配列には面白い機能がある.
var members = ["唯", "律", "澪", "紬", "梓"]; keionClub.forEach(function(m) { console.log(m + "ちゃんカワイイ!!"); }); // Console: // 唯ちゃんカワイイ!! // 律ちゃんカワイイ!! // 澪ちゃんカワイイ!! // 紬ちゃんカワイイ!! // 梓ちゃんカワイイ!!DOM
さっき,JavaScriptはWebサイトに動きをつけるものだといいましたね.あれは嘘ではありません.
HTMLの中にこんな要素があったとします.<div id="title">CompositeComputerClub</div>これをJavaScript上で操作するために,この要素と対応したJavaScriptのオブジェクトが用意されています.
var titleElem = document.getElementById("title")で取得ができます.
このオブジェクトにはたくさんの変数と関数が入っており,例えば
titleElem.innerHTML = "CompositeConstructionClub"とすることでHTMLの表示を変更できます.部室とか自作してそうですね.
JQuery(時間余ったら話す)
ボタンを押したら入力しておいたメッセージを出すコードをJavaScriptで書いてみましょう.
HTML
<input type="text" id="msg_text"></input> <button id="msg_button">Message</button>JavaScript
document.getElementById("msg_button").addEventListener(function(e) { alert(document.getElementById("msg_text").value); });この
getElementById
とかaddEventListener
が長くて書く気が失せますよね.そこでどこかのえらいひとがJQueryというものを作りました.これを使うと,
$("#msg_button").click(function(e) { alert($("#msg_text").val()); });となります.短いですね.
ほかにもJQueryを使うととても便利なので,掲示板にも採用しています.C3超感覚掲示板
作り方
あらかた作っておいたので,皆さんには一部を考えて実装してもらいます.
CodePenについて
今回はCodePenというサービスを利用します.
https://codepen.io
ここのアカウントを作っておいてください.(Forkせずにそのまま編集することも可能ですが,間違えてブラウザのタブを削除したときになにもかもどうでもよくなるので,ログインしてやることをおすすめします!!)
[超感覚Discordを参照]
これで,未完成のC3超感覚掲示板のコピーが自分のアカウントに作られます.
Consoleを活用しよう
Codepenの左下にConsoleというボタンがあるので,クリックしてみましょう!!
こういうのが出ましたか?
これは,Consoleというやつです.
ここにJavaScriptで
console.log("メッセージ”)
したものが表示されます.開発のときにとても便利なので表示した状態で作っていきましょう!!
実装
実際に実装していきましょう!!!
右側の「JS」画面を使っていきます.投稿を表示する機能(30行目)
ここで実装してほしい機能
var postBox = generatePostBox(username, created_at, text)
を呼び出して投稿Boxを新しくつくり postBox 変数へ代入する.prependPostBox(postBox)
を呼んで- 挿入後,postBox.hide().fadeIn() をつかってフェードインさせる.
投稿を送信する機能(57行目)
ここで実装してほしい機能
- 変数 username : 投稿ユーザー名
- 変数 text : 投稿内容
もし内容が""であれば,(if文)
- showEmptyAlert() を行う.
内容が空でなければ送信してOKなので,(else)
- db.post(username, text)で送信する.
- makePostFormEmpty()でフォームを空にする. ```
- 投稿日:2020-04-14T18:27:31+09:00
画像ファイルのアップロード時に複数のプレビュー画像を表示する【Vue.js】
ファイルアップロード時に複数の画像プレビューを表示する
題名の通りですが、今回は備忘録として、
画像アップロードを行う際に複数の画像プレビューを
Vue.jsを利用して表示する方法について書いていこうと思います。FileAPI
FIleAPIについては以下のドキュメントを参照してください。
https://developer.mozilla.org/ja/docs/Web/API/File実装例
<template> <div> <input @change="inputFileList($event)" multiple="multiple" accept="image/*" > <div v-for="(uploadFile, index) in updatedFileList" :key="index" > <p>ファイル名: {{ uploadFile.fileName }}</p> <p>ファイルタイプ: {{ uploadFile.fileType }}</p> <p>サイズ: {{ uploadFile.size.width }}×{{ uploadFile.size.height }}</p> <img :src="uploadFile.url"> </div> </div> </template> <script> export default { data: { uploadFileList: [] } computed: { // this.uploadFileListに変更が加わった際に検知するためです uploadFileList() { return this.uploadFileList } } methods: { async inputFileList(event) => { // event.target.filesはファイルデータが格納されたリストです const fileList = event.target.files if (fileList === 0) { return } // FileAPIは、APIなので複数ファイルを扱う時は、 // for文の中でawaitする必要があります for (file of fileList) { // ファイルデータ用のオブジェクトを用意します const fileData = { name: '', type: '', size: { width: 0, height: 0 }, url: '' } const image = new Image() const fileReader = new FileReader() // 即時関数をawaitすることで処理の完了までループが終わりません await (async () => { fileReader.onload = async () => { image.src = fileReader.result // ファイルURL取得 fileData.url = fileReader.result // 即時関数をawaitすることでfileData.sizeのデータを担保します await (() => { image.onload = () => { // ファイルサイズ取得 fileData.size = { width: image.naturalWidth, height: image.naturalHeight } } })() } // FileAPIの起動 fileReader.readAsDataURL(file) })() // 取得したファイルデータのオブジェクトをuploadFileListにpushします this.uploadFileList.push(fileData) } } } }おわりに
間違いや質問などありましたらコメントお願いします。
- 投稿日:2020-04-14T18:04:11+09:00
jQueryとeach()とreturn false
なんてないことですけど備忘録。
$('hoge').each()
なんてので総当たりする。
ifを使って判定して条件にマッチしたときに処理を止めるとき$('.hoge').each(function(){ if(!$(this).hasClass('active')){ $('.fuga').removeClass('active'); return false; } else { $('.fuga').addClass('active'); } });と、「return false;」を入れる。
もしページ内の.hogeに.activeが無ければそこで処理を止める。
ページ内の.hogeに全部.activeがあればelseを通ります。忘れていたのでここに書いとく。
- 投稿日:2020-04-14T16:52:23+09:00
スクロール位置でクラスを付与してくれるDelighters
スクロール位置によって、表示要素に動きを付けたい際利用できるライブラリです。
散々流行った今更のパララックスかもしれませんが、まだちょっと需要はありそうです。この演出をGoogle先生に聞いてみたところ、jQueryを利用したライブラリばっかりがヒットしてしまいました
Delightersはピュアなjsで実装できる貴重なライブラリだと思います。Delighters Good Points
◉ 軽量
◉ レスポンシブ対応 - タブレット、スマホもどんとこい!!
◉ スクロール位置で指定した要素にクラスが付与されるだけ。導入がシンプルで簡単。
◉ jsによる動きの定義がない。使い慣れたCSSを利用してこちらで細かな設定が自由に定義できて嬉しい。Delighters 使い方
ざっくりとした使い方です。
※慣れてる方は飛ばして下さい。Delighters公式サイトのUsageをみていただくのが一番です。scriptファイルを読み込む
公式のGitHubから落としてこれます。<script type="text/javascript" src="delighters.js">動かしたい要素のhtmlに
data-delighter
という属性を追加する<div class="xxxクラス名は自由" data-delighter>自分で自由にスタイルシートで動きをつける
センスが出る腕の見せどころw ダサくなりたくない…
アニメーションの設定をします。ここでは公式のクラスを引用してます。/* delighters.jsが読み込まれると、 [data-delighter] 属性を持っている要素それぞれに .delighter が付与されます。*/ .foo.delighter { transition: all .3s ease-out; transform: translateX(-100%); opacity: 0; } /* スクロールしてターゲットが画面上部(初期設定)から75%(初期設定)の位置にきた際 .started が設定されます。*/ .foo.delighter.started { transform: none; opacity: 1; } /* スクロールしてターゲットが画面下部(初期設定)から75%(初期設定)の位置にきた際 .ended が設定されます。 */ .foo.delighter.started.ended { border: solid red 10px; }Delightersカスタマイズ
属性名や、スクロール位置で設定されるクラス名、上部もしくは下部からどれくらいの位置にするかなど変更できるそうです。
options = { attribute: 'data-delighter', classNames: ['delighter', 'started', 'ended'], start: 0.75, // default start threshold end: 0.75, // default end threshold autoInit: true // initialize when DOMContentLoaded }
- 投稿日:2020-04-14T15:00:13+09:00
Nuxt.jsで初めて作成したポートフォリオをGitHub Pagesで公開しました
この記事は、「Nuxt.js ってなんですか?」な状態の人間が、やりたいことを盛り込んで作成したポートフォリオについて書いたものです。
作成したポートフォリオ
https://tayuta.github.io/portfolio/
GitHub Pages に公開しています。https://github.com/tayuta/portfolio
ソースコードです。作成に至った動機
ポートフォリオを作成することになったのは、社内でポートフォリオ部(正式名称:そうだポトフを作ろう! 略称:ポトフ)が発足されたことがきっかけです。
もともと業務では、JavaScriptやHTML、CSSなど、フロント系はほとんど触れあったことがなかったので、勉強になるかと思い、入部しました。プロジェクトの作成
ポートフォリオの研究
ポートフォリオが一体どういったものか知らなかったので、ほかの人が作成しているものを片っ端から見あさりました。
また、ポートフォリオの作成だけでなく、自分でレイアウトを考えたりすることも初めてだったので、デザイン手法などについても学習しました。【学習に利用した記事】
全部知ってる?主要なWebデザイン手法のまとめポートフォリオ概要決め
つぎに、どのようなポートフォリオを作るか、なんとなく決めました。
- SPA
- Nuxt.jsで作成する
- テーマは、海の中(最終的には全く違うものができました。←)
- 以下のコンテンツを縦に並べる
- プロフィール
- スキル
- これまで作ったもの(ほぼありませんが...)
- 愛犬について(あまりにコンテンツが少なかったので後から追加)
Nuxt.js プロジェクトの作成
以下の記事を参考に、Nuxt.js プロジェクトを作成しました。
Nuxt.js を導入しよう設定内容が少し変わっていたので、こちらの記事も参考になります。
Nuxt.js の導入 -2.8.1ver-画面が表示できたので、あとは自分がやりたいことを好きなように盛り込みました。
盛り込んだこと
背景に泡をぷかぷかさせる
当初のテーマは海だったので、背景に泡をぷかぷかさせたいと思いました。
導入方法
bubbly-bg.js をポートフォリオに組み込みます。
GitHub : https://github.com/tipsy/bubbly-bg※Nuxt.js の場合、JavaScriptファイルをどこに置いて、どこで読み込めばいいのか分からなかったので有識者に質問したところ、ファイルの内容を mounted にぶち込むように教わったので、そうしました。
※mounted が何なのかはもちろん分からなかったので、以下の記事を読んでなんとなく理解しました。
Vueのライフサイクルを完全に理解した想定通りに動くことを確認した後、?ソースなので、整理をします。
index.vue<template> <section class="container"> <canvas id="bubbly"></canvas> <div class="body"> <!-- 省略 --> </div> </section> </template> <script> export default { mounted() { const canvas = document.getElementById('bubbly') const width = (canvas.width = window.innerWidth) const height = (canvas.height = window.innerHeight) const context = canvas.getContext('2d') context.shadowColor = '#c9ffbf' context.shadowBlur = 4 const gradient = this.setGradient(context, width, height) const bubbles = this.setBubbles(width, height) const draw = () => { requestAnimationFrame(draw) this.anim(context, gradient, bubbles, width, height) } draw() }, methods: { // メソッド内省略 } } </script> <style lang="scss"> #bubbly { position: fixed; z-index: -5; top: 0; left: 0; min-width: 100vw; min-height: 100vh; } </style>以下の記事を参考にしました。
背景のグラデーションや、泡の数・動く速度を変更したい場合も、こちらが参考になります。
【JavaScript】美しい泡が漂う[Beautiful bubbly backgrounds]の使い方背景を斜めにする
背景が斜めだとおしゃれかと思い、背景を斜めにしました。
導入方法
背景を斜めにするためには、要素全体を回転させ、その内側の要素を反対に回転させます。
ただ要素を回転させると、左右に空白ができてしまうため、横幅を大きめに指定します。sample.vue<template> <section class="container"> <div class="contents"> <div class="inner"> コンテンツ </div> </div> </section> </template> <style scoped lang="scss"> .contents { -webkit-transform: rotate(10deg) translate3d(0, 0, 0); transform: rotate(10deg) translate3d(0, 0, 0); background-color: #ffdadf; width: 200%; margin-left: -180px; .inner { -webkit-transform: rotate(-10deg) translate3d(0, 0, 0); transform: rotate(-10deg) translate3d(0, 0, 0); max-width: 50%; margin-left: 157px; } } </style>また、このままでは、背景が横にはみ出てしまい、横スクロールが発生してしまいます。
そのため、はみ出た部分を非表示にする必要があるので、親要素である container に「overflow-x: hidden;」を指定します。sample.vue<style scoped lang="scss"> .container { overflow-x: hidden; } </style>以下の記事を参考にしました。
斜めの背景を作るためのCSSは「回転させて元に戻す」で書く!スクロールにより、要素をふわっと表示させる
要素が画面に表示されてからアニメーションを発火させるために、カスタムスクロールディレクティブを作成しました。
導入方法
まずは、plugins フォルダ内に以下のファイルを作成します。
scroll.jsimport Vue from 'vue' Vue.directive('scroll', { inserted: function(el, binding) { const f = function(evt) { if (binding.value(evt, el)) { window.removeEventListener('scroll', f) } } window.addEventListener('scroll', f) } })nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/scroll'] }mixin.js に handleScroll メソッドを定義します。
mixin.jsexport default { methods: { handleScroll: (evt, el) => { const top = el.getBoundingClientRect().top if (window.scrollY > top + window.pageYOffset - 600) { el.classList.add('isView') return true } return false } } }ふわっと表示させたい要素に、v-scroll ディレクティブを追加し、アニメーションを設定します。
アニメーションを変更することで、ふわっと表示以外にも、横から表示・回転しながら表示などもできるかと思います。sample.vue<template> <div v-scroll="handleScroll" class="fade-in">ふわっと表示</div> </template> <script> import mixin from './mixin' export default { mixins: [mixin] } </script> <style scoped lang="scss"> .fade-in { opacity: 0; } .fade-in.isView { animation-name: fade-in; animation-duration: 2s; animation-timing-function: ease-out; animation-delay: 0.2s; animation-iteration-count: 1; animation-direction: normal; animation-fill-mode: both; } @keyframes fade-in { 0% { opacity: 0; transform: translate3d(0, 20px, 0); } 100% { opacity: 1; transform: translate3d(0, 0, 0); } } </style>以下の記事を参考にしました。
Nuxt.js でスクロールでふわっと要素が出現するやつを「カスタムディレクティブ」で実装するまた、handleScroll メソッドに関しては、sample.vue に記述しても問題ありませんが、私は複数コンポーネントで利用する予定だったので、mixinに記述しました。
mixin については、以下が参考になります。
ミックスインスクロールしながら画面遷移を行う
メニューのリンクをクリックした際に、スクロールしながら指定場所を表示させたいと思い、「vue-scrollto」を導入しました。
導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm i vue-scrolltoその後、plugins フォルダ内に以下のファイルを作成します。
vue-scrollto.jsimport Vue from 'vue' import VueScrollTo from 'vue-scrollto' Vue.use(VueScrollTo, { duration: 700, // スクロール継続時間 easing: [0, 0, 0.1, 1], // 速度の緩急 offset: -70 // 遷移後の位置調整 })nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-scrollto'] }あとは、以下のように、v-scroll-to に遷移先の要素の id を指定することで画面内遷移が可能です。
sample.vue<template> <nuxt-link v-scroll-to="'#bottom'" to>Scroll to bottom</nuxt-link> <div id="bottom">bottom</div> </template>以下の記事を参考にしました。
スクロール継続時間などのオプションについても、こちらが参考になります。
「vue-scrollto」を使ってイージングスクロールを実装する写真をスライダーで表示
コンテンツが少なかったので、愛犬の写真を表示することにしました。
複数の写真を見てもらうため、自動で写真が切り替わるようにしたかったので、実現することができそうな「vue-awesome-swiper」を導入しました。導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm install vue-awesome-swiper --saveその後、plugins フォルダ内に以下のファイルを作成します。
vue-awesome-swiper.jsimport Vue from 'vue' import VueAwesomeSwiper from 'vue-awesome-swiper' import 'swiper/css/swiper.css' Vue.use(VueAwesomeSwiper)nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-awesome-swiper'] }以下のように、スライダーを組み込みます。
sample.vue<template> <swiper :options="swiperOption" ref="mySwiper1"> <swiper-slide v-for="(item, index) in items" :key="index"> <img :src="item.img" alt="..." /> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> <div class="swiper-button-prev" slot="button-prev"></div> <div class="swiper-button-next" slot="button-next"></div> </swiper> </template> <script> export default { data: function() { return { items: [ { img: require('~/static/img_1.jpg') }, { img: require('~/static/img_2.jpg') } ], swiperOption: { autoplay: { delay: 2500, disableOnInteraction: false }, pagination: { el: '.swiper-pagination', clickable: true }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' } } } } } </script> <style scoped lang="scss"> .swiper-container { height: 300px; width: 100%; } .swiper-slide { text-align: center; font-size: 38px; font-weight: 700; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; border-left:1px solid #fff; } </style>以下の記事を参考にしました。
「swiperOption」のその他の設定についても、こちらが参考になります。
モバイルタッチスライダー「vue-awesome-swiper」の使い方注意点
フェードアニメーションと複数カラムスライドは同時に設定できませんでした。
以下の記述の場合、「slidesPerView: 3」の設定が無視されます。sample.vueswiperOption: { effect: 'fade', slidesPerView: 3, ... }パララックス
パララックスを利用しているサイトかっこいい!と思い導入しましたが、どこに使えばいいか分からず、ひっそりと利用しています。
私が今回導入したプラグインは、「vue-prlx」ですが、その他に、「vue-parallax-js」などがあるようです。以下が参考になるかと思います。
nuxt.jsでパララックスをするならvue-parallax-jsがお手軽。Cool!細かい挙動の設定が「vue-prlx」のほうが分かりやすかったので、今回は「vue-prlx」を選択しましたが、気が向いたら「vue-parallax-js」も使ってみようかな、と思っています。(
思っているだけです。)導入方法
まずは、プロジェクトディレクトリで下記のコマンドを実行します。
npm i vue-prlxその後、plugins フォルダ内に以下のファイルを作成します。
vue-prlx.jsimport Vue from 'vue' import VuePrlx from 'vue-prlx' Vue.use(VuePrlx)nuxt.config.js の plugins キー内にファイルパスを追加します。
nuxt.config.jsexport default { plugins: ['~/plugins/vue-prlx'] }あとは、パララックス効果を追加したい要素に対して、v-prlx ディレクティブを追加するだけです。
sample.vue<template> <img src="sample.png" alt="" v-prlx> </template>以下の記事を参考にしました。
細かい挙動の設定についても、こちらを参照してください。
vue-prlxを使ってさくっとパララックス体験をしてみるファビコンの作成
私は、「X-Icon Editor」を利用して、作成しました。
簡単なデザインだったので、問題なく作成できました。GitHub Pagesに公開
ポートフォリオなので、ゆくゆくは人目に触れるようにしたいと思い、ひとまず手軽にできると聞いた GitHub Pages に公開することにしました。
公開方法
まず、nuxt.config.js の router の base と favicon のパスにリポジトリ名を記述。
※ router の base を編集することにより、localhostのパスが「localhost:3000/リポジトリ名」になりますnuxt.config.jsexport default { router: { base: '/リポジトリ名/' }, head: { title: pkg.name, meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { hid: 'description', name: 'description', content: pkg.description } ], link: [ { rel: 'icon', type: 'image/x-icon', href: '/リポジトリ名/favicon.ico' } ] }次に、ローカルにgh-pagesブランチを作成し、gitignoreからビルド先フォルダを外します。
# Nuxt generate # distビルドコマンドを実行します。
npm run generatedist フォルダが作成されるので、ローカルのgh-pagesブランチにコミットします。(masterブランチにコミットする必要はありません。)
最後に、以下のコマンドを実行し、dist フォルダのみを gh-pages ブランチに切り離してリポジトリに push します。git subtree push --prefix dist/ origin gh-pagesうまく公開できている場合、GitHub の Setting から公開されたページを確認することができます。
以下の記事を参考にしました。
Nuxt.jsで作ったWebサイトをささっとGithub Pagesに公開する悩んだこと・大変だったこと
無名関数内で this を利用する
無名関数内で、this を利用する際に、以下のように記述していました。
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const a = function() { this.count++ } a() } } } </script>この記述では、Vueインスタンスが参照できないため、「Cannot read property 'count' of undefined」というエラーが発生します。
対応方法① this を別の変数に代入しておく
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const me = this const a = function() { me.count++ } a() } } } </script>余分に me という変数が出現するため、個人的にはあまり好きではないと思いました。
対応方法② アロー関数を利用する
sample.vue<script> export default { data: function() { return { count: 0, } }, methods() { increment: function() { const a = () => { this.count++ } a() } } } </script>私が実際に採用した方法です。
余分に変数が増えない分、すっきりしました。モバイルルータで画像が表示されない
流行りのコロナウイルスによりテレワークになった際に、会社から支給されたモバイルルータが少し遅めだったこともあり、画像が表示されないという事件が発生しました。
原因は、画像サイズが大きすぎたことでした。対応方法① png ファイルを jpeg ファイルに変更
なんとなく png ファイルにそろえていましたが、容量的には jpeg ファイルの方が良いということを初めて知りました。
今後は、透過画像以外は jpeg ファイル、と心に刻みました。対応方法② 画像サイズを縮小
そもそも、高画質である必要がない画像ばかりだったので、画像サイズを縮小しました。
斜めレイアウトの調整
marginの調整などの際、斜めに移動するため、思い通りにレイアウトできるまでに時間がかかりました。
数学が得意であれば、計算でもう少しスムーズにできたのかもしれないです...これからやりたいこと
- Netlifyで正式にリリース
- それっぽいドメインにできるそうなので、気が向いたら変えたい。
- Lighthouseを使ってチューニング
- 画像サイズ以外にも改善できるところを改善したい。
- 投稿日:2020-04-14T11:26:42+09:00
cookieを再設定するとexpiresの値が削除される
cookie操作時に気づいたので共有します。
以下のようなexpires(有効期限)の設定されたcookie情報があった場合に
key=valA; expires=2020-04-15T14:00:00.000Z;
以下のように値だけ入れ直したところ
document.cookie = 'key=valB;'
予想では以下のように値だけ変更される想定でしたが、
key=valB; expires=2020-04-15T14:00:00.000Z;
実際には以下のように値は変更されるが、
同時に有効期限の値が失われてしまった
key=valB;
なので、有効期限を設定されていた場合は、
以下のように値だけの更新であっても、有効期限も設定し直す必要があることが分かった
document.cookie = key=valB; expires=2020-04-15T14:00:00.000Z;
以上。
あまり、この事に触れた記事を見かけたことがなかったので投稿してみました。
ご参考まで!
- 投稿日:2020-04-14T09:52:47+09:00
Yarnでローカルのパッケージをaddする方法
この投稿では
yarn
コマンドで、ローカルのパッケージをインストールする方法を紹介します。通常
yarn add
はnpmjs.comで公開されたパッケージをダウンロードしてきてインストールしますが、ここで説明するのはローカルにのみ存在する自作のライブラリをadd
する方法です。(
npm
で同様のことをする方法は、「npmでローカルのパッケージをinstallする方法」をご覧ください)やりかた
ローカルのパッケージをインストールには、単純にインストールしたいパッケージのファイルパスを
yarn add
の引数にします:yarn add インストールしたいパッケージのパスnode_modulesにインストールされるパッケージをシンボリックリンクにしたい場合:
yarn add link:インストールしたいパッケージのパス
ローカルパッケージをインストールする具体例
少し具体例をもとに説明します。
以下の図のように、
myapp
パッケージとmylib
パッケージがあり、myapp
からmylib
を使いたい例を見てみましょう。
mylib
のindex.js
では、helloWorld
変数が提供されていて、myapp
のmain.js
でそれを使いたいとします。このとき、
myapp
パッケージにてyarn add ../mylib
を実行するとこれが実現します:$ yarn add ../mylib yarn add v1.22.4 info No lockfile found. [1/4] ? Resolving packages... [2/4] ? Fetching packages... [3/4] ? Linking dependencies... [4/4] ? Building fresh packages... success Saved lockfile. success Saved 1 new dependency. info Direct dependencies └─ mylib@1.0.0 info All dependencies └─ mylib@1.0.0 ✨ Done in 0.08s.インストールされると、
package.json
にmylib
への依存設定が追加されます:package.json{ "name": "myapp", "version": "1.0.0", "license": "MIT", "dependencies": { "mylib": "../mylib" } }
main.js
を実行してみます:$ node main.js Hello World!しっかりと
mylib
の変数が使われているが分かります。ちなみに、インストールされた
myapp/node_modules/mylib
はmylib
をごっそりコピーしたものになります。../../mylib
へのシンボリックリンクではないので注意です。シンボリックリンクにしたい場合はファイルパスの頭に
link:
を付けます:yarn add link:../mylib
最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします→Twitter@suin
- 投稿日:2020-04-14T09:41:16+09:00
npmでローカルのパッケージをinstallする方法
この投稿では
npm
コマンドで、ローカルのパッケージをインストールする方法を紹介します。通常
npm intall
はnpmjs.comで公開されたパッケージをダウンロードしてきてインストールしますが、ここで説明するのはローカルにのみ存在する自作のライブラリをinstall
する方法です。(
yarn
で同様のことをする方法は、「Yarnでローカルのパッケージをaddする方法」をご覧ください)やりかた
ローカルのパッケージをインストールには、単純にインストールしたいパッケージのファイルパスを
npm intall
の引数にします:npm install インストールしたいパッケージのパス
ローカルパッケージをインストールする具体例
少し具体例をもとに説明します。
以下の図のように、
myapp
パッケージとmylib
パッケージがあり、myapp
からmylib
を使いたい例を見てみましょう。
mylib
のindex.js
では、helloWorld
変数が提供されていて、myapp
のmain.js
でそれを使いたいとします。このとき、
myapp
パッケージにてnpm install ../mylib
を実行するとこれが実現します:$ npm install ../mylib + mylib@1.0.0 added 1 package and audited 1 package in 0.74s found 0 vulnerabilitiesインストールされると、
package.json
にmylib
への依存設定が追加されます:package.json{ "name": "myapp", "version": "1.0.0", "license": "MIT", "dependencies": { "mylib": "file:../mylib" } }
main.js
を実行してみます:$ node main.js Hello World!しっかりと
mylib
の変数が使われているが分かります。ちなみに、インストールされた
myapp/node_modules/mylib
は../../mylib
へのシンボリックリンクになります:$ ls -la myapp/node_modules lrwxr-xr-x 11 suin 14 Apr 9:35 mylib -> ../../mylib
- 投稿日:2020-04-14T02:55:12+09:00
商品一覧ページ内のカートに入れる機能の実装(非同期通信)
はじめに
商品一覧ページ内の各商品に割り振られているカートに入れるボタンが押された際にuser_idとeffector_id(現在作成中のアプリケーションではエッフェクターが商品のため各所でeffectorを使用していく)にログイン中のuserのidとクリックされた商品のidを保存することを目指す。今回は非同期通信を使用したい。
テーブル、コントローラー、APIの作成
cartsテーブルの作成
ターミナルアプリケーションのディレクトリ$ rails g model cartcartモデルの作成
(migrateファイル)create_carts.rbclass CreateCarts < ActiveRecord::Migration[5.0] def change create_table :carts do |t| t.references :user, foreign_key: true t.references :effector, foreign_key: true t.timestamps end end endマイグレーションファイルの編集
ターミナルアプリケーションのディレクトリ$ rails db:migrateマイグレーションの実行
(modelファイル)cart.rbclass Cart < ApplicationRecord belongs_to :effector belongs_to :user end(modelファイル)effector.rbclass Effector < ApplicationRecord belongs_to :genre has_many :users, through: :carts #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要 has_many :carts end(modelファイル)user.rbclass User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :boards has_many :effectors, through: :carts #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要 has_many :carts end各モデル内にリレーションを記載
APIの準備
app/controller/api/carts_controller.rbを作成
app/controller/api/carts_controller.rbclass Api::CartsController < ApplicationController def create Cart.create(user_id: params[:user_id], effector_id: params[:effector_id]) #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存 end endルーティング設定
routes.rbRails.application.routes.draw do root to: "effectors#index" devise_for :users resources :users, only: [:show, :edit, :update] resources :boards resources :effectors do resources :genres end resources :carts, only: [:show, :destroy] namespace :api do resources :carts, only: :create, defaults: { format: 'json'} end #cartsコントローラーとapp/controller/api/carts_controller.rbのルーティング設定 endここまで設定が終わったら商品一覧のカートに入れるボタンが押された際にcartsテーブルにuser_idとeffector_idが保存されるようにjsを記述していく。
商品一覧のカートに入れるボタンが押された時の処理
カートに入れるボタンが押された時onclick:を用いてjs内の関数を発火できるように記述する。
app/views/effectors/index.html.haml.main .main__list - @effectors.each do |effector| .main__list__effector{data: {genre: effector.genre.id}} .main__list__effector__info .main__list__effector__info__visual %h.main__list__effector__info__visual__name = effector.name .main__list__effector__info__visual__image %img{alt: "image1", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image1}"} %img{alt: "image2", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image2}"} .main__list__effector__info__text %h.main__list__effector__info__text__genre = effector.genre.genre %h.main__list__effector__info__text__point = effector.point pt %br %h.main__list__effector__info__text__detail = effector.text .main__list__effector__info__btns - if effector.youtube != nil .main__list__effector__info__btns__video %button.main__list__effector__info__btns__video__btn{onclick: "test(#{effector.youtube})"} 動画を視聴 - if effector.link != nil .main__list__effector__info__btns__official = link_to "#{effector.link}", class: "main__list__effector__info__btns__official__btn" do .main__list__effector__info__btns__official__btn__text 公式サイト - if user_signed_in? .main__list__effector__info__btns__cart %button.main__list__effector__info__btns__cart__btn{onclick: "createCart(#{current_user.id},#{effector.id})"} -#クリックされた時関数名createCartを引数(current_user.id,effector.id)とし発火 カートに入れる .popup .popup__content .popup__content__youtube %iframe(width="560" height="315" id = "youtube_test" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen) %button#close 閉じる発火される関数の記述
effectors.jsfunction createCart(userId, effectorId) { var param = { user_id: userId, effector_id: effectorId //受け取った引数をuser_id:とeffector_id:として変数paramに格納 } ajaxRequest("api/carts",'post',param) //非同期通信する際の関数を複数回の利用を見越して外出しして呼び出す(引数をapi/carts,post,paramとし呼び出し) } function ajaxRequest(url,type,data) { $.ajax({ url: url, //url: api/cartsと同義 type: type, //type: postと同義 dataType: 'json', data: data //data: paramと同義 //引数で持ってきた仮引数url,type,dataを使用しajaxの記述をする }) .done(function() { alert('商品をカートに入れました') }) .fail(function() { alert('error'); }); }ここまできたらjson形式で送られたデータをapi側のコントローラーで保存してあげるだけである。
先ほど記述したapp/controller/api/carts_controller.rbを見てみるapp/controller/api/carts_controller.rbclass Api::CartsController < ApplicationController def create Cart.create(user_id: params[:user_id], effector_id: params[:effector_id]) #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存 end endすでに記載している通りにjosn形式で送られてきたデータからcartsテーブルのuser_idカラムにparams[:user_id]をeffector_idカラムにparams[:effector_id]を保存する記載をする。
これにてカートに入れるボタンの実装が完了します。終わりに
今回はカートに入れるボタンというショッピングサイトには欠かせない機能を非同期通信にて行えるように実装した。
ユーザーと商品という多対多という関係性、非同期通信でのデータの保存など初学者が苦労する機能の実装を行うことで力がつくのを感じました。
この機能はいいね機能などにも流用できると思うので学習する価値ありだと感じます。
2回目の投稿のため拙い文章が眼に余るかと思いますがご精読ありがとうございました。駆け出しエンジニアのみなさん一緒に頑張っていきましょう。
- 投稿日:2020-04-14T02:55:12+09:00
商品一覧ページ内のカートに入れるボタンの実装(非同期通信)
はじめに
商品一覧ページ内の各商品に割り振られているカートに入れるボタンが押された際にuser_idとeffector_id(現在作成中のアプリケーションではエッフェクターが商品のため各所でeffectorを使用していく)にログイン中のuserのidとクリックされた商品のidを保存することを目指す。今回は非同期通信を使用したい。
テーブル、コントローラー、APIの作成
cartsテーブルの作成
ターミナルアプリケーションのディレクトリ$ rails g model cartcartモデルの作成
(migrateファイル)create_carts.rbclass CreateCarts < ActiveRecord::Migration[5.0] def change create_table :carts do |t| t.references :user, foreign_key: true t.references :effector, foreign_key: true t.timestamps end end endマイグレーションファイルの編集
ターミナルアプリケーションのディレクトリ$ rails db:migrateマイグレーションの実行
(modelファイル)cart.rbclass Cart < ApplicationRecord belongs_to :effector belongs_to :user end(modelファイル)effector.rbclass Effector < ApplicationRecord belongs_to :genre has_many :users, through: :carts #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要 has_many :carts end(modelファイル)user.rbclass User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :boards has_many :effectors, through: :carts #今回はcartsコントローラーのshowアクションを使用するため上の記述は不要 has_many :carts end各モデル内にリレーションを記載
APIの準備
app/controller/api/carts_controller.rbを作成
app/controller/api/carts_controller.rbclass Api::CartsController < ApplicationController def create Cart.create(user_id: params[:user_id], effector_id: params[:effector_id]) #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存 end endルーティング設定
routes.rbRails.application.routes.draw do root to: "effectors#index" devise_for :users resources :users, only: [:show, :edit, :update] resources :boards resources :effectors do resources :genres end resources :carts, only: [:show, :destroy] namespace :api do resources :carts, only: :create, defaults: { format: 'json'} end #cartsコントローラーとapp/controller/api/carts_controller.rbのルーティング設定 endここまで設定が終わったら商品一覧のカートに入れるボタンが押された際にcartsテーブルにuser_idとeffector_idが保存されるようにjsを記述していく。
商品一覧のカートに入れるボタンが押された時の処理
カートに入れるボタンが押された時onclick:を用いてjs内の関数を発火できるように記述する。
app/views/effectors/index.html.haml.main .main__list - @effectors.each do |effector| .main__list__effector{data: {genre: effector.genre.id}} .main__list__effector__info .main__list__effector__info__visual %h.main__list__effector__info__visual__name = effector.name .main__list__effector__info__visual__image %img{alt: "image1", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image1}"} %img{alt: "image2", class: "main__list__effector__info__visual__image__file", src: "#{- effector.image2}"} .main__list__effector__info__text %h.main__list__effector__info__text__genre = effector.genre.genre %h.main__list__effector__info__text__point = effector.point pt %br %h.main__list__effector__info__text__detail = effector.text .main__list__effector__info__btns - if effector.youtube != nil .main__list__effector__info__btns__video %button.main__list__effector__info__btns__video__btn{onclick: "test(#{effector.youtube})"} 動画を視聴 - if effector.link != nil .main__list__effector__info__btns__official = link_to "#{effector.link}", class: "main__list__effector__info__btns__official__btn" do .main__list__effector__info__btns__official__btn__text 公式サイト - if user_signed_in? .main__list__effector__info__btns__cart %button.main__list__effector__info__btns__cart__btn{onclick: "createCart(#{current_user.id},#{effector.id})"} -#クリックされた時関数名createCartを引数(current_user.id,effector.id)とし発火 カートに入れる .popup .popup__content .popup__content__youtube %iframe(width="560" height="315" id = "youtube_test" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen) %button#close 閉じる発火される関数の記述
effectors.jsfunction createCart(userId, effectorId) { var param = { user_id: userId, effector_id: effectorId //受け取った引数をキーuser_id:とキーeffector_id:にそれぞれのバリューとして変数paramに格納 } ajaxRequest("api/carts",'post',param) //非同期通信する際の関数を複数回の利用を見越して外出しして呼び出す(引数をapi/carts,post,paramとし呼び出し) } function ajaxRequest(url,type,data) { $.ajax({ url: url, //url: api/cartsと同義 type: type, //type: postと同義 dataType: 'json', data: data //data: paramと同義 //引数で持ってきた仮引数url,type,dataを使用しajaxの記述をする }) .done(function() { alert('商品をカートに入れました') }) .fail(function() { alert('error'); }); }ここまできたらjson形式で送られたデータをapi側のコントローラーで保存してあげるだけである。
先ほど記述したapp/controller/api/carts_controller.rbを見てみるapp/controller/api/carts_controller.rbclass Api::CartsController < ApplicationController def create Cart.create(user_id: params[:user_id], effector_id: params[:effector_id]) #json形式で送られてきたデータからparams[:user_id]をuser_idカラムにparams[:effector_id]をeffector_idカラムに保存 end endすでに記載している通りにjosn形式で送られてきたデータからcartsテーブルのuser_idカラムにparams[:user_id]をeffector_idカラムにparams[:effector_id]を保存する記載をする。
これにてカートに入れるボタンの実装が完了します。終わりに
今回はカートに入れるボタンというショッピングサイトには欠かせない機能を非同期通信にて行えるように実装した。
ユーザーと商品という多対多という関係性、非同期通信でのデータの保存など初学者が苦労する機能の実装を行うことで力がつくのを感じました。
この機能はいいね機能などにも流用できると思うので学習する価値ありだと感じます。
2回目の投稿のため拙い文章が眼に余るかと思いますがご精読ありがとうございました。駆け出しエンジニアのみなさん一緒に頑張っていきましょう。
- 投稿日:2020-04-14T00:59:33+09:00
discord.js + Klasa を使ったBotの作成覚え書き
参考 : discord.jsのフレームワークKlasaが強すぎる
合わせて読んでください。準備
- 環境
- Win10
- Node.js 12.13.0
- npm 6.12.0
適当にプロジェクトフォルダを作成し discord.js と Klasa をインストール
npm install --save discordjs/discord.js dirigeants/klasaコーディング
最初の一歩
app.js
を作成app.jsconst secret = require('./secret.js'); // BOTトークンはここに記述 const token = secret.token; const {Client} = require('klasa'); new Client({ prefix: '!!', // ボットのPrefix language: 'ja-JP', // 言語コード }).login(token);この状態で一度
node app.js
から起動し、危険なログが出てなければとりあず成功。コマンドの作成
commands/general
配下に以下のソースを作成。Klasaはファイル名がそのままコマンド名になる。
ディレクトリ名はヘルプのカテゴリ名になる。
なお、下のソースに書かれているusage
は単なる説明文ではなく引数のマッチャを参照するための記述なので注意。(これで30分ぐらい潰した……)commands/general/hello.jsconst {Command} = require('klasa'); module.exports = class extends Command { /** * @constructor * @param {...any} args */ constructor(...args) { // コマンドのオプション: https://klasa.js.org/#/docs/klasa/master/typedef/CommandOptions super(...args, { description: '挨拶を返す', usage: '<name:string>', // <>は必須引数、[]はオプション引数、<名前:型>のように書く }); } /** * @param {*} message */ async run(message,[name]) { return message.sendMessage(`${name}さんこんにちは!`); } };参考 :
Klasa : CreatingArguments
Klasa : CreatingCommandsBOTの反応はこんなかんじ
データストアの作成
providers
ディレクトリにプロバイダを作成する。公式を見るとなんか適当に書いてよさそうだったので適当に書いてみる。providers/datas.jsconst {Provider} = require('klasa'); module.exports = class extends Provider { /** * @constructor * @param {...any} args */ constructor(...args) { super(...args, {name: 'datas'}); this.counter = 0; } /** * init */ init() { this.counter=1; } /** * countup * @return {Number} count */ countup() { this.counter++; return this.counter; } };
hello.js
から動作確認してみる。const {Command} = require('klasa'); module.exports = class extends Command { /** * @constructor * @param {...any} args */ constructor(...args) { // コマンドのオプション: https://klasa.js.org/#/docs/klasa/master/typedef/CommandOptions super(...args, { description: '挨拶を返す', usage: '<name:string>', }); this.data = this.client.providers.get('datas'); } /** * @param {*} message */ async run(message, [name]) { return message.sendMessage(`${name}さんこんにちは!${this.data.countup()}回めの挨拶ですね!`); } };本当に適当に動いてしまった。
- 投稿日:2020-04-14T00:12:51+09:00
RailsでGoogleAnalyticsを設定する
Railsで作成したアプリにGoogleAnalyticsを設定することがたくさんあると思う。
google-analytics-railsという便利なgemがあるそうだが、PRを見てみると2017年10月で終わっている…
多分メンテナンスされていないし、gemを使うほどでもないので自分で設定することにしたが、RailsからJavascriptへの変数の渡し方に手間取ったので残しておく。Analyticsタグの設置
GoogleAnalyticsタグは
head
に書いていく。今回はログインしている場合は変数current_user
をJavascriptに渡してあげて、ログインしていない場合は変数を渡さないという仕様にする。
このcurrent_user
をRailsからJavascriptに渡す時にかなり工夫した。コード
コードを書いていく。テンプレートエンジンはslimを使っている。
app/views/layouts/application.slim.htmldoctype html html head meta content=("text/html; charset=UTF-8") http-equiv="Content-Type" = csrf_meta_tags = stylesheet_link_tag 'application', media: 'all' = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' - if Rails.env.production? = render './google_analytics'Analyticsは本番環境だけで動かしたいので
if Rails.env.production?
の中に入れる。
Analyticsスクリプトは他のファイルでも使う可能性があり使いまわしたいので、部分テンプレートで共通化しておく。
先に答えを出すと、下記のようなコードになる。app/views/layouts/_google_analytics.slim.htmlscript async="" src="https://www.googletagmanager.com/gtag/js?id=#{トラッキングID}" javascript: window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'トラッキングID'); if (#{raw current_user.to_json}) { gtag('set', {'user_id': #{raw current_user.to_json}.id}); }RailsからJavascriptに変数を渡す場合、その変数のデータ型がintegerの場合はそのまま渡して問題ないが、それ以外の場合は
current_user.to_json
というようにto_json
をつけてあげないといけない。
また、エスケープ処理をさせないために、ActionView::Helpers::OutputSafetyHelper
で用意されているraw
メソッドを使用する。
こうすることで、Railsのcurrent_user
をgon
などを使わずに渡すことが出来た。
- 投稿日:2020-04-14T00:02:08+09:00
ReactでLIFFアプリケーションをつくる 〜その1 VSCode+Docker+Reactの環境構築する〜
はじめに
最初に、今回は環境構築なので、LIFFは登場しません
LINEってワードをよく聞くし、キャッシュレスの流れも強めなので、
「LINE連携したアプリケーション(MessagingAPI、LIFF、LINE Pay)を作れたら結構強い人なんじゃないか?」
と最近思い始めました。
(LINE Payって個人利用できたりするのだろうか?)Messaging APIは少し触ったので、今回はReactでLIFFアプリケーションを作ります。
この記事では、VSCode+Docer+Reactの環境構築〜HelloWorldまでやります。※ちなみに、LIFFとは以下のことです
https://developers.line.biz/ja/docs/liff/overview/VSCode
Install
https://azure.microsoft.com/ja-jp/products/visual-studio-code/
からダウンロード&インストールしてください。Macユーザで、
Homebrew
導入済であれば、以下コマンドでインストールできます。brew cask install visual-studio-codeSetting : 設定
setting.json
editorやら、formatやらの設定ファイルです。
以下サイトを参考にとりあえず設定してみました。
- IntelliSense in Visual Studio Code
- VSCodeで爆速コーディング環境を構築する(主にReactJS向け設定)
- Visual Studio Code の初期設定と最低限必要な拡張機能 - フロントエンド向け -
Command + ,
で設定を開き、右上にあるアイコン(↓のようなアイコンがあります)を押すとsettings.json
を編集できます。
そして、内容は以下のように設定しました。
settings.json{ // see. Customizing IntelliSense // The contents described below have been copied // https://code.visualstudio.com/docs/editor/intellisense#_customizing-intellisense // from here // Controls if quick suggestions should show up while typing "editor.quickSuggestions": { "other": true, "comments": false, "strings": false }, // Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character. "editor.acceptSuggestionOnCommitCharacter": true, // Controls if suggestions should be accepted on 'Enter' - in addition to 'Tab'. Helps to avoid ambiguity between inserting new lines or accepting suggestions. The value 'smart' means only accept a suggestion with Enter when it makes a textual change "editor.acceptSuggestionOnEnter": "on", // Controls the delay in ms after which quick suggestions will show up. "editor.quickSuggestionsDelay": 10, // Controls if suggestions should automatically show up when typing trigger characters "editor.suggestOnTriggerCharacters": true, // Controls if pressing tab inserts the best suggestion and if tab cycles through other suggestions // タブでサジェクト内容の切替できるようにする "editor.tabCompletion": "on", // Controls whether sorting favours words that appear close to the cursor "editor.suggest.localityBonus": true, // Controls how suggestions are pre-selected when showing the suggest list // 直近利用したワードが一番最初に選択されるようにサジェクトされる "editor.suggestSelection": "recentlyUsed", // Enable word based suggestions "editor.wordBasedSuggestions": true, // Enable parameter hints "editor.parameterHints.enabled": true, // to here "diffEditor.renderSideBySide": false, "editor.colorDecorators": false, // see. // [VSCodeで爆速コーディング環境を構築する(主にReactJS向け設定)](https://qiita.com/teradonburi/items/c4cbd7dd5b4810e1a3a9) // [Visual Studio Code の初期設定と最低限必要な拡張機能 - フロントエンド向け -](https://qiita.com/hi85/items/eaede5ebb509f21f27f5) // format "editor.formatOnPaste": true, "editor.formatOnSave": true, "html.format.extraLiners": "", "html.format.unformatted": null, "html.format.wrapLineLength": 0, // editor "editor.minimap.enabled": false, "editor.multiCursorModifier": "ctrlCmd", "editor.renderControlCharacters": true, "editor.renderLineHighlight": "all", "editor.tabSize": 2, "editor.wordWrap": "on", // emmet "emmet.showSuggestionsAsSnippets": true, "emmet.triggerExpansionOnTab": true, "emmet.variables": { "lang": "ja" }, // confirm when deleting files. "explorer.confirmDelete": true, // files "files.exclude": { "**/.git": true, "**/.DS_Store": true, "**/node_modules": true }, "files.insertFinalNewline": true, "files.trimFinalNewlines": true, "files.trimTrailingWhitespace": true, "search.exclude": { "**/.git": true, "**/node_modules": true // @TODO: List files to exclude from search. } }keybinding.json
キーバインドの設定です。
Command + k -> Command + s
で設定を表示し、また右上にある以下アイコンを押すとkeybindings.json
を開けます。設定値は本家の内容をまるパクリしました。
keybinding.json// Place your key bindings in this file to override the defaults [ // see Key bindings // https://code.visualstudio.com/docs/editor/intellisense#_key-bindings { "key": "ctrl+space", "command": "editor.action.triggerSuggest", "when": "editorHasCompletionItemProvider && editorTextFocus && !editorReadonly" }, { "key": "ctrl+space", "command": "toggleSuggestionDetails", "when": "editorTextFocus && suggestWidgetVisible" }, { "key": "ctrl+alt+space", "command": "toggleSuggestionFocus", "when": "editorTextFocus && suggestWidgetVisible" } ]Extension
プラグインの導入です。
以下サイトを参考にインストールさせていただきました。
- インストールするだけでVSCodeをカッコよくする拡張4つ - Qiita
- VSCodeのオススメ拡張機能 24 選 (とTipsをいくつか)
- VSCode intellisense
- React Tutorial 2: ローカル開発環境
install-extension.bash## see ## [インストールするだけでVSCodeをカッコよくする拡張4つ - Qiita](https://qiita.com/ksakiyama134/items/8ca98295897dc1280644) ## Bracket Pair Colorizer ## see. https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer code --install-extension CoenraadS.bracket-pair-colorizer ## Dracula Theme ## see. https://draculatheme.com code --install-extension gerane.Theme-Dracula ## Indent Rainbow ## see. https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow code --install-extension oderwat.indent-rainbow ## Material Icon Theme ## see. https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme code --install-extension PKief.material-icon-theme ## see ## [VSCodeのオススメ拡張機能 24 選 (とTipsをいくつか)](https://qiita.com/sensuikan1973/items/74cf5383c02dbcd82234) ## GitLens ## see. https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens ## REST CLIENT ## see. https://marketplace.visualstudio.com/items?itemName=humao.rest-client code --install-extension humao.rest-client ## Partial Diff ## see. https://marketplace.visualstudio.com/items?itemName=ryu1kn.partial-diff code --install-extension ryu1kn.partial-diff ## React snippets code --install-extension dsznajder.es7-react-js-snippets ## Babel JavaScript code --install-extension mgmcdermott.vscode-language-babel ## Marp for VSCode ## see. https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode code --install-extension marp-team.marp-vscodeconfirm installed extension : インストール済の確認
インストールしたExtensionは
code -list-extensions
で確認できますちなみに
設定ファイル類はこちらにコミットしましたがなんだか見辛かったので、それぞれ記載しました。
https://github.com/ken-araki/env/tree/master/vscodenode
Install
まずはnodeをインストールするのですが、今回はdockerを利用します。
なので、作業ディレクトリに以下ファイルを作成してください。(dockerについてはあまり触れません)docker-compose.yml
docker-compose.ymlversion: "3" services: node: build: ./docker/node volumes: - ./:/home/node ports: - "3000:3000"その後、以下コマンドでDockerイメージを作成しておきます。
docker-compose builddocker/node/Dockerfile
docker/node/DockerfileFROM node:13.12.0-slim WORKDIR /home/nodeReact
基本的に、React Tutorial 2: ローカル開発環境に沿って進めます。
Node.jsのインストールが終わっているので、「2. Create React App のインストールガイドに従って新しいプロジェクトを作成する。」から始めます。
2. Reactアプリケーションの作成
以下コマンドでDocker containerで
npx create-react-app my-app
を実行します。
(my-app
部分はよしなに変更してください)docker-compose run --rm node sh -c "npx create-react-app app"3~6. srcの改修
チュートリアルにしたがって、src配下に
index.js
とindex.css
を作成してください。
(と言ってもコピペ)Reactアプリケーションの開始
以下コマンドでDocker containerで
npm start
を実行します。docker-compose run --rm --service-ports node sh -c "cd app; npm start"その後http://localhost:3000にアクセスすると空の三目並べの盤面が表示されます。
コード
コードはこちらにコミットしています
https://github.com/ken-araki/line-liffおわりに
まずは、これでいい感じにコーディングできるか試してみようと思います。
Reactチュートリアルやりながら、イケていない部分を少しずつ直していきます。
「もっとこうした方がいいよ!」があったら教えてもらえると嬉しいです!次は、チュートリアル終わらせつつ、LIFFアプリケーション登録までやろうと思います。
そのあと、kotlin-reactも触ってみたいのですが、業務で使う機会なさそうだな、とも思ったり。。。
どうなんですかね?と言うので、今回は終わりです。