20200406のJavaScriptに関する記事は25件です。

【JavaScript関連】【短期】Qiitaの読んでおかなければいけない記事100選【毎日自動更新】

ページ容量を増やさないために、不具合報告やコメントは、説明記事 に記載いただけると助かります。
CSS, HTML 等のタグのみが付与されている記事は除いています。
【CSS/HTML】【短期】Qiitaの読んでおかなければいけない記事100選【毎日自動更新】 を参照してください。

順位 記事名
________________________________________
ユーザ 投稿日付
更新日付
LGTM1
1 Chrome拡張の高速な英語辞書ツールをつくりました(Mouse Dictionary) wtetsu 18/09/04
19/12/31
4111
124
2 2020年のフロントエンドマスターになりたければこの9プロジェクトを作れ rana_kualu 19/11/11
19/11/20
2781
245
3 イマドキのJavaScriptの書き方2018 shibukawa 17/12/26
19/11/13
5038
187
4 2020年にWebフロントエンドを勉強する人が作るべきたったひとつのアプリ Dragon-taro 20/02/04
20/02/09
2179
2179
5 4歳娘「パパ、具体的な名前をつけないで?」 Yametaro 20/03/18
20/03/31
1532
1532
6 TypeScriptの型入門 uhyo 18/02/16
19/11/05
2191
246
7 ワイの正規表現入門 Yametaro 20/03/01
20/03/04
1474
1474
8 すべての新米フロントエンドエンジニアに読んでほしい50の資料 suzu-4 19/07/11
19/07/12
3445
174
9 【動画付き】 draw.io 使い方まとめ 〜エンジニアでなくても使えるTips集〜 G-awa 20/02/09
20/02/09
1397
1397
10 Vue.jsを100時間勉強して分かったこと kskinaba 19/05/16
19/12/23
1289
507
11 async/await 入門(JavaScript) soarflat 17/08/03
19/12/24
1717
212
12 Vue.jsで作成された、ちょっと面白くて役立ちそうなサービス s-yoshiki 20/01/28
20/01/31
1476
1476
13 【保存版】Webフロントエンド基礎力(初心者向け) teradonburi 19/11/04
20/03/15
1578
105
14 webpack 4 入門 soarflat 17/02/01
19/09/02
1809
137
15 Vue開発者のためのVue.jsベストプラクティス集15選 mtoyopet 20/01/29
20/02/25
1267
1267
16 Vue.js を vue-cli を使ってシンプルにはじめてみる 567000 16/09/10
19/07/09
1464
124
17 たぶんこれが一番分かりやすいと思います React + Redux のフロー図解 mpyw 17/01/05
18/04/23
2313
134
18 jQuery から Vue.js へのステップアップ mio3io 17/10/13
18/12/14
1821
88
19 治安の悪い Slack Emoji を作るツールを作った zk_phi 18/06/17
20/01/29
2266
126
20 Reactを使うとなぜjQueryが要らなくなるのか naruto 16/05/09
19/10/31
4109
84
21 【JavaScript】アロー関数式を学ぶついでにthisも復習する話 mejileben 17/03/26
19/07/11
1203
114
22 ReactとVueのどちらを選ぶか yoichiwo7 18/06/16
19/06/05
1538
106
23 JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 suin 20/03/22
20/03/23
1159
1159
24 TypeScriptをプロダクト開発に使う上でのベストプラクティスと心得 jagaapple 20/02/04
20/03/17
1093
1093
25 ワイ「何で子コンポーネントに状態を持たせたらあかんの?」 Yametaro 19/11/21
19/12/27
904
52
26 vue.js + typescript = vue.ts ことはじめ nrslib 18/10/08
19/11/11
992
126
27 MacにNode.jsをインストール kyosuke5_20 16/11/15
20/02/16
712
127
28 もしものために,香川県からのアクセスを避ける ni__no13 20/01/22
20/03/18
965
965
29 ES2015(ES6) 入門 soarflat 16/12/14
20/01/17
1104
89
30 ラーメンで理解するasync/await 7tsuno 19/12/18
19/12/23
1135
115
31 コードレビュー虎の巻 teradonburi 19/11/19
19/12/24
1238
48
32 <script> タグに async / defer を付けた場合のタイミング phanect 17/08/05
19/02/23
870
107
33 フロントエンドのコンポーネント設計に立ち向かう seya 18/04/01
19/04/21
1370
113
34 今からVue.jsを始める人のための「知るのを後回しにしてよい」n個のこと fruitriin 20/03/06
20/03/08
783
783
35 【Laravel 6 & PHP 7.4 対応】Vue + Vue Router + Vuex + Laravel チュートリアル(全16回)を書きました。 MasahiroHarada 19/01/13
20/01/19
1809
85
36 この TypeScript が Hello, world! のくせに慎重すぎる matzkoh 19/12/02
20/01/28
464
433
37 2019年版 最先端のフロントエンド開発者になるために学ぶべきこと baby-degu 19/07/21
19/11/14
1533
53
38 2018年の最先端フロントエンドエンジニアになろう rana_kualu 18/04/02
19/05/12
1794
30
39 テストしやすい「純粋」な関数とは? Yametaro 20/01/18
20/01/20
831
831
40 お前らのReactは遅い teradonburi 18/12/01
20/02/15
857
121
41 iPadでプログラミングしてる人、今まで馬鹿にしててすみませんでしたァァァァ!!!! Mahito6 19/03/04
19/07/18
1924
69
42 Vue.js + Vuexでデータが循環する全体像を図解してみた m_mitsuhide 18/07/30
19/12/05
1009
90
43 個人的にオススメしたいTech系YouTuberたち yuki-naka 20/02/09
20/02/09
622
622
44 CORSまとめ tomoyukilabs 16/02/01
17/11/30
1520
70
45 2019年版Vue.jsを使ってる人には必ず知っていてほしいVue.jsの武器とドキュメントに書かれていないコンポーネントやメンテナンスの際に役立つTips kahirokunn 19/03/01
20/01/08
1400
88
46 Facebook製のJavaScriptテストツール「Jest」の逆引き使用例 chimame 16/10/13
18/11/07
966
84
47 ブラウザレンダリングの仕組み goemp 19/11/24
19/12/14
980
16
48 正規表現の可視化ツールRegulexを使おう! yucatio 20/03/02
20/03/03
557
557
49 JavaScriptの配列の使い方まとめ。要素の追加,結合,取得,削除。 takeharu 15/11/28
16/06/28
1335
61
50 VTuberのホームページをGitHubのプルリクだけで更新していったらどうなるのか?企画に参戦してみた unsoluble_sugar 20/01/18
20/01/20
678
678
51 ESLint 最初の一歩 mysticatea 15/10/21
19/07/08
1195
64
52 2018年のフロントエンドエンジニアならこの程度は知ってて当然だよな? rana_kualu 18/02/28
18/05/16
2004
43
53 Prettier 入門 ~ESLintとの違いを理解して併用する~ soarflat 18/02/21
18/07/23
801
63
54 JavaScript で forEach を使うのは最終手段 diescake 18/12/01
18/12/06
579
104
55 Reactベース静的サイトジェネレータGatsbyの真の力をお見せします uehaj 18/12/21
19/08/23
540
108
56 あなたがnpm installをしてはいけない時 jigengineer 19/08/09
19/08/14
731
126
57 もう保守されない画面遷移図は嫌なので、UI Flow図を簡単にマークダウンぽく書くエディタ作った hirokidaichi 16/04/02
18/12/25
4809
41
58 貴方はいくつ知っている?あまり知られていない便利なChrome DevToolsの機能まとめ HayatoKamono 19/12/10
19/12/30
818
21
59 TypeScriptを使って嬉しかったこと Yametaro 20/01/12
20/01/25
648
648
60 ブラウザレンダリング入門〜知ることで見える世界〜 codemafia0000 19/03/16
19/03/27
1698
42
61 関数型プログラミングはまず考え方から理解しよう stkdev 16/04/24
16/05/08
2110
66
62 4歳娘「パパ、20歳以上のユーザーを抽出して?」 Yametaro 20/04/02
20/04/08
440
440
63 TypeScriptのInterfaceとTypeの比較 tkrkt 17/05/26
19/04/16
536
79
64 新人にドヤ顔で説明できるか、今風フロントエンド開発ハンズオン(Git/Node.js/ES6/webpack4/Babel7) riversun 18/11/11
19/09/04
1856
26
65 Ubuntuに最新のNode.jsを難なくインストールする seibe 15/12/10
19/02/10
959
58
66 JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる YoshikiNakamura 16/01/27
18/10/25
947
44
67 jQuery愛好家のためのVue.js、React入門(いずれAngularも) BRSF 20/01/24
20/03/13
501
501
68 JavaScriptが辿った変遷 naoki_mochizuki 16/09/19
19/01/17
1107
53
69 非同期処理ってどういうこと?JavaScriptで一から学ぶ kiyodori 15/12/19
15/12/19
1048
53
70 フロントエンドエンジニア1年目はコードレビューでどんな指摘を受けるのか su_mi1228 19/11/19
19/12/04
563
9
71 ReactとVueを改善したSvelteというライブラリーについて so99ynoodles 19/05/17
19/07/05
707
69
72 2017年のフロントエンドエンジニアならこの程度は知ってて当然だよな? rana_kualu 17/02/14
19/03/07
2790
32
73 Webpackってどんなもの? kamykn 16/09/17
16/09/19
882
66
74 ?React 16.8: 正式版となったReact Hooksを今さら総ざらいする uhyo 19/02/03
20/01/19
735
76
75 フロントエンドエンジニア御用達の MDN web docs を網羅した snakada 19/09/21
19/10/27
1169
34
76 ReactはウェブやHTMLとは特に関係のないライブラリです kfurumiya 20/03/07
20/03/07
615
615
77 3000人に聞いた、2019年最先端のフロントエンド開発者が使ってるツールはこれだ rana_kualu 19/12/15
19/12/15
734
43
78 JavaScriptのpreventDefault()って難しくない?preventDefault()を使うための前提知識 tochiji 18/08/19
19/12/10
371
94
79 【2019年4月版】JavaScriptのconsoleがすごいことになってた。 koinori 19/04/02
19/04/11
2311
11
80 【初心者向け】NPMとpackage.jsonを概念的に理解する righteous 19/06/24
20/03/11
260
138
81 JavaScript の this を理解する多分一番分かりやすい説明 takkyun 17/07/29
18/10/14
801
51
82 Vueのライフサイクルを完全に理解した chan_kaku 18/11/24
20/01/09
320
102
83 ようこそ!Electron入門 umamichi 16/12/28
19/11/22
463
66
84 Vue.jsの書き方実例集(随時追加)※逆引きリファレンス的な Yorinton 17/09/02
19/01/26
525
45
85 Storybookがなぜ必要か?(Vue.js編) masaakikunsan 17/12/23
19/02/26
602
46
86 Vueの秘密のパフォーマンステク9選紹介 miyaoka 19/05/15
19/05/16
1097
50
87 JavaScript アロー関数を説明するよ may88seiji 17/04/16
19/08/26
452
75
88 JavaScript の テンプレートリテラル を極める! kura07 15/08/07
18/09/17
733
59
89 2019年5月時点 JavaScript初心者が参考にしていいモダンJavaScript解説サイト2つ fujineyuri 19/05/25
19/05/25
1170
11
90 Vue.js to TypeScriptの書き方一覧 ryo2132 19/04/13
19/09/09
341
82
91 JavaScriptでvarが推奨されない理由を整理してみた taiju_suzuki 20/01/08
20/01/13
620
219
92 TypeScript + Node.js プロジェクトのはじめかた2019 notakaos 19/02/08
19/11/11
347
94
93 slackで「投稿ルールが守られない問題」を自作のスラッシュコマンドで解決する(設定編) marogoma 19/06/15
19/06/27
1156
9
94 [axios] axios の導入と簡単な使い方 ksh-fthr 17/09/13
19/07/15
416
59
95 高階関数を書いたら、中級者になれた気がした。 Yametaro 20/03/20
20/03/26
368
368
96 Nuxt.jsを使うときに、SPA・SSR・静的化のどれがいいか迷ったら nishinoshake 18/09/17
18/09/20
494
62
97 Vue.js おすすめライブラリ 21選(おまけ+1) andmorefine 19/04/14
19/04/16
699
51
98 Chrome拡張の開発方法まとめ その1:概念編 k7a 16/03/13
16/03/15
938
37
99 【Google Apps Script, Slack】彼女にバレずにワクワクメールのメッセージに気付くために夜な夜な怪しげなスクリプトを組んだ話 83k 20/01/06
20/01/09
652
80
100 20 年代のフロントエンド mizchi 20/01/30
20/01/30
501
501

  1. 1行目が総数。2行目が直近3ヵ月。 

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

【JavaScript関連】【長期】Qiitaの読んでおかなければいけない記事100選【毎日自動更新】

ページ容量を増やさないために、不具合報告やコメントは、説明記事 に記載いただけると助かります。
CSS, HTML 等のタグのみが付与されている記事は除いています。
【CSS/HTML】【長期】Qiitaの読んでおかなければいけない記事100選【毎日自動更新】 を参照してください。

順位 記事名
________________________________________
ユーザ 投稿日付
更新日付
LGTM1
1 イマドキのJavaScriptの書き方2018 shibukawa 17/12/26
19/11/13
5038
1082
2 Chrome拡張の高速な英語辞書ツールをつくりました(Mouse Dictionary) wtetsu 18/09/04
19/12/31
4111
1689
3 TypeScriptの型入門 uhyo 18/02/16
19/11/05
2191
1121
4 async/await 入門(JavaScript) soarflat 17/08/03
19/12/24
1717
846
5 webpack 4 入門 soarflat 17/02/01
19/09/02
1809
610
6 Vue.js を vue-cli を使ってシンプルにはじめてみる 567000 16/09/10
19/07/09
1464
656
7 Reactを使うとなぜjQueryが要らなくなるのか naruto 16/05/09
19/10/31
4109
474
8 すべての新米フロントエンドエンジニアに読んでほしい50の資料 suzu-4 19/07/11
19/07/12
3445
3445
9 たぶんこれが一番分かりやすいと思います React + Redux のフロー図解 mpyw 17/01/05
18/04/23
2313
586
10 2020年のフロントエンドマスターになりたければこの9プロジェクトを作れ rana_kualu 19/11/11
19/11/20
2781
2781
11 jQuery から Vue.js へのステップアップ mio3io 17/10/13
18/12/14
1821
531
12 【JavaScript】アロー関数式を学ぶついでにthisも復習する話 mejileben 17/03/26
19/07/11
1203
552
13 Vue.jsを100時間勉強して分かったこと kskinaba 19/05/16
19/12/23
1289
1289
14 治安の悪い Slack Emoji を作るツールを作った zk_phi 18/06/17
20/01/29
2266
488
15 2020年にWebフロントエンドを勉強する人が作るべきたったひとつのアプリ Dragon-taro 20/02/04
20/02/09
2155
2155
16 ES2015(ES6) 入門 soarflat 16/12/14
20/01/17
1104
425
17 ReactとVueのどちらを選ぶか yoichiwo7 18/06/16
19/06/05
1538
563
18 CORSまとめ tomoyukilabs 16/02/01
17/11/30
1520
373
19 MacにNode.jsをインストール kyosuke5_20 16/11/15
20/02/16
712
467
20 JavaScriptの配列の使い方まとめ。要素の追加,結合,取得,削除。 takeharu 15/11/28
16/06/28
1335
350
21 2018年の最先端フロントエンドエンジニアになろう rana_kualu 18/04/02
19/05/12
1794
332
22 4歳娘「パパ、具体的な名前をつけないで?」 Yametaro 20/03/18
20/03/31
1532
1532
23 もう保守されない画面遷移図は嫌なので、UI Flow図を簡単にマークダウンぽく書くエディタ作った hirokidaichi 16/04/02
18/12/25
4809
269
24 ESLint 最初の一歩 mysticatea 15/10/21
19/07/08
1195
356
25 <script> タグに async / defer を付けた場合のタイミング phanect 17/08/05
19/02/23
870
402
26 Facebook製のJavaScriptテストツール「Jest」の逆引き使用例 chimame 16/10/13
18/11/07
966
365
27 ワイの正規表現入門 Yametaro 20/03/01
20/03/04
1474
1474
28 vue.js + typescript = vue.ts ことはじめ nrslib 18/10/08
19/11/11
992
562
29 JavaScriptを読んでて「なにこれ!?」と思うけれど調べられない記法8選。 ukiuni@github 15/04/17
15/04/22
2895
157
30 2017年のフロントエンドエンジニアならこの程度は知ってて当然だよな? rana_kualu 17/02/14
19/03/07
2790
189
31 JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる YoshikiNakamura 16/01/27
18/10/25
947
301
32 【保存版】Webフロントエンド基礎力(初心者向け) teradonburi 19/11/04
20/03/15
1578
1578
33 【動画付き】 draw.io 使い方まとめ 〜エンジニアでなくても使えるTips集〜 G-awa 20/02/09
20/02/09
1397
1397
34 フロントエンドのコンポーネント設計に立ち向かう seya 18/04/01
19/04/21
1370
445
35 関数型プログラミングはまず考え方から理解しよう stkdev 16/04/24
16/05/08
2110
300
36 非同期処理ってどういうこと?JavaScriptで一から学ぶ kiyodori 15/12/19
15/12/19
1048
301
37 【Laravel 6 & PHP 7.4 対応】Vue + Vue Router + Vuex + Laravel チュートリアル(全16回)を書きました。 MasahiroHarada 19/01/13
20/01/19
1809
411
38 2018年のフロントエンドエンジニアならこの程度は知ってて当然だよな? rana_kualu 18/02/28
18/05/16
2004
285
39 Ubuntuに最新のNode.jsを難なくインストールする seibe 15/12/10
19/02/10
959
299
40 Vue.jsで作成された、ちょっと面白くて役立ちそうなサービス s-yoshiki 20/01/28
20/01/31
1470
1470
41 iPadでプログラミングしてる人、今まで馬鹿にしててすみませんでしたァァァァ!!!! Mahito6 19/03/04
19/07/18
1924
385
42 JavaScriptが辿った変遷 naoki_mochizuki 16/09/19
19/01/17
1107
339
43 なぜ仮想DOMという概念が俺達の魂を震えさせるのか mizchi 14/11/30
14/12/02
2434
251
44 Vue.js + Vuexでデータが循環する全体像を図解してみた m_mitsuhide 18/07/30
19/12/05
1009
392
45 Prettier 入門 ~ESLintとの違いを理解して併用する~ soarflat 18/02/21
18/07/23
801
330
46 ライブラリを使わない素のJavaScriptでDOM操作 kouh 15/05/28
18/04/26
1218
180
47 Webpackってどんなもの? kamykn 16/09/17
16/09/19
882
259
48 Node.js を5分で大雑把に理解する hshimo 13/11/24
17/07/04
1605
172
49 2019年版Vue.jsを使ってる人には必ず知っていてほしいVue.jsの武器とドキュメントに書かれていないコンポーネントやメンテナンスの際に役立つTips kahirokunn 19/03/01
20/01/08
1400
428
50 お前らのReactは遅い teradonburi 18/12/01
20/02/15
857
417
51 2019年版 最先端のフロントエンド開発者になるために学ぶべきこと baby-degu 19/07/21
19/11/14
1533
1533
52 Chrome拡張の開発方法まとめ その1:概念編 k7a 16/03/13
16/03/15
938
193
53 Vue開発者のためのVue.jsベストプラクティス集15選 mtoyopet 20/01/29
20/02/25
1262
1262
54 JavaScript の テンプレートリテラル を極める! kura07 15/08/07
18/09/17
733
221
55 TypeScriptのInterfaceとTypeの比較 tkrkt 17/05/26
19/04/16
536
333
56 5分で理解する React.js tomzoh 15/09/02
18/12/14
1646
181
57 新人にドヤ顔で説明できるか、今風フロントエンド開発ハンズオン(Git/Node.js/ES6/webpack4/Babel7) riversun 18/11/11
19/09/04
1856
205
58 ブラウザレンダリング入門〜知ることで見える世界〜 codemafia0000 19/03/16
19/03/27
1698
362
59 ゼロからはじめるExpress + Node.jsを使ったアプリ開発 nkjm 15/12/29
16/02/13
827
206
60 JavaScript の this を理解する多分一番分かりやすい説明 takkyun 17/07/29
18/10/14
801
267
61 【2019年4月版】JavaScriptのconsoleがすごいことになってた。 koinori 19/04/02
19/04/11
2311
334
62 Vue.jsの書き方実例集(随時追加)※逆引きリファレンス的な Yorinton 17/09/02
19/01/26
525
301
63 JavaScript で forEach を使うのは最終手段 diescake 18/12/01
18/12/06
579
412
64 JavaScriptの「this」は「4種類」?? takeharu 13/04/09
15/12/07
1973
145
65 ようこそ!Electron入門 umamichi 16/12/28
19/11/22
463
313
66 JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 suin 20/03/22
20/03/23
1159
1159
67 削除済(ID:c7fad62a12cc2809b507) kenju 15/06/25
16/10/25
2840
164
68 Storybookがなぜ必要か?(Vue.js編) masaakikunsan 17/12/23
19/02/26
602
269
69 Promiseについて0から勉強してみた toshihirock 16/04/09
16/04/17
652
176
70 Reactベース静的サイトジェネレータGatsbyの真の力をお見せします uehaj 18/12/21
19/08/23
540
372
71 react-router@v4を使ってみよう:シンプルなtutorial muijp 17/06/27
19/02/16
575
229
72 TypeScriptをプロダクト開発に使う上でのベストプラクティスと心得 jagaapple 20/02/04
20/03/17
1085
1085
73 ワイ「何で子コンポーネントに状態を持たせたらあかんの?」 Yametaro 19/11/21
19/12/27
904
904
74 Service Workerの基本とそれを使ってできること y_fujieda 16/08/31
16/08/31
764
159
75 JavaScript アロー関数を説明するよ may88seiji 17/04/16
19/08/26
452
238
76 コードレビュー虎の巻 teradonburi 19/11/19
19/12/24
1238
1238
77 ちゃんと使い分けてる? dependenciesいろいろ。 cognitom 16/05/09
16/05/09
849
167
78 yarnチートシート morrr 17/05/25
17/06/14
573
212
79 ラーメンで理解するasync/await 7tsuno 19/12/18
19/12/23
1135
1135
80 ?React 16.8: 正式版となったReact Hooksを今さら総ざらいする uhyo 19/02/03
20/01/19
735
397
81 Fluxとはなんなのか knhr__ 17/01/31
19/05/26
512
227
82 Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた naoki85 17/09/14
19/07/07
597
193
83 【詳解】モテたいVimmer必見 快適にコーディングするためのvimrc解説 ahiruman5 16/10/10
17/01/07
1706
164
84 Electronでアプリケーションを作ってみよう Quramy 15/05/06
19/02/14
2411
114
85 Webパフォーマンス虎の巻 usagi-f 18/10/24
18/10/24
1840
101
86 図で理解するJavaScriptのプロトタイプチェーン howdy39 16/10/02
18/01/09
1307
164
87 [axios] axios の導入と簡単な使い方 ksh-fthr 17/09/13
19/07/15
416
244
88 JavaScriptの「&&」「||」について盛大に勘違いをしていた件 Imamotty 15/09/11
15/09/11
1076
157
89 npm とか bower とか一体何なんだよ!Javascript 界隈の文脈を理解しよう megane42 15/09/23
15/09/30
2546
99
90 var/let/constの使い分けのメモ masarufuruya 17/06/01
19/02/26
422
234
91 もしものために,香川県からのアクセスを避ける ni__no13 20/01/22
20/03/18
963
963
92 Vue.js初心者向け:Vue.jsとaxiosでJsonを取得してコンポーネントに反映するメモ sygnas 17/04/06
18/07/17
583
177
93 30分で出来る、JavaScript (Electron) でデスクトップアプリを作って配布するまで nyanchu 15/07/18
19/08/08
2606
155
94 そろそろ真面目に、HTMLで帳票を描く話をしようか cognitom 15/10/05
15/10/07
2240
150
95 JavaScriptのpreventDefault()って難しくない?preventDefault()を使うための前提知識 tochiji 18/08/19
19/12/10
371
325
96 この TypeScript が Hello, world! のくせに慎重すぎる matzkoh 19/12/02
20/01/28
464
464
97 あなたがnpm installをしてはいけない時 jigengineer 19/08/09
19/08/14
731
731
98 JavaScript中級者への道【5. コールバック関数】 matsuby 15/12/27
18/10/11
534
155
99 TypeScriptを使ってReactのチュートリアルを進めると捗るかなと思った(実際捗る) m0a 16/03/15
20/03/22
416
189
100 WebAssemblyとは?〜実際にC言語をブラウザで動かす〜【2019年6月版】 umamichi 17/04/12
19/12/11
465
199

  1. 1行目が総数。2行目が直近1年。 

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

【プログラミング学習5日目】callback関数について勉強してみた

はじめに

独学プログラミング学習の5日目

忘れっぽいので備忘録代わりに残しておこうと思う
※人に見せる前提ではないよ

目標

  • 簡単なページをサクっと作れるようになる
  • Web上に自分のポートフォリオを公開
  • アウトプットのスキルを身につける

callback関数ってなに?

コールバック(英: Callback)とは、プログラミングにおいて、他のコードの引数として渡されるサブルーチンである。これにより、低レベルの抽象化層が高レベルの層で定義されたサブルーチン(または関数)を呼び出せるようになる。
※wikipedia調べ

つまり,引数として渡される関数のことだよ

const callback = () => {
  console.log('callback関数');
}

const call = (fuc) => {
  console.log('callback関数を呼び出す');
  fuc();
}
call(callback);

こんな感じで,関数を引数に渡して呼び出せるよ
今回は自作関数の引数に渡したけど,setTimeoutみたいに標準関数の引数として渡すこともあるみたい

非同期処理でよく使われるらしいからcallbackと一緒に非同期についても調べてみたよ

非同期処理は,他の人に仕事を頼んでる間に自分の仕事をガーっと進められる技術らしいよ
具体的に言うと,API叩いてレスポンス返ってくるまでの間JavaScriptの処理は止まらないで先に進んでいくらしい
インタプリタって上から1行ずつ実行されるんじゃないの?って疑問になるけど,そういうものだと思って覚えることにしたよ・・・・

深く考えすぎてここで足を止めるのは良くない気がするからcallbackは関数を引数として渡すということ,非同期は他の人に声かけたけど返事待たずに次の行動する子って覚えておくよ

おわり

不完全燃焼だけど,今日は合間の時間も取れなかったのでここまで
全然理解せずに次に進むのもあれなので,明日は箸休めでWSLの環境構築でもやってみるよ

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

意外と難しい?Vuetifyのv-slot=activator="{ on }"について解説!

こんにちは。ゲームを作って学ぶプログラミング学習サービスプロアカを開発しているアカネヤです。

一部のVuetifyのコンポーネントでは、Vueのスロットの機能を利用します。
これが意外と複雑ですので、解説します。

内容としては、Vueの名前付きスロットスコープ付きスロットになります。

例えば、v-menuコンポーネントの使い方は下のようになります。

<v-menu>
  <template v-slot:activator="{ on }">
    <v-btn v-on="on">
      メニューを開く
    </v-btn>
  </template>
  <v-list>
    <v-list-item>
      メニューの項目1
    </v-list-item>
  </v-list>
</v-menu>

v-on="on"を指定したHTML要素をクリックすると、v-listの部分が表示されます。

ここではVueの名前付きスロット機能と、スコープ付きスロットの両方を使用しています。

このコードの中で、普段あまり使わない文法は

<template v-slot:activator="{ on }">

の部分だと思います。

これは、この<template>activatorというnameに対するスロットであることを指定しています。
また、スロットプロパティとして、デフォルトスロットを表示するためのイベントハンドラを受け取っています。
そのイベントハンドラは、スロットプロパティのうちonというキーで<v-menu>コンポーネントから渡されるため

<template v-slot:activator="{ on }">

となるのです。

詳しく知りたい方は、スロットについてのVue公式ドキュメントを全部読むことをおすすめします。
https://jp.vuejs.org/v2/guide/components-slots.html

終わりに

私が開発しているゲームを作って学ぶプログラミング学習サービスプロアカでは無料体験も行っています。ぜひご覧下さい。

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

Kinx ライブラリ - Math

Math

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。

今回は Math です。

Math は数値演算ライブラリ。同じメソッドが Integer、Double でも特殊メソッドとして使えるので、あえて Math オブジェクトを通して使う必要はない。例えば、以下のように使用できる。

var a = 2.pow(10);     // Math.pow(2, 10)   => 1024
var b = 2.0.pow(10);   // Math.pow(2.0, 10) => 1024
var c = (-10).abs();   // Math.abs(-10)     => 10

単項マイナス(-)は関数呼び出しより優先順位が低いため、カッコで括る必要があることに注意。何気に random() も数値に対して使えるが、レシーバーの値に意味はない、というのは知っていても良いし、まぁ知らなくても良い。

var a = 1000.random(); // 1000 に意味はない
var b = 10.0.random(); // 10.0 に意味はない
var c = Math.random(); // Math には意味がある

特殊メソッド、および特殊オブジェクトに関する詳細は Kinx ライブラリ - String を参照してください。

Math

Math オブジェクトのメソッド一覧は以下の通り。

メソッド 意味
Math.sin(dbl) サイン。Math.sin(x) は、$\sin x$ を求める。
Math.cos(dbl) コサイン。Math.cos(x) は、$\cos x$ を求める。
Math.tan(dbl) タンジェント。Math.tan(x) は、$\tan x$ を求める。
Math.asin(dbl) アークサイン。Math.asin(x) は、$\sin θ=x$ となるような $θ$ を求める。
Math.acos(dbl) アークコサイン。Math.acos(x) は、$\cos θ=x$ となるような $θ$ を求める。
Math.atan(dbl) アークタンジェント。Math.atan(x) は、$\tan θ=x$ となるような $θ$ を求める。
Math.atan2(dbl, dbl) アークタンジェント2。Math.atan2(x,y) は、$xy$ 直交座標における $(x,y)$ の偏角を求める。
Math.sinh(dbl) ハイパボリックサイン。Math.sinh(x) は、$\sinh x$ を求める。
Math.cosh(dbl) ハイパボリックコサイン。Math.cosh(x) は、$\cosh x$ を求める。
Math.tanh(dbl) ハイパボリックタンジェント。Math.tanh(x) は、$\tanh x$ を求める。
Math.exp(dbl) Math.exp(x) は $e^x$ を返す。$e$ は、自然対数の底であるネイピア数(オイラー数)。
Math.ldexp(dbl, int) Math.ldexp(x,y) は $x \times 2^y$ を返す。
Math.log(dbl) Math.log(x) は $\log_e x$ を返す。
Math.log10(dbl) Math.log10(x) は $\log_{10} x$ を返す。
Math.pow(dbl, dbl) Math.pow(x,y) は $x^y$ を返す。
Math.sqrt(dbl) Math.sqrt(x) は $\sqrt x$ を返す。
Math.ceil(dbl) Math.ceil(x) は $x$ 以上の最小の整数値を Double で返す。
Math.floor(dbl) Math.floor(x) は $x$ 以下の最大の整数値を Double で返す。
Math.fmod(dbl, dbl) Math.fmod(x,y) は $x \div y$ の浮動小数点余剰を返す。結果は $x$ と同じ符号で $y$ 以下の絶対値となる。
Math.abs(dbl) Math.abs(x) は $x$ の絶対値を Double で返す。
Math.random() Math.random() は $0 \leq r < 1$ となる乱数を返す。

おわりに

最初にも書いたが、同じメソッドが Integer、Double に直接作用するので、Math オブジェクト経由であえて使う必要はないかな、と。

ではまた次回。

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

岡山県版新型コロナウイルス対策サイトを開発・運用している話

ogp.png

はじめに

岡山県版新型コロナウイルス対策サイト(非公式)の運用のルサカです。
今回は岡山県版新型コロナウイルス対策サイトを開発・運用の過程についてQiitaに投稿しました。

開発開始

岡山県版作るのに東京都のコロナウイルス対策サイトGitHubのリポジトリを活用し作成しました。以下のようにふじしゃんこと藤原出帆さん(Twitter)と役割を分担し開発をしました。
ふじしゃん → 東京都版の部分を岡山仕様にするなどなど
ルサカ → ロゴやOGP画像などを独自の岡山仕様にするなど
その結果、約18時間で開発を終え、公開することができました。

さくらインターネットさんとの出会い

もともとは、Netlifyで公開していましたが、転送量の上限が100GBと万が一アクセスが増えた場合対応ができなくなるため、さくらインターネットさんが新型コロナウイルス関連で提供してくれているサーバーを利用することにしました。本当にさくらインターネットさんありがとうございます!!!
詳細↓
https://www.sakura.ad.jp/information/pressreleases/2020/03/23/1968203129/

オープンソースで開発へ

開発開始からしばらくの間はふじしゃんの僕のみでGitHubのプライベートリポジトリにて開発をしていましたが、岡山県版新型コロナウイルス対策サイトをよりよい物にし、多くの方に活用していただくためにオープンソースで開発することにしました。

最後に

岡山県版新型コロナウイルス対策サイトの運営の誰がいつ新型コロナウイルスに感染するかもわからないため特定の人に依存することのない運用を目指しています。
さらに、岡山県版新型コロナウイルスをより良いものにするためには沢山の人の力が必要です。

岡山県版新型コロナウイルス対策サイトに力を貸してください!!!

岡山県版新型コロナウイルス対策サイト↓
https://okayama.stopcovid19.jp/
GitHubリポジトリ↓
https://github.com/stopcovid19-okayama/covid19
Twitter↓
https://twitter.com/covid19_okayama
Slack↓
https://join.slack.com/t/okayama-stopcovid19/shared_invite/zt-d86r1ajq-ba1w0w71DGcX_fed6lufog

よろしくお願いします!!!

リンク

[東京都新型コロナウイルス対策サイト]
https://stopcovid19.metro.tokyo.lg.jp/
[さくらクラウド]
https://cloud.sakura.ad.jp/

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

github jsのアップロードエラー

github から「index.html」「style.css」「js」をアップロードしようとしましたが、
「js」が検証のコンソールでチェックすると not::ERRABORTED 404 となります。

エラーを調べたら、githubに「js」ファイルが無いとのことでした。

今回、「js」フォルダーはhtmlのbodyタグの中に書きましたので、
headタグの中には何も「js」用のリンクは書きませんでした。

「index.html」「style.css」はきちんと反映されていました。

「js」をアップロードするのは初めてでして、何がエラーに引っかかっているのかわかりません。

ご教示頂けたら幸いです。
よろしくお願い致します。

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>javascript-type</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>


<script src="js/main.js"></script>
</body>

スクリーンショット (266).png

スクリーンショット (267).png

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

【LIFF入門?】LIFFでLINE Offical Account(旧LINE@)上に予約フォームを作成する

はじめに

こんな感じの作ります

canova.PNGcanova.PNGcanova.PNG

使用技術

  • LIFF (LINE Front-end Framework)
  • Go
    • Goの勉強したかったのでGoにしましたが、バックエンドは何でもいいです
  • JavaScript, jQuery
  • Heroku
  • Git

ソースコードはこちら(GitHub)

LINE公式アカウント作成

こちらの公式HPを参考に作成します。

リッチメニュー設定

リッチメニュー用の画像を作成する

チャット画面下に表示されるバナーのことをリッチメニューというようです。
まずはリッチメニューに設定する画像をCanovaを使って作成します。
Canovaは素材が豊富で無料プランでもいい感じの画像が作れるので便利です。
canova.PNG

リッチメニューを設定する

LINE Offical Account Manager上からいい感じに設定します。(適当)
PCからのみ設定することができ、スマホからは設定できないようです。
リンクは一旦適当なリンクを設定しておきます。
LIFFアプリを作成後にそのURLを設定します。

rich1.PNG
rich2.PNG

LIFFアプリ作成

チャネル作成

こちらの公式HPを参考にして、LINE Developersでチャネルを作成します。
LIFFを使うために基本的な情報を登録します。

コーディング

ディレクトリ構成

任意のディレクトリに作業用ディレクトリを以下の構成で作成します。
Go以外で試す場合は、index.htmlstatic/があれば動作すると思います。

reservation/
|- static/
   |- liff.js
   |- index.js
|- vendor/
   |- vendor.json // Heroku上でGoを動かすために必要
|- index.html
|- main.go

ソースコードは冒頭のGitHubを参照ください。

ハマりポイント

PORTの指定はport := os.Getenv("PORT")のように環境変数から取得します。
Herokuで実行する際はHeroku指定のPORT番号でListenする必要があるためです。

main.go
func main() {
    port := os.Getenv("PORT")
    fmt.Printf("Starting server at Port %s", port)
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static/"))))
    http.HandleFunc("/", handler)
    http.ListenAndServe(fmt.Sprintf(":%s", port), nil)
}

Herokuにデプロイ

Herokuに関する説明は省略します。
HerokuでNew Appを作成した後に以下のコマンドを実行します。
HerokuのDeploy画面に表示されているコマンドのままです。

$ heroku login
$ cd reservation/
$ git init
$ heroku git:remote -a (自分のApp名)
$ git add .
$ git commit -am "make it better"
$ git push heroku master

デプロイ後にHerokuのURLにアクセスしてフォームが表示されれば成功です。

LIFFアプリをチャネルに追加

こちらの公式HPを参考にして、LIFFアプリがLINEやブラウザ上で動作できるようにするために、LIFFアプリをチャネルに追加します。
エンドポイントURLにはHerokuのURLを設定します。

動作確認

LINE Offical Account ManagerのリッチメニューのリンクをLIFFの設定画面に表示されているLIFF URLをに変更します。
liffurl.PNG

LINE公式アカウントを自分のLINEの友だちに追加して試してみます。
冒頭のデモ画像のようになれば成功です。

おまけ

ローカルのサーバで動作確認をするにはngrokがとても便利です。
参考リンクを貼っておきます。

参考

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

reCAPTCHA v3 × Laravel

Laravel5.7にreCAPTCHAv3を導入する手順

v3導入にあたって、

anhskohbo/no-captcha
ARCANEDEV/noCAPTCHA
どちらのライブラリを使えば良いの??問題

(結論としては今回はARCANEDEV/noCAPTCHA
になります。これはLaravelの4.2~7.xまでサポートしているようなので、今回は5.7で検証していますが、他のバージョンでも同様にいけるはずです。)


reCAPTCHAのトークンは二分間しか持たない問題

Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action.
Google reCAPTCHA

上記2点に主に焦点を当てて導入手順を述べていきたいと思います。

目次

  1. reCAPTCHAとは?
  2. サイトキー(SITEKEY)とシークレットキー(SECRETKEY)の取得
  3. composerでライブラリをインストール
  4. フロントエンド
  5. バックエンド

reCAPTCHAとは?

Google reCAPTCHA
人間になりすましてBOTが操作していないかチェックしてくれる,Googleのサービス。
「私はロボットではありません」のあれです。

このreCAPTCHA
v1,v2 とあるなかで 2018/10/29からv3になっています。
v2とv3の違いについてはググるとすぐにわかるのでここでは省きますが、
ユーザーがチェックを入れる必要がなくなったという事実はv3導入において一つのポイントになります。

サイトキー(SITEKEY)とシークレットキー(SECRETKEY)の取得

Google reCAPTCHA Developer's Guide
↑ここに大まかな実装方法は書いてあります

サイトキー(SITEKEY)とシークレットキー(SECRETKEY)の取得はこちらから
↑ここにreCAPTCHAを適用したいサイトを載せます。
主な各項目について
ラベル :
ここはサイトに対するニックネーム的扱いです。(自分がわかればなんでも良いです。)
reCAPTCHAタイプ :
今回はv3を利用するのでv3にチェックを入れます。
ドメイン :
普通にドメインを登録すれば良いのですが、開発環境で確認したい場合はlocalhostではなく、
127.0.0.1

で登録をして進めてください。

これで登録が完了すると
・サイトキー(SITEKEY)
・シークレットキー(SECRETKEY)
が発行されます。
あとはライブラリと組み合わせて
実装を進めます。

composerでライブラリのインストール

ARCANEDEV/noCAPTCHA
をcomposerでインストールします。
Laravelのバージョンに応じてnoCAPTCHAのインストールのバージョンを確認してください
今回はLaravel5.7なので

composer require arcanedev/no-captcha:8.x

インストールしたら

php artisan vendor:publish --provider="Arcanedev\NoCaptcha\NoCaptchaServiceProvider"

でno-captchaのconfigファイルを呼び出して、
versionを示す部分がv3になっているか確認をします。(私はデフォルトでv3になっておりました。)

その後、先ほど所得した
SITEKEYとSECRETKEYを
.envファイルに

NOCAPTCHA_SECRET=your-secret-key
NOCAPTCHA_SITEKEY=your-site-key

と記述してセット

フロントエンド

Google reCaptcha フロントエンド
↑公式の参照ページはこちら
公式にはざくっとこんな感じのことが記述されています。

  1. Load the JavaScript API with your sitekey.
  2. Call grecaptcha.execute on an action or when the page loads.
  3. Send the token immediately to your backend with the request to verify.

1.まずJavaScript APIを読み込んでください。
2.イベント発火かあるいは、ページがロードされる際、"grecaptcha.execute"を呼び出すよう記述してください
3.すみやかにバックエンドにrequestと一緒にトークンを送り込んでください。

なんとなくここを意識しながらフロントエンドの実装にうつります。

form.blade.php
<form id="form" action="{{ route('post')}}" method="POST">


    <button type="subbmit" id="form_btn">送信</button>
</form>

今回はNoCaptchaを使った時の書き方を以下に記述します。

reCAPTCHAを適用したいformの中に

form.blade.php
<form id="form" action="{{ route('post')}}" method="POST">

    {!! no_captcha()->input() !!}

    <button type="subbmit" id="form_btn">送信</button>
</form>

と記述します。
これは以下とまったく同じ意味です。

<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">

あとで、javascriptこのinputタグに対して
valueにトークンをセットしてあげます。

そして</body>付近に

form.blade.php
{!! no_captcha()->script() !!} 

これは以下と同じ意味になります。

<script src="https://www.google.com/recaptcha/api.js?hl=jp&amp;render=SITE_KEY"></script>

v3のreCAPTCHAのイメージと、SITE_KEYをAPIに投げることで、当サイトがreCAPTCHAの保護対象かどうかを判断しています。

そして今回のポイントの一つ
reCAPTCHAのトークンは二分間しか持たない問題

Note: reCAPTCHA tokens expire after two minutes. If you're protecting an action with reCAPTCHA, make sure to call execute when the user takes the action.

ここをクリアするために
少しjavascriptで工夫を懲らします。

$(function () {
    $('#form_btn').on('click',function (e){
        if(confirm('本当に送信してもよろしいですか?')){
            e.preventDefault();
            grecaptcha.ready(function() {
                grecaptcha.execute('取得したサイトキー', {action: 'login'}).then(function(token) {
                    $('#g-recaptcha-response').val(token);
                    //ここでトークンを渡す。
                    $('#form').submit();
                });
            });    
        }
    });
});

バックエンド

Google Recapcha バリデーション
↑ここにバリデーションの方法など書いてます。
取得したSECRETKEYを用いて色々する必要があるのですが、
このあたりは
ARCANEDEV/noCAPTCHA
がとても楽にしてくれています。

私たちがやるべきことはコントローラでValidatorを利用してバリデーションルールを追加すれば良いだけ。

FormController.php
        $requests = $request->all();
        $rules = [
                // other 他のバリデーションルール
            'g-recaptcha-response' => ['required',new CaptchaRule] //ここではrequiredとcaptchaを設定しております。
        ];
        $messages = [
             // 他にも
            'g-recaptcha-response.captcha' => 'reCaptchaによってうまく認証されませんでした'
        ];
        $validator = Validator::make($requests, $rules, $messages)->validate();

・requiredはトークンがセットされているかどうか
・captchaはトークンが有効かどうか

これで実装完了です。

ちなみに…

anhskohbo/no-captcha
でも試したのですが、こちらでは私ではうまくできませんでした。
・READMEに、v3のサポートが明記されない
・インストールしてみましたが、参照URLがv2のものになっていた

もしかしたらconfigファイルをいじったりしたらうまくできるのかもしれませんが、それはまたの機会に。
PHP用にGoogleからもライブラリが出ているようなので今度はそちらでも試してみたいところです。

Qiita初投稿です。
記述に不備があればご指摘くださいますようよろしくお願いいたします。

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

JSで言語に応じて対応するページに振り分ける方法。ただし注意点あり・・・

多言語サイトで、言語に応じてページを振り分けたい。そのようなサイトを作る機会があったので、今回はJSでブラウザの言語設定を取得して振り分ける方法を紹介したいと思います。

リダイレクトさせる、その前に

よし、これからリダイレクトさせるぞ!と意気込んでいるかと思いますが、ひとつ悲しいお知らせがあります。Googleはリダイレクトは推奨していません。なぜならクローラが正しくページを見つけられないからです。

ユーザーの言語設定に応じて、動的にコンテンツを変更する方法や、ユーザーをリダイレクトする方法を採用する場合は、
コンテンツのすべてのパターンを Google が見つけてクロールするとは限らないことにご注意ください。

他にもIPアドレスで判断して振り分ける方法もおすすめしていません。なるべくなら、リダイレクトなど動的な振り分けはしないほうがよいです。
多地域、多言語のサイトの管理

ブラウザの言語設定を取得してページを振り分ける方法

具体的に方法をみていきたいと思います。今回私はざっくり以下のような方法をとりました。

  • ブラウザの言語設定を取得
  • sessionStorageで初回か判定
  • switchで飛ばしたいページに飛ばす

完成形

先に完成形です。

ridirect.js
    /**
     * 言語設定に応じてリダイレクト
     *
     * @returns {undefined}
     */
    function ridirectURL() => {
      const baseUrl = 'https://example.com/';
      const browserLang = (window.navigator.languages && window.navigator.languages[0]) ||
        window.navigator.language ||
        window.navigator.userLanguage ||
        window.navigator.browserLanguage;

      // console.log(browserLang); ←コンソールにブラウザの言語設定を表示させる

      switch(browserLang) {
        // 英語
        case 'en':
        case 'en-US':
          location.href = `${baseUrl}en`;
          break;
        // 簡体字
        case 'zh-CN':
        case 'zh-Hans':
        case 'zh-SG':
          location.href = `${baseUrl}cs/`;
          break;
        // 繁体字
        case 'zh-Hant':
        case 'zh-MO':
        case 'zh-HK':
        case 'zh-TW':
          location.href = `${baseUrl}ct/`;
          break;
        default:
          break;
      }
    };

    /**
     * セッション初回の判定
     *
     * @returns {undefined}
     */
    function firstOrNot() {
      // sessionStorageに 'access' というアイテムがなかったら
      if(!sessionStorage.getItem('access')){
        sessionStorage.setItem('access', 0); // sessionStorageにアイテムをセット
        ridirectURL(); // 前述のリダイレクト処理を実行
      }
    };

ブラウザの言語設定を取得

javascriptでブラウザの言語設定を取得するの記事を参考にブラウザの言語設定を取得します。

各言語はディレクトリを分けて作っています。
基本は日本語ページ、それ以外に対応する言語があれば、そのページに振り分けます。計4種類。

// 日本語
https://example.com/
// 英語
https://example.com/en/
// 中国語 簡体字
https://example.com/cn/
// 中国語 繁体字
https://example.com/ct/

言語コードについて

取得される言語コードですが、 ja のように言語コードだけの場合と、 ja-JPと言語コードと国コードがハイフンつなぎになっている場合もあります。

属性には単一の「言語タグ」を Tags for Identifying Languages (BCP47) で定義された書式で持ちます。

MDN:lang
Tags for Identifying Languages BCP47

詳しくは↑を参照ですが、なかなか細かく定義されていますので、興味がある人は目を通してみてください。

    /**
     * 言語設定に応じてリダイレクト
     *
     * @returns {undefined}
     */
    function ridirectURL() => {
      const baseUrl = 'https://example.com/';
      const browserLang = (window.navigator.languages && window.navigator.languages[0]) ||
        window.navigator.language ||
        window.navigator.userLanguage ||
        window.navigator.browserLanguage;

      switch(browserLang) {
        // 英語
        case 'en':
        case 'en-US': // アメリカ英語
          location.href = `${baseUrl}en/`;
          break;
        // 簡体字
        case 'zh-CN': // 中国語
        case 'zh-Hans': // 簡体字
        case 'zh-SG': // シンガポール
          location.href = `${baseUrl}cs/`;
          break;
        // 繁体字
        case 'zh-Hant': // 繁体字
        case 'zh-MO': // マカオ
        case 'zh-HK': // 香港
        case 'zh-TW': // 台湾
          location.href = `${baseUrl}ct/`;
          break;
        default:
          break;
      }
    };

ちょっと補足
zh-MO(中華人民共和国マカオ特別行政区) ですが、端末によっては簡体字と繁体字の両方設定できるものもありました。今回は繁体字に振り分けることにしました。このように、言語設定に応じて細かく振り分けるとなるとなかなか大変です。

また、上の例では全てのブラウザ言語設定に対して、対応したページに振り分けられないかもしれません。言語コードの条件判定は適宜設定してください。

sessionStorageで初回か判定

WebStorageAPIを使って初回アクセス時だけLoadingを表示する の記事を参考にsessionStorageを使い、セッションの初回かどうかを判定。2回目以降なら、なにもさせないようにします。

    /**
     * セッション初回の判定
     *
     * @returns {undefined}
     */
    function firstOrNot() {
      // sessionStorageに 'access' というアイテムがなかったら
      if(!sessionStorage.getItem('access')){
        sessionStorage.setItem('access', 0); // sessionStorageにアイテムをセット
        ridirectURL(); // 前述のリダイレクト処理を実行
      }
    };

ぼやき
もっとわかりやすい関数名にしたい・・・

まとめ

というわけでJSでブラウザの言語設定を取得して、対応する言語ページに振り分ける処理を紹介しました。最初の方にいったとおり、動的に言語ページを切り替えるのはおすすめできません。それでもどうしてもというときに参考にしてみてください。

また多言語サイトを作る際はhreflangの設定も忘れず行いましょう。
ページのローカライズ版について Google に知らせる


参考
WHATWG Living Standard: langおよびxml:lang属性
言語コード
window.navigator.language
地球の歩き方: マカオ
地元マカオ人に聞いた!マカオで食べるべきおすすめマカオグルメ8選

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

Javascript初心者のためのArray.prototype反復メソッド使い分け

Array.prototype反復メソッドって何?

これです
反復メソッド - Array.prototype - MDN

要するに、配列の各要素に対してループ処理をして何かうまいことやるためのメソッドたち。
下記のメソッドは全て上記ページにリンクがあるので、詳しいことの確認は上記ページからどうぞ。

それぞれこう使おう

配列の中からいくつかは採用して、いくつかは捨てたい

? Array.prototype.filter()
コールバックの中で、採用したい要素が満たす条件をBooleanで指定します。
ふつう、入力する配列と出力する配列の要素数が異なりそうなときに使いますね。

配列の中から一つだけ採用したい

? Array.prototype.find()
filterの返り値が一つになったバージョンとも言えます。
複数ある場合、配列の中で最初に見つかった要素だけを返します。

余談

find()は要素の存在を確かめたい場合にも使えますが、その用途だとArray.prototype.includes()の方が適任です。

配列の各要素を使って処理したい

? Array.prototype.forEach()
返り値はありません。処理の結果が欲しい場合は別のメソッドを。
各要素に処理した結果を保持するならmapを一番よく使うと思う。

配列の各要素に何か処理をして、新しい配列にしたい

? Array.prototype.map()
コールバックの中で、各要素に対する処理を記述します。
(数値の)配列の各要素を全て2倍した配列が欲しいなんてときに使います。

配列の各要素を合計とかしたい

? Array.prototype.reduce()
返り値は一つの値になります。
取得したい結果の初期値を与えておいて、ループの中で①各要素に何か処理する、②結果に処理済みの値を作用させる、という処理を延々続けるイメージです。

どれか一つでも該当するか調べたい

? Array.prototype.some()
コールバックの中に、各要素のうちどれか一つでも該当してほしい条件を指定します。
Array.prototype.includes()とは違って、特定の要素が存在することの確認だけでなく(数値の)配列の中にどれか一つでも偶数があるか?みたいな使い方ができます。

全ての要素が該当するか調べたい

? Array.prototype.every()
someが全要素になったパターンとも言えます。
コールバックの中に、各要素の全てにおいて該当してほしい条件を指定します。

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

検索機能で検索boxの下に候補を出す方法

0 はじめに

 今回は以下の写真のように、ユーザーが検索する時の助けになるように、boxの下に候補を出す方法を記述します。
 もっといい方法があるとは思いますが、今の私の理解力と技術ではこれがベストです。

バージョンです

 version ruby 2.5.1p57
          Rails 5.2.4.1

1 実装の流れ

a) controllerで候補に出すデータをインスタンス変数に入れる

b) viewにinputタグ(type:hidden)を記述。その中に1の変数を記述

c) 検索boxに入力されるたびに発火させ処理させる

d) 検索boxに入力された値をもとに正規表現を作成

e) インスタンス変数の値をeachで取り出して正規表現とマッチするか調べる

f) マッチしたものだけ関数を使って要素を作り、検索boxにappendする

2 コード・解説

a) controllerで候補に出すデータをインスタンス変数に入れる

jsサイドにデータを渡すためのコードです。
今回は「new.html.haml」 「edit.html.haml」以外に検索機能を実装します。productsコントローラーにbeforeアクションを設定しました。@wordに商品名を入れ、@id_boxにproduct.idを入れます。

products_controller.rb
class ProductsController < ApplicationController
 before_action :set_product_name, except: [:new, :edit]
 ---省略---
 def set_product_name
   @product_for_search = Product.all
   @wordbox = []
   @id_box = []
   @product_for_search.each do |product|
     @id_box << product.id
   @word_box << product.name
   end
  end
end

b) viewにinputタグ(type:hidden)を記述。その中に1の変数を記述

 jsが発火した時にここから商品名及び、商品idを取得できるようにします。
 一番下の#result-wordの下にliで候補を表示します

index.html.haml
= form_with(url: products_searches_path, local: true, method: :get, class: "search-form") do |form|
 .search-group
  = form.text_field :keyword, placeholder: "商品を検索する", class: "main-header__search-box", id: "_products_searches_keyword"
  = form.label :keyword, for: "search-btn", class: "search-label" do
   = form.submit "検索", class: "search-btn", id: "search-btn", style: "display: none"
   = image_tag 'icon-search 1.png',size: "30x25",class: "main-header__search-img"
  %input{name: "search-word-list", type: "hidden", value: @wordbox, class: 'search_word_list' }  ←この行を入れる
  %input{name: "search-id-list", type: "hidden", value: @id_box, class: 'search_id_list' }     ←この行を入れる
 %ul#result-word ←この下に候補用の要素を追加する

c) 検索boxに入力されるたびに発火させ処理させる

jsファイル完全版

search.js
$(document).on('turbolinks:load', function(){
  var searchWordList = $('.search_word_list').val();


  function appendList(word, number) {    
    let item = $(`
    <li class="list result-list">
      <a href = "/products/${number}" class="search-word-list">
        <p>${word}</p>
    `);
    $("#result-word").append(item);
  }

  function editElement(element) {
    if (element != ""){
      let result = "^" + element;
      return result;
    }else{
      let result = "$^";
      return result;
    }
  }

  $("#_products_searches_keyword").on("keyup", function() {
    let input = $("#_products_searches_keyword").val();
    if (input==""){
      $("#result-word").empty();
    }else {
      let inputs = input.split(" ");
      let newInputs = inputs.map(editElement);
      let reg = RegExp(newInputs.join("|"));


      $.each( JSON.parse(searchWordList), function(i, word) {
        var searchIdList = $('.search_id_list').val();
        searchIdList =JSON.parse(searchIdList)
        if (word.match(reg)) {
          appendList(word,searchIdList[i]);
        }
      });
    };
  });
});

search.jsの詳細コード

search.js
 var searchWordList = $('.search_word_list').val(); ⬅️①

 $("#_products_searches_keyword").on("keyup", function() { ⬅️②
    let input = $("#_products_searches_keyword").val();
    if (input==""){
      $("#result-word").empty();
    }else {
      let inputs = input.split(" ");
      let newInputs = inputs.map(editElement);
      let reg = RegExp(newInputs.join("|"));


      ---省略---
      });
    };
  });

① ページが読み込まれた時に商品の名前、idを取得する
② ↓入力されるたびに候補が出て欲しいので、keyupを使って発火させる。
  ↓発火すると検索boxに入れられた値を取得する
  ↓何も入力されていなければ候補用の要素を削除する
  ↓入力された検索ワードが複数ある場合はスペースで区切り、配列(inputs)にする
  ↓配列(inputs)をmapで新しい配列にする d)に飛ぶ
  ↓正規表現用の変数を用意し、先ほど ^ マークを付けた配列を"|"(「または」を意味する)を間に入れて合体させる。

d) 検索boxに入力された値をもとに正規表現を作成

search.js
 function editElement(element) {
    if (element != ""){
      let result = "^" + element;
      return result;
    }else{
      let result = "$^";
      return result;
    }
  }

inputで分けられた配列の中身があるときだけ検索ワードの先頭に ^ マークをつける。「test ␣」のようにスペースが空いている場合は「"^test", "^"」というふうに配列が作成されるので、すべての商品名がヒットしてしまう。「""」の時は ^ マークは付けないようにする。 b)に戻る。

e) インスタンス変数の値をeachで取り出して正規表現とマッチするか調べる

search.js
 $.each( JSON.parse(searchWordList), function(i, word) {
   var searchIdList = $('.search_id_list').val();
   searchIdList =JSON.parse(searchIdList)
   if (word.match(reg)) {
   appendList(word,searchIdList[i]);
   }
 });

 一行目のJSON.parseはsearchWordListをobjectに変換するためのメソッド
 jsのeachはobjectに対して処理を行うようでこの記述がないとエラーが表示される。(理解仕切れていません)

Uncaught TypeError: Cannot use 'in' operator to search for 'length' in ["aa", "test", "選択してくださいテスト", "test-sample", "服"]

商品のidにも同じように記述する
はじめは商品のidを渡さずに、eachのindexを使ってリンクのURLを作成していたが、本番環境でエラーが出たので、書き換えました。

f) e)のeachでマッチしたものだけ、関数を使って要素を作り、検索boxにappendする

search.js
 function appendList(word, number) {    
   let item = $(`
   <li class="list result-list">
    <a href = "/products/${number}" class="search-word-list">
     <p>${word}</p>
  `);
  $("#result-word").append(item);
  }

候補をクリックするとその商品のページに移動するためリンクを作成しています。その時にproduct.idが必要なめviewから取得しました。

 

3 最後に

今回のポイントは
・商品のデータをビューからjsに渡す
・検索ワードを入力している途中でスペースが入った時にすべての商品名がヒットしてしまうので、スペースには ^ マークを付けない
・JSON.parseでobjectに変換する
・検索ワードを正規表現にして該当するものだけヒットするようにする

以上です。
最後までご覧いただきありがとうございました。

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

reactでボタンクリックでコピーさせる | JavaScript

  const copyText = (): void => {
    navigator.clipboard.writeText(hoge);
  };
          <Button
            onClick={(): void => copyText()}
            value='コピー'
          />

備考

navigator.clipboard.writeText(hoge); のしたでAlertとかするとコピーできなくなる

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

javascript jQuery スクロール禁止、解除

スクロール禁止

$('html *').css('overflow','hidden');
$(window).on('touchmove.noScroll', function(e) {
    e.preventDefault();
});

解除

    $('html *').css('overflow','visible');
    $(window).off('.noScroll');

できました。スマホ対応です。

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

JavascriptでArrayに対する破壊的メソッドを安全に使う方法

これは何

@Shokorep さんにより、JSの破壊・非破壊メソッドがまとまっている記事が書かれていましたが、私のこの記事では「破壊的な関数をどうやって安全に使うか」という話を書こうと思います。

破壊的とは

対象となるArrayの中身を変えてしまうこと。
例えば reverse() ですと以下のようになります。

image.png

元のArrayであるarr1の中身が変わってしまっています。

破壊的なものを安全に使う

以下のように一回配列展開(スプレッド構文)をしてあげると安全に使用することができます。

image.png

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

JavaScriptでArrayに対する破壊的メソッドを安全に使う方法

これは何

@Shokorep さんにより、JSの破壊・非破壊メソッドがまとまっている記事が書かれていましたが、私のこの記事では「破壊的な関数をどうやって安全に使うか」という話を書こうと思います。

破壊的とは

対象となるArrayの中身を変えてしまうこと。
例えば reverse() ですと以下のようになります。

image.png

元のArrayであるarr1の中身が変わってしまっています。

破壊的なものを安全に使う

一回配列展開をしてあげると元のArrayとは無関係になるので、安全に使用することができます。

スプレッド構文([...arr])を使う方法

image.png

concat() を使う方法

image.png

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

[Angular] リアクティブフォームから値を取得する際のvalueに型を定義する

リアクティブフォームのvalueがanyなのをどうにかしたい。
けどそんなに手間をかけたくない。。
そんな時に手軽に型を定義できる方法を発見したので共有します。

目的

https://angular.jp/api/forms/AbstractControl#value
これのanyをどうにかしたい。

簡単な型の定義方法

まずは、FormGroupを拡張した型定義用のclassを用意する。

export class FormGroupTyped<T> extends FormGroup {
  get value(): T {
    return this.value;
  }
}

それを利用して、リアクティブフォームから値を取得する。

// fromの型を定義しておく。
interface Form {
  hoge: string;
}

ngOnInit() {
  const form: FormGroupTyped<Form> = this.formBuilder.group({
    hoge: [''],
  });

  // Formで定義した型となる。  
  form.value.hoge; // => (property) Form.memo: string
}

これでだけで型を与えることができました!
手軽に導入できるので個人的には気に入っています。
取得した値にTypeGuardをしたりする手間も省けますしね!

参考

https://github.com/angular/angular/issues/13721#issuecomment-441493880

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

[Angular] リアクティブフォームのvalueに型を定義する

リアクティブフォームのvalueがanyなのをどうにかしたい。
けどそんなに手間をかけたくない。。
そんな時に手軽に型を定義できる方法を発見したので共有します。

目的

https://angular.jp/api/forms/AbstractControl#value
これのanyをどうにかしたい。

簡単な型の定義方法

まずは、FormGroupを拡張した型定義用のclassを用意する。

export class FormGroupTyped<T> extends FormGroup {
  get value(): T {
    return this.value;
  }
}

それを利用して、リアクティブフォームから値を取得する。

// fromの型を定義しておく。
interface Form {
  hoge: string;
}

ngOnInit() {
  const form: FormGroupTyped<Form> = this.formBuilder.group({
    hoge: [''],
  });

  // Formで定義した型となる。  
  form.value.hoge; // => (property) Form.hoge: string
}

これでだけで型を与えることができました!
手軽に導入できるので個人的には気に入っています。
取得した値にTypeGuardをしたりする手間も省けますしね!

参考

https://github.com/angular/angular/issues/13721#issuecomment-441493880

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

ほぼメモ。JSONの文章中でダブルクォーテーションを使いたい。

例えばこんなファイルがったとします。

{
  "こんにちは": "Hello!",
  "おやすみなさい": "Good night!"
}

これだけだったら特に問題にならないですね。

もし、
ダブルクォーテーションを使いたかったら???

{
  "六法全書": "\"a digest of Japanese laws\""
}

翻訳参考
ダブルクォーテーションの直前に\を置けば解決です。

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

storybook for htmlを使って簡単にコンポーネントのカタログを作成する

対象読者

  • React.js,Vue.jsを使っていないプロジェクトでstorybookを導入したいけどやり方がわからない人
  • マークアップ言語 + JavaScriptちょっとわかる人
  • storybookの勉強はしたいけど、React.js,Vue.jsの勉強まではやりたくない人

成果物

URL

https://miwa-storybook-html.netlify.com/

GitHub

現在作成中です。

https://github.com/miwashutaro0611/html-storybook

対応環境

言語

  • HTML
  • SCSS

cssで行いたい場合、「既存のscssファイルの読み込み」の部分などのscsscssに変えたり、「storybook上でscssファイルが読み込まれるように設定」の部分を飛ばすなどで対応することができると思います。(未検証)

バージョン

  • node: v12.16.1
  • @storybook/html: "^5.3.18"
  • node-sass: "^4.13.1"

セットアップ

参考: Storybook for HTML

自動セットアップ

$ npx -p @storybook/cli sb init --type html

ゼロから作成する場合

ゼロから設定を行う方法を見る

1. package.json作成。必要なパッケージのインストール

$ npm init
$ npm i -D @storybook/html babel-loader @babel/core

パッケージ一覧

2. npm scriptの追加

package.json
{
    "scripts": {
      "storybook": "start-storybook"
    }
}

3. .storybook/main.jsの作成

$ mkdir .storybook
$ touch .storybook/main.js

.storybook/main.jsに記載する内容

module.exports = {
    stories: ['../src/**/*.stories.[tj]s'],
};

上記にように記載した場合、以下のような感じで読み込みが行われる

├── .storybook
│   └── main.js
└── src 
    ├── index.stories.js # 対象ファイル
    └── components # 対象ディレクトリ
        └── index.stories.js # 対象ファイル

4. ストーリーファイルの作成

export default { title: 'Button' }

export const withText = () => '<button class="btn">Hello World</button>' // HTMLで書く場合

export const withEmoji = () => {
  const button = document.createElement('button') // button要素作成
  button.innerText = '? ? ? ?' // button要素のテキスト
  return button
};

storybook上でscssファイルが読み込まれるように設定

参考: Custom Webpack Config

必要なパッケージのインストール

$ npm i -D style-loader css-loader sass-loader

パッケージ一覧

.storybook/main.jsにscss読み込み設定を記載

const { resolve } = require('path')

module.exports = {
  webpackFinal: async(config, {configType}) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ],
      include: resolve(__dirname, '../'),
    })
    return config
  }
}

storybookに読み込みを行うコンポーネントを作成

.htmlを使ってHTMLの記載を行いたい場合

├── _index.scss # スタイル用ファイル
├── index.html # テンプレート用ファイル
└── index.stories.js # storybook用ファイル

_index.scss

.c-title {
  font-size: 40px;
  span {
      font-size: 60px;
  }
}

index.html

<p class='c-text'>Hello <span>World!!</span></p>

index.stories.js

import Templete from './index.html'
import './_index.scss'

export default {
  title: 'Heading',
}

export const HeadingTem = () =>  {
  return Templete
}

テンプレート内に入れる

├── _index.scss # スタイル用ファイル
├── index.js # テンプレート用ファイル
└── index.stories.js # storybook用ファイル

_index.scss

.c-title {
  font-size: 40px;
  span {
      font-size: 60px;
  }
}

index.js

export const Template = () => {
  return `
    <p class='c-text'>Hello <span>World!!</span></p>
  `
}

index.stories.js

import Templete from './index.js'
import './_index.scss'

export default {
  title: 'Heading',
}

export const HeadingTem = () =>  {
  return Templete
}

既存のscssファイルの読み込み

参考: Default Config

  • reset.cssなどの読み込み
  • 上記のようなコンポーネントごとにscssファイルを記載したくない時
  • プロジェクトのscssをそのまま使いたい時

の時に.storybook/config.jsに読み込みを行うことで既存のscssファイルを読み込むこともできる。

.storybook/config.jsにscss読み込み設定を記載

import '../scss/style.scss' // 読み込みを行いたいscssファイル

アドオン一覧

アドオン参考リンク

スクリーンショット 2020-04-05 3.35.50.png

※2020年4月5日時点

今回使ったアドオン一覧

@pickra/copy-code-block

HTMLのソースコードを表示・コピーすることができるアドオン

インストール

$ npm i @pickra/copy-code-block

使い方

コンポーネントファイル

import copyCodeBlock from '@pickra/copy-code-block'
import Templete from './index.html'

export const TempleteCode = () =>  {
  return (Templete + copyCodeBlock(Templete)) // テンプレートの内容 + コードブロックを表示
}

@storybook/addon-knobs

テンプレート内のテキストや状態を動的に変更を行うことができるアドオン

インストール

$ npm i @storybook/addon-knobs

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-knobs/register']
}

コンポーネントファイル

import { withKnobs, text } from '@storybook/addon-knobs'

export default {
  decorators: [withKnobs]
}

export const Template = () => {
  const tmpText = text('Text', 'Hello World!!')
  return `
    <p class='c-text'>${tmpText}</p>
  `
}

@storybook/addon-a11y

コンポーエント内のアクセシビリティをチェックするアドオン

インストール

$ npm i @storybook/addon-a11y

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-a11y/register']
}

ファイル全体に適応させたい場合、.storybook/config.jsに以下を記載

import { addDecorator } from '@storybook/html'
import { withA11y } from '@storybook/addon-a11y'

addDecorator(withA11y)

@storybook/addon-storysource

ストーリーのソースを表示するアドオン

インストール

$ npm i @storybook/addon-storysource

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-storysource'],
};

@storybook/addon-notes

テキストやマークダウン形式でストーリーの説明部などを追加することができるアドオン

インストール

$ npm i @storybook/addon-notes

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-notes/register'],
};

コンポーネントファイル

import README from './README.md' // コンポーネントと同じ階層にファイルを配置

export default {
  title: 'Heading',
  parameters: {
    notes: { README }
  }
}

@storybook/addon-viewport

インストール

$ npm i @storybook/addon-viewport

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-viewport/register']
}

サイズをカスタマイズしたい場合
既存だと「iphone5」などのサイズがないので、.storybook/config.jsをカスタマイズして、任意のサイズでの表示されるようにする。

import { addParameters } from '@storybook/html'

const customViewports = {
  iPhone5: {
    name: 'iPhone5',
    styles: {
      width: '320px',
      height: '568px',
    },
  },
  iPhone6: {
    name: 'iPhone6,7,8',
    styles: {
      width: '375px',
      height: '667px',
    },
  },
  iPhoneX: {
    name: 'iPhoneX',
    styles: {
      width: '375px',
      height: '812px',
    },
  },
  iPhoneXsMax: {
    name: 'iPhoneXsMax',
    styles: {
      width: '414px',
      height: '896px',
    },
  },
}

addParameters({
  viewport: { viewports: customViewports }
})

@storybook/addon-docs

ストーリーをドキュメント形式で表示してくれるアドオン 

インストール

$ npm i @storybook/addon-docs

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-docs'],
};

@storybook/addon-backgrounds

storybookの背景色を変更することができるアドオン

インストール

$ npm i @storybook/addon-backgrounds

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['@storybook/addon-backgrounds/register']
};

.storybook/config.jsに以下を記載

import { addParameters } from '@storybook/html'

addParameters({
  backgrounds: [
    { name: 'white', value: '#fff', default: true }, // デフォルトの色を設定したい場合、「default: true」を記載。
    { name: 'black', value: '#333' },
    { name: 'facebook', value: '#3b5998' },
    { name: 'twitter', value: '#00aced' },
  ]
})

storybook-dark-mode/register

storybookのテーマカラーをダークモード・ライトモードで切り替えを行うことができるアドオン

インストール

$ npm i storybook-dark-mode

使い方

.storybook/main.jsに以下を記載

module.exports = {
  addons: ['storybook-dark-mode/register']
};

.storybook/config.jsに以下を記載

import { addParameters } from '@storybook/html'

addParameters({
  darkMode: {
    dark: { ...themes.dark, appBg: 'black' },
    light: { ...themes.normal, appBg: 'white' }
  }
})

20200309233915.png

画像のようなエラーが出た場合、@storybook/themingのインストールを行う。

$ npm i @storybook/theming

.storybook/config.jsに「themes」を記載

import { addParameters } from '@storybook/html'
import { themes } from '@storybook/theming' // これを追記

addParameters({
  darkMode: {
    dark: { ...themes.dark, appBg: 'black' },
    light: { ...themes.normal, appBg: 'white' }
  }
})

アドオンを読みこんだ後の設定ファイルの中身

.storybook/main.js

const { resolve } = require('path')

module.exports = {
  stories: ['../components/**/*.stories.js'],
  addons: [
    '@storybook/addon-knobs/register',
    '@storybook/addon-a11y/register',
    '@storybook/addon-storysource/register',
    '@storybook/addon-notes/register',
    '@storybook/addon-viewport/register',
    '@storybook/addon-docs',
    '@storybook/addon-backgrounds/register',
    'storybook-dark-mode/register'
  ],
  webpackFinal: async(config, {configType}) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'
      ],
      include: resolve(__dirname, '../'),
    })
    return config
  }
}

.storybook/config.js

import { configure, addParameters, addDecorator } from '@storybook/html'
import { withA11y } from '@storybook/addon-a11y'
import { themes } from '@storybook/theming'

import '../scss/style.scss'

addDecorator(withA11y)

const customViewports = {
  iPhone5: {
    name: 'iPhone5',
    styles: {
      width: '320px',
      height: '568px',
    },
  },
  iPhone6: {
    name: 'iPhone6,7,8',
    styles: {
      width: '375px',
      height: '667px',
    },
  },
  iPhoneX: {
    name: 'iPhoneX',
    styles: {
      width: '375px',
      height: '812px',
    },
  },
  iPhoneXsMax: {
    name: 'iPhoneXsMax',
    styles: {
      width: '414px',
      height: '896px',
    },
  },
}

addParameters({
  viewport: { viewports: customViewports },
  backgrounds: [
    { name: 'white', value: '#fff', default: true },
    { name: 'black', value: '#333' },
    { name: 'facebook', value: '#3b5998' },
    { name: 'twitter', value: '#00aced' },
  ],
  darkMode: {
    dark: { ...themes.dark, appBg: 'black' },
    light: { ...themes.normal, appBg: 'white' }
  }
})
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Serverless Components はオレたちの未来を劇的にスケールさせるか

Serverless.inc 社より、Serverless Components がついに GA されました。

近年のアプリケーション開発では、いくつかの SaaS を組み合わせることで超高速に開発を行うことができます。例えば「認証は Auth0、ホスティングは Netlify、バックエンド API は AWS Lambda を使用する」といった具合です。このように複数のサービスを組み合わせることで、Undifferentiated Heavy Lifting な作業を排除できます。開発者は価値を生み出すビジネスロジックにのみ集中できるようになるのです。

以下はサーバレスアーキテクチャの例です。複数の SaaS を組み合わせて構築しています。

architecture.png

SaaS を組み合わせるだけで、一定の機能群を作り上げることができる時代になりました。しかし、それにしても複雑な管理は残ります。アプリケーション開発者は複数のサービスを手作業で組み合わせなければならず、構築と構成管理に一定の複雑度を残してしまいます。

そこで、Serverless Components です。

Serverless Components は、全てのクラウドベンダー、 SaaS ベンダーに対してインフラとアプリをプロビジョニングします。すでに提供されているコンポーネントを組み合わせるだけで即座にアプリケーションを構築できます。

従来 Serverless Framework は function と event は簡単に定義できていましたが、インフラリソースをプロビジョニングするためにはどうしても Cloudformation を定義する必要がありました。
また、プロビジョニングできる対象も AWS や GCP などの特定のクラウドベンダーのサービスにしか対応しておらず、Auth0 などを使用する場合は自前で構成管理をする必要がありました。Serverless Components なら様々な SaaS に対応できます。

コンポーネント

Serverless Component は React のコンポーネントと同じ構造に基づいています。個々のコンポーネントを参照したり、複数のコンポーネントを同時に作成できます。

先の例をコンポーネントを使用して構築すると以下のように分解ができます。もちろん、より小さくコンポーネントを分割することもできます。ここでは最小の意味のある単位で分割した場合を図示しています。

components.png

サーバレスコンポーネントは、高次のユースケース(ウェブサイト、ブログ、請求システムなど)を中心に構築されています。関係のない低レベルなインフラの詳細は抽象化され、代わりに単純な構成が提供されます。例えば、S3 の静的サイト公開設定や、ログ記録、暗号化設定などはユースケースに対しては意識する必要はありません。事前に設定済みのコンポーネントを使用すれば良いのです。

これはソフトウェア開発における基本的な考え方 関心の分離 (Separation of Concerns: SoC) に基づいていますね。確かに Infrastructure as Code をやっていると、インフラリソースの細部まで理解して構築する必要があり、多大な学習コストを要していました。

ServerlessComponents を使用したウェブサイト

さて、まずは最もシンプルなアプリケーションを Serverless Component を使用して構築してみましょう。
ここでは、GitHub のリポジトリでも例としてあげている サーバレスウェブサイト を構築することにします。

今回構築するウェブサイトは、AWS S3 でホストされます。無料の AWS ACM SSL 証明書で保護された AWS Route 53 のカスタムドメインでアクセスします。さらに、静的コンテンツは、AWS Cloudfront を使用して迅速かつグローバルに配信されます。

website.png

従来このような構成を実現する場合、ServerlessFramework に直接 Cloudformation を書き下し、各リソース間の詳細な設定と依存関係を意識する必要がありました。数百行の Cloudformation のテンプレートが必要でしょう。

Serverless Components を使用する場合はこれだけです。

component: website
name: website
inputs:
  src:
    src: ./src
    hook: npm run build
    dist: ./dist
  domain: geeawa.ga

驚異的なほど、シンプルです。
component: website として、website コンポーネントを使用することを宣言し、そのコンポーネントに渡す設定値を input: にて指定しています。ただ、それだけです。

Serverless Components を使用してウェブサイトを構築する

実際に website コンポーネントを使用してこの構成を作ってみましょう。

Install

まずは最新バージョンの Serverless Framework をインストールします。

$ npm install -g serverless

Create

サンプルとして、以下のようにテンプレート URL を指定して構築します。

$ serverless create --template-url https://github.com/serverless/components/tree/master/templates/website
$ cd website

次に、.env ファイルを使用して AWS アクセスキーの情報を記載しましょう。.envファイルは website のルートディレクトリに作成します。

AWS_ACCESS_KEY_ID=XXX
AWS_SECRET_ACCESS_KEY=XXX

ディレクトリ構成は以下のようになっているはずです。

|- src
  |- index.html
|- serverless.yml
|- .env

Deploy

あとはデプロイをするだけです。

$ serverless deploy

デプロイが完了すると以下のようにウェブサイトの URL が発行されます。Cloudfront へ配信が完全に完了するまでに少し時間がかかることに注意してください。

serverless ⚡ framework
Action: "deploy" - Stage: "dev" - App: "landing-page" - Instance: "landing-page"

bucket:    website-089y5jm
bucketUrl: http://website-089y5jm.s3-website-us-east-1.amazonaws.com
url:       https://d2u9prrumf2g64.cloudfront.net
domain:    https://www.geeawa.ga

以下のようなサイトがデプロイされています。

page.png

Dev Mode

さらに興味深い機能として Dev Mode があります。開発中にソースディレクトリの変更を監視し、保存すると即座にデプロイできます。

sls.gif

Remove

作成されたインフラを破棄する場合は、serverless.yml ファイルが含まれているディレクトリで次のコマンドを実行するだけです。

$ serverless remove

コンポーネントを自作する

コンポーネントを自作するためには以下の2つのファイルが必要です。

  • serverless.component.yml: ServerlessComponent の定義を記入します。
  • serverelss.js: ServerlessComponent のコード(実装)を記述します。

serverless.component.yml

コンポーネントをサーバーレスレジストリ内で利用できるようにするためには serverless.component.yml を作成する必要があります。

# serverless.component.yml

name: express # 必須 コンポーネント名
version: 0.0.4 # 必須 バージョン
author: eahefnawy # 必須 著者
org: serverlessinc # 必須 開発組織名
description: Deploys Serverless Express.js Apps # 任意 説明
keywords: aws, serverless, express # 任意 registry.serverless.comで検索するときに引っかかるキーワード
repo: https://github.com/owner/project # 任意 ソースコードのリポジトリURL
license: MIT # 任意 ライセンス
main: ./src # 任意 コンポーネントのソースコードが格納されているディレクトリ

serverless.js

serverless.jsには以下のように実装していきます。React の思想にインスパイアされており、Component を継承したつくりになっています。deploy, removeなどの Function を書いていくことになります。

// serverless.js

const { Component } = require("@serverless/core");

class MyBlog extends Component {
  async deploy(inputs) {
    console.log("Deploying a serverless blog"); // --debug モードで実行するとログが出力されます。
    this.state.url = outputs.url; // stateに保存する
    return outputs;
  }
}

module.exports = MyBlog;

deploy() は必ず書く必要があります。deploy() は、コンポーネントが何らかのクラウドリソースを作成するためのロジックが存在する場所です。serverless deploy コマンドを実行すると、常に deploy() メソッドが呼び出されます。

このクラスに他のメソッドを追加することもできます。remove() ではサーバレスコンポーネントが作成したクラウドリソースを全て削除します。

他にもメソッドはいくつでも追加できます。コンポーネントを追加機能付きでプロビジョニングしたい場合などに拡張できる作りになっています。

Serverless Components は test(), logs(), metrics() 機能を備えたコンポーネント、またはデータベースコンポーネントの初期値を確立するためのコンポーネント seed() の開発に着手しているようです。

メソッド以外の deploy() メソッドはすべてオプションです。すべてのメソッドは、inputs 個別の引数ではなく単一のオブジェクトを取り、単一のオブジェクト outputs を返します。

まとめ

クラウドや SaaS ベンダーのリソースを統一的に管理し、再利用可能にするプラットフォームが Serverless Components です。

現在公式が提供しているコンポーネントは 67 種類(2020/04/06 現在)です。
まずは AWS や Kubernates 関連がラインナップし始めています。急激に拡大しています。もう 本当に必要なものだけを実装し、組み合わせるだけ という開発スタイルに変わりはじめています。

これこそがクラウドテクノロジーの目指していたところかもしれません。さらなる発展が楽しみですね。

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

【JS】JS-Proメモ

メモ

let

  • 変数(変更可能)

const

  • 定数(変更不可能)

条件分岐

  • if文とswitch文の二つの方法

if文

  • 2つから片方を選択する場合に使用

switch文

  • 複数から選択する場合に使用

出力の中で比較演算子を使うとtrue or falseで帰ってくる

エディタ
const age = 20
console.log(age > 10)
console.log(age > 30)
ターミナル
true
false

反復処理

  • while文とfor文の二つの方法

while文

  • 長いが文法がif文と同じ為、わかりやすい

for文

  • 変数の定義もfor文内ででき、シンプルに記述できる

constructor(コンストラクタ)

  • インスタンスを作る時、実行したい処理を中に記述

this

  • コンストラクタによって作成されたインスタンス
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

解決方法: "Error: Invariant failed: You should not use <Link> outside a <Router>"

はじめに

react-router-hash-linkを使ってreactアプリを作っている時につまずいた備忘録です。

コード

React.js
import React, { Component } from 'react';
import { HashLink } from 'react-router-hash-link';

export default function hoge() {
    return (
        <HashLink to="./hoge#hoge" smooth>
            hoge
        </HashLink>
    )
}

エラー

console.log
Uncaught Error: Invariant failed: You should not use <Link> outside a <Router>
    at invariant (tiny-invariant.esm.js:10)
    at Link.js:84
    at updateContextConsumer (react-dom.development.js:18304)
    at beginWork (react-dom.development.js:18661)
    at HTMLUnknownElement.callCallback (react-dom.development.js:188)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:237)
    at invokeGuardedCallback (react-dom.development.js:292)
    at beginWork$1 (react-dom.development.js:23203)
    at performUnitOfWork (react-dom.development.js:22154)
    at workLoopSync (react-dom.development.js:22130)
    at performSyncWorkOnRoot (react-dom.development.js:21756)
    at scheduleUpdateOnFiber (react-dom.development.js:21188)
    at updateContainer (react-dom.development.js:24373)
    at react-dom.development.js:24758
    at unbatchedUpdates (react-dom.development.js:21903)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:24757)
    at Object.render (react-dom.development.js:24840)
    at Module../src/index.js (index.js:8)
    at __webpack_require__ (bootstrap:784)
    at fn (bootstrap:150)
    at Object.1 (serviceWorker.js:141)
    at __webpack_require__ (bootstrap:784)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1

発生条件と解決方法

どうもstorybookはreact-routerに依存したサードパーティのコンポーネントを追加することを予期していないようで、対象コンポーネントをreact-router-dom<MemoryRouter/>で囲ってあげれば対応できるっぽいです。
また同様のことがreact-redux<Provider/>の外でconnectuseSelecterを使った場合などにも生じるようです。

ただ今回は別にstorybookを使っているわけでもないのでとりあえず該当のコードを<Memoryrouter/>で囲うことで解決しました。

React.js
import React, { Component } from 'react';
import { MemoryRouter} from 'react-router-dom';
import { HashLink } from 'react-router-hash-link';

export default function hoge() {
    return (
        <MemoryRouter>
            <HashLink to="./hoge#hoge" smooth>
                hoge
            </HashLink>
        <MemoryRouter>
    )
}

storybookに追加する際のエラーでもこれと同様に<MemoryRouter/>で囲う他、addDecolatorを用いる方法もあるようです。以下の記事を参照してみてください。

参考

https://github.com/storybookjs/storybook/issues/8892
https://qiita.com/daikiojm/items/da3299d7b90d38194d85

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

Netlify functionを使ってフォームが送信されたときに送信したユーザーのメールアドレスに自動返信する。

自社サイトを構築するときに、いままではWordpressのプラグインを使っていたので
フォームを送信したときに自動的に送信した人のメールアドレスに返信するシステムを作っていた。
JAMstackだとサーバーも何もないのでそのような動的な動きを作るにはどうすればいいか悩んだ。

netlify function

https://docs.netlify.com/functions/overview/

これを使うことでAWS Lambdaと同様の動きをnetlify上で起こすことができる。
今回使用するのはsubmission-createdという名前を使うことでFORMが送信されたときをトリガーとして動作させることができる。
他にも様々なことをトリガーとしてどうさせることができるので用途に応じてチョイスするのが良いだろう。

使う内容としてはnodemailerを使う
https://nodemailer.com/about/

submission-created.js
require('dotenv').config();

const nodemailer = require('nodemailer');

exports.handler = function(event, context, callback) {
  const { name, email, message } = JSON.parse(event.body).payload.data

  console.log(user);

  let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
      type:"OAuth2",
      user:"GmailのID",
      clientId:"取得したClientID",
      clientSecret:"取得したコード",
      refreshToken:"(リフレッシュトークン)",
      accessToken: "(アクセストークン)"   
    },
  });


  console.log(event.body);

  let mailOptions = {
    from: `"表示する名前"<使用するgmailアドレス>`,
    to: `${email}`,
    subject: 'ありがとうございます。フォームを送信いたしました',
    html: `${name}様 メッセージを送信しました。`,
  };

  transporter.sendMail(mailOptions, function(error, info) {
    if (error) {
      callback(error);
    } else {
      callback(null, {
        statusCode: 200,
        body: 'Ok',
      });
    }
  });
};

送信例
IMG_9740.PNG

Netlifyはサーバーレスの味方

フォームを作ることに関してはまた別に書こうとは思うが
かんたんな動的動作についてはサーバーレスでもなんとかなるのでコストダウンにつながるのではないかとは思われる。

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

Kinx ライブラリ - String

String

はじめに

「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。言語はライブラリが命。ということでライブラリの使い方編。

今回は String です。

文字列操作の基本インターフェース。String オブジェクトに括り付いたメソッドは特殊メソッド(と呼ぶメソッドがある、名前は今決めた)扱いで、文字列オブジェクトに直接作用させることができる。

String 特殊オブジェクト

特殊メソッドを持つオブジェクトを特殊オブジェクトと呼び(←今決めた)、String、Array、Integer、Double、Binary がある。特殊メソッドは、特殊オブジェクトが対象としているオブジェクト(String なら文字列)に対して直接作用させることができる。

例えば、以下のように関数定義してみよう。

String.greeting = function(name) {
    System.println("Hello, I am %{name}.");
};

すると、以下のように書くことができるようになる。

"John".greeting();

実行してみよう。

Hello, I am John.

使い方によっては便利。ただし、ライブラリの追加(組み込み特殊メソッドの追加)で使う可能性がある ので乱用はあまりしないほうが良いかもしれない。

String

組み込み特殊メソッド

メソッド 意味
String.startsWith(str) 文字列が str で始まれば true。
String.endsWith(str) 文字列が str で終れば true。
String.find(str) 文字列の中で str が見つかった位置(0~)を返す。見つからなかった場合は -1 を返す。
String.subString(str, start[, len]) str の部分文字列を返す。
String.replace(str, cond, repl) str から cond にマッチする部分を全て repl に置換する。cond は文字列または正規表現オブジェクトの指定が可能。
String.toInt(str) str を整数値に変換する。
String.toDouble(str) str を実数値に変換する。
String.parentPath(str) str をパスと認識し、親パスとなる部分文字列を返す。例)"ab/cd/ef.x".parentPath()"ab/cd.x"
String.filename(str) str をパスと認識し、親パス部分を削除したファイル名部分文字列を返す。例)"ab/cd/ef.x".filename()"ef.x"
String.stem(str) str をパスと認識し、ファイル名の stem 部分文字列を返す。例)"ab/cd/ef.x".stem()"ef"
String.extnsion(str) str をパスと認識し、ファイル名の拡張子部分文字列を返す。例)"ab/cd/ef.x".extnsion()".x"
String.split(str, sep) strsep を区切り文字として分割し、配列として返す。sep は文字列、または正規表現オブジェクトの指定が可能。
String.each(str, callback) str を 1 文字ずつ分割し、それを引数にして callback 関数を呼び出す。callback 関数の第 2 引数に index (0~) も渡される。

each は現在残念ながら日本語はうまく分割してくれないので注意。正式リリースまでに UTF-8 対応はさせる予定。

特殊オペレーター

/ オペレーター

文字列に対して / オペレーターを適用した場合、/ で連結した文字列を返す。その際、重複したセパレータは 1 つになる。

var a = "aa/bb" / "ccdd";   // => "aa/bb/ccdd"
var b = "aa/bb/" / "ccdd";  // => "aa/bb/ccdd"
var c = "aa/bb" / "/ccdd";  // => "aa/bb/ccdd"

=~ オペレーター

文字列に対して =~ を適用した場合、右辺値には正規表現オブジェクトを期待する。正規表現のオブジェクトではなかった場合、例外が送出される。

!~ オペレーター

文字列に対して !~ を適用した場合、右辺値には正規表現オブジェクトを期待する。正規表現のオブジェクトではなかった場合、例外が送出される。

後置 [] オペレーター

文字列に対してインデックスアクセスをした場合、その位置にある文字コードを整数値で返す。したがって、「5 文字目が 'a' である」という判断をする場合は以下のように書く。

if (str[5] == 'a'[5]) {
    /* ... */
}

ちょっと C と違うことに注意。文字 'a' は文字ではなく 文字列リテラル のため、同じように [5] が必要。

単項 * オペレーター

単項 * オペレーターを文字列に適用した場合、文字列を配列に変換する。

var a = *"abc";  // => [97, 98, 99]

尚、補足として配列に単項 * オペレーターを適用すると、文字列に戻ってくる。

おわりに

文字列操作を簡単にしたいがためにスクリプト言語を使う、というのもよくあるシーン。そもそもコレ系スクリプトの元祖的な位置付けである Perl はテキスト処理が楽、ということで使われてた経緯もありますし。そういう意味で、文字列操作はプリミティブですが重要な機能。テキスト処理は C で書きたくない処理の一つですね。

ではまた次回。

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