- 投稿日:2020-09-28T23:44:26+09:00
new Proxy() の set() の返り値は true でいい
Uncaught TypeError
JavaScript らしいエラーに出会ったので残しておく。
エラーは以下。VM213:16 Uncaught TypeError: 'set' on proxy: trap returned falsish for property 'a' at <anonymous>:16:21setter が false を返していることが上記のエラーの原因だが、そのときに書いていたコードは false なんて返していないと思っていた。
'use strict' const target = { a: 0 }; const handler = { set: function (target, prop, value, receiver) { const res = target[prop] = value return res }, }; const proxy = new Proxy(target, handler); console.log(proxy.a = 1); console.log(proxy.a = 0);false は返していないが 0 を返していたので、それは false を返していることになる
console.log(proxy.a = 0);
の 0 の代入で、setter は代入された 0 をそのまま返す。
setter の返り値は boolean 型なので暗黙的に boolean 型に変換される。
Javascript は 0 は false として扱うため、setter の返り値は false となり、エラーとなる。Boolean(1) // true Boolean(0) // false Boolean(2) // trueそもそもの誤りとして、代入したものを return で返すコードが Proxy の仕様に沿っていない、ということ。なんとなくで
res
を返してたが、これがダメやな。const handler = { set: function (target, prop, value, receiver) { const res = target[prop] = value return res }, };どう書くべきか
MDN のサンプルでは、return の値に true を設定しているので、以下が正解の書き方になる。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxyconst handler = { set: function (target, prop, value, receiver) { target[prop] = value return true }, };エラーを発生させたいパターンは、 false を return に設定すればいい。
const handler = { set: function (target, prop, value, receiver) { if (value === 2) { return false } target[prop] = value return true }, };まとめ
JavaScript の仕様に沿った書き方をしよう、っていう記事。以上!
- 投稿日:2020-09-28T23:41:46+09:00
Qiitaでプログラミング言語トレンド
1. 概要
日本ではプログラミング言語のトレンドはどんな感じか知りたいので、Qiitaの過去データを取得して分析してみましょう。以下の写真は世界でのトレンドです(参考:PYPLサイト)。
2. データ取得
2.1. APIの利用
APIの制限のため、問題がいくつか発生しました:
- 全部投稿を取得するAPIがありません(全部は580000投稿ぐらいがある)。
- APIによる一回の上限は1万投稿です(100ページ * 100投稿/1ページ)。
- 実際は5900投稿を取得すると、403エラーが発生してから、APIをアクセスできない(スパムから保護するため、1時間60リクエストだけ) → あるタグの投稿数は5900投稿以下のためフィルターを適用します(Stocksの数は30以上)。AWSのEC2インスタンスを適用して取得した時、403エラーになると、インスタンスを再起動しました(新しいIPになる)。
- あるタグの投稿数は5900以下なのに、全部投稿を取得できません。2017年09月の時点ぐらいには500エラーが発生しました。 → 最後取得できた投稿の作成日を保存して、新しいリクエストを作ります。
で、以上の問題を解決すると、以下のコードです。
let axios = require("axios") let fs = require("fs") let csvStr = require("csv-stringify/lib/sync") let PAGE_MAX = 55 function parse_response(response, record_num, outcsv) { for (record_idx = 0; record_idx < record_num; record_idx++) { let record = [] id = response["data"][record_idx]["id"] comments_count = response["data"][record_idx]["comments_count"] likes_count = response["data"][record_idx]["likes_count"] reactions_count = response["data"][record_idx]["reactions_count"] tags = response["data"][record_idx]["tags"] tags_str = "" for(tag_num = 0; tag_num < tags.length; tag_num++){ tags_str = tags_str.concat(', ', tags[tag_num]["name"]) } title = response["data"][record_idx]["title"] user_id = response["data"][record_idx]["user"]["id"] created_at = response["data"][record_idx]["created_at"] record.push(id, comments_count, likes_count, reactions_count, tags_str, title, user_id, created_at) outcsv.push(record) } return outcsv } async function getArticle(tag) { let outcsv = [] let columns = ["id", "comments_count", "likes_count", "reactions_count", "tags", "title", "user_id", "created_at"] outcsv.push(columns) let last_date = "2020-09-28" let record_sum = 0 for (page = 1; page <= PAGE_MAX; page++){ let response = await axios.get("https://qiita.com/api/v2/items?page=" + page + "&per_page=100&query=" + encodeURIComponent("stocks:>30") + "+" + encodeURIComponent("tag:" + tag)) record_num = response["data"].length if(record_num != 0){ outcsv = parse_response(response, record_num, outcsv) record_sum = record_sum + record_num last_date = response["data"][record_num-1]["created_at"].split('T')[0] console.log(record_sum + ":" + last_date) } if(record_num < 100){ break } } for (page = 1; page <= PAGE_MAX; page++) { let response = await axios.get("https://qiita.com/api/v2/items?page=" + page + "&per_page=100&query=" + encodeURIComponent("stocks:>30") + "+" + encodeURIComponent("tag:" + tag) + "+" + encodeURIComponent("created:<" + last_date)) record_num = response["data"].length if(record_num != 0){ outcsv = parse_response(response, record_num, outcsv) record_sum = record_sum + record_num console.log(record_sum) } if(record_num < 100){ break } } fs.writeFileSync(tag + ".csv", csvStr(outcsv)) } // それぞれのタグを変更する:C, C++, C#, Go, Java, Javascript, Kotlin, Objective-C, // PHP, R, Ruby, Swift, Typescript getArticle("python")2.2. アウトプットデータ
結果のデータは各投稿のID,コメント数、LGTM数、絵文字リアクション数、タグ、タイトル、筆者のID、投稿の日時です。
データ量
言語 データ投稿数 全部投稿数 Python 5337 46000 Javascript 5305 37257 Ruby 2927 29307 PHP 2010 21088 Java 1568 15905 Swift 2577 15317 C# 815 10319 Go 1021 9084 C++ 630 8006 Typescript 701 5891 Kotlin 287 4100 Objective-C 935 4010 R 204 3526 C 261 3305 3. トレンド
以上の結果のデータをTableauにグラフを作成しましょう!
3.1. 全体グラフ
横軸は投稿の作成日です(単位:年間)。
縦軸は各言語のタグの投稿数の割合です(単位:パーセント)。3.2. 結果を分析しよう
3.2.1. Python
投稿数に基づと、2012年のPython言語ユーザーの割合は4%でした。その後、急速な成長により、この率は2014年にPHP、2015年にRubyとSwift、2016年にJavascriptを上回りました。現在、Pythonは一番人気がある言語(35%)になりました。3.2.2. Javascript
2012年、JSの投稿数の割合は22%でしたが、2014年までに徐々に18%減少しました。現在、その割合は26%になり、人気がある言語トップで2位にランクされています。3.2.3. Ruby
2012年、Rubyの投稿数の割合は35%に達し1位になりました。その後、何年にも渡って継続的に減少しています。現在、4%になりました。3.2.4. Typescript
2013年から始まり、近頃の3年間の高い成長により、現在、3位(10%)になりました。3.2.5. Swift/Objective-C
Swiftの発達とともに、Objective-Cは衰退していました(0.24%)。全体として、iOSの言語は2015年,2016年に人気があり、最近、少し減少しました。3.2.6. 他の言語
4. よく投稿した時間、曜日
- 投稿日:2020-09-28T23:13:59+09:00
JavaScriptでアラートメッセージを表示させる
プログラミング勉強日記
2020年9月28日
エラーメッセージやサクセスメッセージを表示させるときにJSのメッセージボックスを表示するためにアラートについて簡単にまとめる。alertの使い方
alert()メソッドとはアラートを出すメソッドで、以下のように記述する。
文字列の場合は"
か'
で値を囲む必要がある。alert( 画面に表示させたい値 ) // 文字列・数値のメッセージを出力 alert('アラートのメッセージ')変数を使ってメッセージを出力する
以下のようにalertには変数を使用することができる。
var warn = "エラーメッセージ"; alert(warn);※注意alertのダイアログはカスタマイズできない
ポップアップメッセージに表示されるアイコンであったり、タイトルテキストやボタンのテキストは変更することができない。
alert()メソッドは特定のメッセージをユーザに認識してもらうことを用途としているので、カスタマイズはできない。どうしてもカスタマイズしたい場合は、HTMLやCSS,JavaScriptを用いて独自にダイアログを作成しなくてはならない。参考文献
JavaScriptでalertを使ってアラートを表示させる方法【初心者向け】
【JavaScript入門】alert(アラート)メッセージはこれで完璧。使い方を総まとめ!
- 投稿日:2020-09-28T23:11:42+09:00
JavaScriptを使ってTwitterのbotを作ってみた その2
JavaScriptを使ってTwitterのbotを作ってみた その2
前回は、Twitterモジュールを使って、いろいろなコマンドを使って、基本的な機能を実装するやり方を紹介しました。今回は、その基本的な機能に応用を加えて、より高度な機能を実装していくためのやり方を紹介していきます。
自動的に機能を実装するようにする
前回やってきた機能についてですが、nodeコマンドで実行した時は機能しますが、それ以降は全く機能しなくなるんですよね...
Dateを取得して、13時にツイートをするようにコードを書いたとしても機能してくれません。ではどうしたら自動的に機能してくれるようになるのか。ここでめちゃくちゃ重宝するのがsetIntervalです。bot.jsconst tweet = 'statuses/update'; bot.post(tweet, {status: "百合は尊い"}, function(err, tweet, res) { console.log("\n下記の内容をツイートしました!\n\n" + tweet.text); });前回はこんな感じでツイートをする機能を書いていきましたね。ちなみに、コマンドは定数に代入することも出来るので、このようにして定数に代入しておくことで、「この機能をするためのコマンドなんだっけ...」といちいち考える必要がなくなるのですごくおすすめです!
この機能にsetIntervalを加えてみます。bot.jsconst tweet = 'statuses/update'; setInterval(function() { bot.post(tweet, {status: "百合は尊い"}, function(err, tweet, res) { console.log("\n下記の内容をツイートしました!\n\n" + tweet.text); }); }, 60_000); // 1分ごとこんな感じです。functionの時間指定の部分は、1,000で1秒なので、
1,000 * 60 = 60,000
60,000と指定することで、1分ごとに機能することが出来ます。こうすることで、1分ごとにツイートをする機能を取得することが出来るようになります。
ただ、このままではツイート重複のエラーが出てしまうので、よくある方法としては、配列内に文字列をたくさん入れて、ランダム抽出する方法です。これはかなり使えるのですごくおすすめです!bot.jsconst tweet = 'statuses/update'; let lily_texts = ["百合は尊い", "とりあえず百合は尊い", "やっぱり百合は尊い", "そして百合は尊い"]; let lily_text = lily_texts[Math.floor(Math.random() * lily_texts.length)]; // ランダム抽出 setInterval(function() { bot.post(tweet, {status: lily_text}, function(err, tweet, res) { console.log("\n下記の内容をツイートしました!\n\n" + tweet.text); }); }, 60_000); // 1分ごとまずはlily_textsにツイートしたい内容をどんどん書いていきます。そして、lily_textで、lily_textsの要素の中からランダムに抽出しています。このようにすることで、重複エラーはほぼ起こらなくなります。ただ、乱数なので、稀に被ってしまうことがあります。
さて、これで自動的にツイートしたり、リツイートしたりする方法が分かりましたが、機能を実装する際に、決まった時間にだけ行いたいときもあると思います。そんなときは、setInterval内でDateを取得すれば大丈夫です!bot.jssetInterval(function() { const now = new Date(); const hour = now.getHours(); // 時を取得 const min = now.getMinutes(); // 分を取得 if(hour === 8 && min === 0) { // 8時になったら bot.post(tweet, {status: lily_text}, function(err, tweet, res) { console.log("\n下記の内容をツイートしました!\n\n" + tweet.text); }); }; }, 60_000); // 1分ごとこのように書くと、午前8時になったときだけ、ツイートをするようになります。
bot.jssetInterval(function() { const now = new Date(); const min = now.getMinutes(); // 分を取得 if(min === 0) { // 1時間ごとに bot.post(tweet, {status: lily_text}, function(err, tweet, res) { console.log("\n下記の内容をツイートしました!\n\n" + tweet.text); }); }; }, 60_000); // 1分ごとまた、こういう風に書くと、setIntervalは1分ごとに機能していますが、ツイートをするのは1時間ごとになります。いろいろ試してみましょう!
まだフォローしていないフォロワーのみフォローする
次に、botのことをフォローしてくれた方をフォローし返すための機能を書いてみましょう。
bot.jsconst follower_list = 'followers/list'; const bot_name = {screen_name: "maki_lily_bot"}; setInterval(function() { bot.get(follower_list, bot_name, function(err, follower_list, res) { console.log(follower_list); }); }, 60_000) // 1分ごとまずはbotのフォロワーを確認する必要があるので、botのフォロワーを取得するコマンドから書いていきましょう。情報を取得するだけなので、getメソッドですね。そして、フォロワーを確認する機能で必須なパラメータはscreen_nameです。(@から始まるid名のことを指します。)
さて、次は取得したフォロワーのことをフォローする機能を書いていきますが、フォローする機能は、通常は1回だけ行うことが出来るようになっています。では、どうすれば一度で一気にフォロワーのことをフォロー出来るようにするのか。ここで使えるのが繰り返し構文です。botのフォロワーの人数分繰り返したいので、配列を使った繰り返しを行うことが出来るfor...of文を使っていきましょう。bot.jssetInterval(function() { bot.get(follower_list, bot_name, function(err, follower_list, res) { for(let followers of follower_list.users) { // フォロワーの人数分繰り返す console.log(followers); }; }); }, 60_000) // 1分ごとここで注意してほしいのが、配列を指定するときに、follower_listと書くのではなく、follower_list.usersと書くということです。理由は、フォロワー一覧を取得してみると、返ってくるのが配列ではなく、ハッシュになっているからです。その結果の中身をよく見てみると、usersというキーの中に、フォロワーさん達の情報が配列形式になって格納されています。つまり、follower_listのキーであるusersを指定してあげることで、配列を指定することが出来るということです。この状態で結果を見てみると、その配列の中身が表示されます。
これでフォロワーの人数分機能を実装することが出来るようになりました。さて、次は、すでにbotがフォローしている人はフォローしないようにしなければいけません。そうしないと、「このフォロワーさんはすでにフォローしていますよ」とエラーが出てしまいます。とはいっても、やり方はそこまで難しくはありません。bot.jssetInterval(function() { bot.get(follower_list, bot_name, function(err, follower_list, res) { for(let followers of follower_list.users) { // フォロワーの人数分繰り返す if(followers.following === true) { // すでにフォローしていたら飛ばす continue; }else { console.log(followers.following); }; }; }); }, 60_000) // 1分ごとフォロワー一覧の結果をもう一度よく見てみると、【following】というキーがありますよね? これは、botがその人のことをフォローしているのかを真偽値の値で教えてくれるところなんです。trueと書かれていれば、その人のことはすでにフォローしているということです。ということは、trueの時は、その回は飛ばしてしまえばいいということですよね?繰り返し構文を飛ばすために使うコマンドはcontinueです。これですでにフォローしている人のことはフォローしないようにすることが出来ました。
ただ、後1つだけエラーが起こる可能性が残されています... それが、鍵垢です。鍵垢は、普通の垢とは違い、フォローする前にリクエストを送る必要があります。またフォローする機能を実装する前に、そのユーザーが承認してくれれば全く問題ないんですが、してくれなかった場合は、またフォローしてしまうことになるんです。最後にそれを防ぐ必要があります。ただ、それも難しくはありません。フォロワーにフォローリクエストを送ったかどうか確認するには【follow_request_sent】という部分を見ます。trueなら送っているということになります。これを利用して、bot.jsconst follow = 'friendships/create'; setInterval(function() { bot.get(follower_list, bot_name, function(err, follower_list, res) { for(let followers of follower_list.users) { // フォロワーの人数分繰り返す if(followers.following === true) { // すでにフォローしていたら飛ばす continue; }else { if(followers.follow_request_sent === true) { // リクエストを送っていたら飛ばす continue; }else{ bot.post(follow, {user_id: followers.id_str}, function(err, follow, res) { console.log("\n" + followers.name + "さんのことをフォローしました!"); }); }; }; }; }); }, 60_000) // 1分ごとこれで遂に完成です! ちなみに、getメソッドの中で、postメソッドを使うときは、そのスコープ外のgetメソッドの値も利用することが出来るので、上記みたいに、user_idを書くときに、followers.id_strとすることで、指定することが出来ます。 本当にお疲れさまでした。
まとめ
今回は基本的な機能に加えて、応用を使って、さらに高度な機能を実装するための方法を紹介しました。この方法を上手く使いこなせるようになると、フォロー機能だけでなく、いいね機能やリツイート機能などもすごく細かい設定をすることが可能になります。是非頑張ってみてください!なお、私が百合botを作成しているときに、一番苦闘した機能は返信機能です。マジでめちゃくちゃ苦労しました。多分30時間以上苦しんだかもしれません。もし要望があった場合は、返信機能のやり方も紹介してみようかなと思います。ありがとうございました。 ノシ
- 投稿日:2020-09-28T22:09:22+09:00
画面でエフェクトの実現の(三) --日付ダイアログ
一般的に、画面なかに日付の入力ボックスがあり、日付ダイアログを使って、いい効果が表現できます。
日付ダイアログの効果は以下のサイトを参照してください。
https://xdsoft.net/jqplugins/datetimepicker/実装要点
・datetimeのプラグインを含める
・日付入力ボックスにスタイルを設定する
・datetimeのメソッドを付くコードサンプル
// datetimeのプラグインを含める <link rel="stylesheet" type="text/css" href="/jquery.datetimepicker.css"/ > <script src="/jquery.js"></script> <script src="/jquery.datetimepicker.js"></script>// 日付入力ボックスにスタイルを設定する <input id="date" class="icon-calendar" />// datetimeのメソッドを付く $("#date").datetimepicker({ timepicker:false, format:'d.m.Y', xxx:xxx, xxx:xxx, ... })
- 投稿日:2020-09-28T20:23:19+09:00
サクッとi18n対応を行うためのReact hooksライブラリ、use-mini18nを作った。
現在、私はいくつかのアプリを個人で開発しています。
それらのほとんどはReactを用いたWebアプリです。アプリはどれも小さなものですが、世界中の人に使ってもらいたいと考えているため、i18n対応はなるべく行うようにしています。
(といっても、なかなか時間が確保できず、英語と日本語だけしか対応できていないケースばかりですが...)一例を挙げると、ランダムな音楽を勧めてくれる、下記のようなシンプルなWebアプリを作っています。
Dig Music - Dig Musicはレコメンドエンジンを使用せず、完全にランダムな形でユーザに新しい音楽を紹介するWebアプリです。Reactでi18n対応をする場合、react-i18nextやreact-intl (FormatJSと呼ばれるモノレポに含まれる形に変わったようですね)を使うことが多いと思います。
私もこれらを使用したことがありますが、どちらも素晴らしいライブラリだと感じています。ですが、私が作成するアプリは非常に小規模なものが多いため、これらのライブラリがオーバースペックに感じることもあります。
設定された言語設定に応じて、適切な言語ファイルを読み込み、表示できればそれでいいんだよな...と思いましたが、少し調べてみたところ、そのようなライブラリはなさそうに思えたので、自分で作ることにしました。
TypeScriptを用いてReact hooksライブラリを作成してみたかったという別の理由もあります。シンプルでこじんまりとしたi18nライブラリ、use-mini18n
こちらが作ったものになります。
use-mini18n - A simple and minimalistic React hook library for i18n
ロゴも思い切って作りました。勢い大事。
こちらのライブラリでやれることはシンプルです。
以下のコードサンプルは、このライブラリがやれることをすべて表しています。
(実際に動作しているところをCodeSandbox上で確認できます)import React from "react"; import ReactDOM from "react-dom"; import { TransProvider, useI18n } from "use-mini18n"; import "./styles.css"; const i18n = { en: { Hello: "Hello {name}", "Start editing to see some magic happen!": "Start editing to see some magic happen!" }, ja: { Hello: "こんにちは {name}", "Start editing to see some magic happen!": "いくつかの魔法を目にするために編集を開始します!" } }; const App = () => { const { t, lang, langs, changeLang, getText } = useI18n(); return ( <div className="App"> <h1>{getText("Hello", { name: "CodeSandbox" })}</h1> <h2>{t["Start editing to see some magic happen!"]}</h2> <hr /> <p>Selected lang: {lang}</p> <select name="lang" onChange={({ target }) => changeLang(target.value)} value={lang} > {langs.map((l, i) => ( <option value={l} key={i}> {l} </option> ))} </select> </div> ); }; const rootElement = document.getElementById("root"); ReactDOM.render( <React.StrictMode> <TransProvider i18n={i18n}> <App /> </TransProvider> </React.StrictMode>, rootElement );開発者が
use-mini18n
でやれることは、このサンプルコードに記載されていることだけです。
いくつかの細かなオプションも用意してあるので、そちらについてはリポジトリ内のREADME、もしくはexamplesを参照してください。また、
use-mini18n
はデフォルトで、ユーザの希望した言語設定をブラウザのlocalStorage
に保存します。
私がこのような設計にしたのは、開発者として言語設定の管理に一切時間を割きたくなかったからです。
もしそのような動作を望まない場合は、localStorage
を利用しないオプションも存在しています。<TransProvider i18n={i18n} enableLocalStorage={false}> <App /> </TransProvider>これで
use-mini18n
に関する話は終わりとなります。
use-mini18n
のミニマムな世界観には満足しています。このライブラリはi18n関連のすべてをカバーしているわけではありませんが、それはそれで良いと考えています。
もしuse-mini18n
が力不足だと感じるときがあれば、そのときは他の素晴らしいi18nライブラリに切り替えるときだと考えています。もしバグや疑問点などありましたら、上に貼ったGitHubリポジトリか、こちらのポストに直接コメントを頂けたらと思います。
というわけで、サクッとi18n対応を行うためのReact hooksライブラリを作ってみた、という内容でした。
最後まで読んでいただき、ありがとうございます!
- 投稿日:2020-09-28T19:53:24+09:00
【vue-moment】vueでtimer設定する方法
目次
・vueでtimer設定をしたい
・timer設定するために必要なもの
・vue-momentのインストール
・vue-momentのtsファイル作成
・moment.tsを読み込む
・vueファイルでmomentを試してみる
・momentでtimer設定を試してみるvueでtimer設定をしたい
vueで一定期間表示する枠や時期が来たら表示または非表示にするためにタイマー設定をして実装したい場合ってありますよね?
実際、私はその事例に当たったので今回対応したことをお伝えしたいと思います。timer設定するために必要なもの
vueでtimer設定するために
vue-momentを使用します。
vue-momentは、日付の解析・検証等をするライブラリで、
日付のフォーマットを「YYYY-MM-DD」に変更した場合や、日付の期間を検証するのに便利なメソッドが揃っています。
Vue.jsプロジェクトに便利なmoment.jsフィルターを提供してくれます。vue-momentのインストール
npm
$ npm install vue-momentyarn
$ yarn add vue-momentインストールが終わったら共通で使えるようにjsファイルを作成します。
vue-momentのtsファイル作成
src/plugins/moment.tsimport Vue from 'vue' Vue.use(require('vue-moment'))ファイルを作成したらnuxt.configで読み込んでおきましょう。
moment.tsを読み込む
nuxt.config.tsplugins: [{ src: '~/plugins/moment.ts' }],pluginsに先ほど作成したmoment.tsを読み込んでおきます。
ここまでできたらあとは、vue側での実装です。
vueファイルでmomentを試してみる
<template> <p> {{ now }} </p> <p> {{ end }} </p> </div> </template> <script> export default { data() { return { now: this.$moment().format('YYYYMMDDHHmmss'), end: this.$moment().format('20200825150000'), } }, } </script>このようなファイルを作ると
nowは今の日時・時間・分・秒まで取得します。
今回はendとしてますが、表示を開始するなどの場合はstartなどにするといいと思います。
endには表示を終了する日時・時間・分・秒を設定しておきます。この状態で上記を表示すると
See the Pen vue-moment by miyawash (@miyawash) on CodePen.
これをベースにタイマー設定をしてみます。
momentでtimer設定を試してみる
<template> <p> {{ now }} </p> <p> {{ end }} </p> <p v-if="now < end">まだ設定時間ではない</p> <p v-else>設定時間をすぎた</p> </div> </template> <script> export default { data() { return { now: this.$moment().format('YYYYMMDDHHmmss'), end: this.$moment().format('20200825150000'), } }, } </script>このように実装すると設定時間までは
「まだ設定時間ではない」が表示され、設定時間後は「設定時間をすぎた」が表示される
これにより、設定時間までの表示や設定時間からの表示などができるようになりました!See the Pen vue-moment timer by miyawash (@miyawash) on CodePen.
参考資料
https://classic.yarnpkg.com/ja/package/vue-moment
https://www.npmjs.com/package/vue-moment
https://momentjs.com/
https://qiita.com/taizo/items/3a5505308ca2e303c099
https://blog.capilano-fw.com/?p=908#24_8_20
- 投稿日:2020-09-28T19:44:07+09:00
QiitaAPIで20年投稿のストック数が多い記事のタグ情報を調べてみた
はじめに
ほとんどプログラミング経験のない初心者(VB.Netを少しかじった程度)ですが、最近「モノをつくる」学習の場を与えて貰えたので、自分なりに色々調べて、JavaScriptにチャレンジしてみました。記事の投稿も初で、初めて尽くしで戸惑ってます。。
ソースコードがキレイじゃないのもご愛敬。目的
Node.jsとQiitaAPI(+axios)を使って今の自分に何ができるか考えてみた。
で、今回は、「今年(2020年)に投稿された記事で、ストック数の多い記事のタグってどんなの?」を調べてみました。
(ストック数が多い記事として、今回はストック数が300以上の記事を対象としてみた。)コード
QiitaAPI.js// axiosモジュールの読み込み const axios = require('axios'); axios.defaults.baseURL = 'https://qiita.com/api/v2'; let array1 = []; // タグ名用 let array2 = []; // カウント用 // main関数 async function main(page) { // QiitaAPIからレスポンス受け取り(ストック>=300 + 作成日>=2020-01 の記事一覧) let response = await axios.get( '/items?page=' + page + '&per_page=100&query=stocks:' + encodeURIComponent('>=300') + '+created:'+ encodeURIComponent('>=2020-01') ); // 取得した記事から[tags]要素を取得 for (let i=0; i<response.data.length; i++) { for (let j=0; j<response.data[i].tags.length; j++) { var tagname = response.data[i].tags[j].name; // タグ名取得 // 配列に登録があれば、カウントを+。登録が無いなら配列に追加。 var result = array1.indexOf( tagname ); // 検索(既に配列にあるか) if (result < 0) { array1.push(tagname); array2.push(1); } else { array2[result] += 1; } } } // 結果出力 if (page==5) { for (let i=0; i<array1.length; i++) { console.log(array1[i]+', '+array2[i]); } } } // main関数 実行 let promise = Promise.resolve(); for (let k=1; k<6; k++) { promise = promise.then(() => main(k)); }色々ハマった点
1.QiitaAPIって何がとれるのさ?
QiitaAPIの仕様書を読み込んでみた。(色々取れそうだけど、技術力が追い付かないので断念。)
最初におや?と思ったのは、1回のレスポンスで最大100件、ページ指定も最大100ページ。つまり、1万件まで。
100件以上を取ろうと思うとページを何度か呼び出すしかないのかな。ってことで、main関数をループすることにした。let response = await axios.get( '/items?page=' + page + '&per_page=100&query=stocks:' + encodeURIComponent('>=300') + '+created:'+ encodeURIComponent('>=2020-01') );2.非同期処理ってなんぞや?
ループしようと思ったはいいけど、上手くいかない。
どうも非同期処理で走るからって理由らしい。正直良く分かってないが、以下サイトを参考に改善してみた。
PromiseによるJavaScript非同期処理レシピ集let promise = Promise.resolve(); for (let k=1; k<6; k++) { promise = promise.then(() => main(k)); }結果
結果は、EXCELで集計。
(あまり細かくなってもアレなので、表は上位10件、グラフは記事数7件以上を表示。)
※2020年に投稿された記事で、ストック数が300以上の記事についてタグを集計
タグ 記事数 JavaScript 67 Python 58 初心者 49 機械学習 24 新人プログラマ応援 24 HTML 16 DeepLearning 16 GitHub 16 Vue.js 16 React 16 考察
Qiitaトップのタグ・ランキングとはまた違った結果になった。
上位の「JavaScript」「Python」は、今年も熱い。ストック数も多いということは、興味関心が高く、役立つ情報がまだまだあるってことかなぁ。興味深いのは、タグ・ランキングでは上位の「Ruby」がランク外。
最近の投稿が少ないか、ストック数が伸びないのか、、、??最後に
JavaScriptの学習も兼ねて今回はチャレンジしてみましたが、もっとより良いアプローチがある気がしました。
そもそも、私の技術力の無さを痛感。(書いてませんが色々断念してます。。。)
まずは書く!調べる!やってみる!
トライアンドエラーで今後も素人ながら挑戦していきます。
- 投稿日:2020-09-28T19:37:52+09:00
【忘備録】すぐ忘れるからwebpackについてまとめておく
- 投稿日:2020-09-28T19:13:21+09:00
【忘備録】npmがふわふわしてるから、軽くまとめておく。
- 投稿日:2020-09-28T18:47:29+09:00
GatsbyJS ローカルで開発中のページをスマホでも見る方法
- 投稿日:2020-09-28T17:33:29+09:00
FetchでExcelファイルがダウンロードできるページに条件をPOSTしてブラウザダウンロードする
やりたいこと
タイトル通りなんですが、いろいろ調べてみても直接ファイルが落ちてこなくて試行錯誤してたどり着いたやつです。
少しだけ解説
headersとしてheaderの内容を記載するのですが、AcceptにExcelであること、responseTypeにblob形式であることが重要なようです。
またfetchで返ってきた値をblob()で処理するとファイル形式(バイナリ形式)として扱われるので無理くりリンク作ってクリックさせています。
https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
https://developer.mozilla.org/ja/docs/Web/API/Body/blobexample.jsvar filename = 'excelfile'; var obj = { fname: filename, format: 'XLSX' }; var method = "POST"; var body = Object.keys(obj).map((key)=>key+"="+encodeURIComponent(obj[key])).join("&"); var headers = { 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8', 'responseType' : "blob", }; fetch("アクセスするURL", {method, headers, body}) .then((res)=> res.blob()) .then(blob => { let anchor = document.createElement("a"); anchor.href = window.URL.createObjectURL(blob); anchor.download = filename+".xlsx"; anchor.click();}) .then(console.log) .catch(console.error);参考にさせていただきました
- 投稿日:2020-09-28T16:44:33+09:00
【改訂】Gatsbyでページごとに個別にCSSを読み込む方法
はじめに
HTML, JavaScript, CSSで構築された既存のサイトを、Gatsbyで再構築しています。
以前、Gatsbyでページごとに個別にCSSを読み込む方法という記事を書きました。
しかし、その後作業を進めていくうちに、こちらの方法では問題を解決できないことがわかりました。
今回は改めて対策方法を検討したので、共有します。前回の内容
前回はこのような方法でページごとに個別にCSSを読み込むことができると言いました。
import React from "react" export default () => ( require("style.css") )しかし、この内容でNetlifyにアップロードしたところ、うまくいきませんでした。
個別ページで読み込んだハズのCSSが、全てのページで読み込まれてしまい、上書きされてしまうという現象が再発してしまいました。Gatsby Develop と Gatsby Serve の違い
原因を調べると、上記の方法は
gatsby develop
ではうまく動作するものの、
gatsby serve
したものではうまく動作していませんでした。
Netlifyにアップロードされるのはgatsby serve
の方です。新・ページごとに個別にCSSを読み込む方法
とういうことで、
gatsby serve
でもうまくいく方法を紹介します。
- 既存のCSSの拡張子
.css
を.scss
に変更する- ファイルを開き、先頭と末尾を
html.hoge{}
で囲むhoge.css#header{ background-color:red; }hoge.scsshtml.hoge{ #header{ background-color:red; } }3.読み込みたいページ(例:hoge.js)で
import
するhoge.jsimport React from "react" import "../css/home.scss" export default () => { return( //ページの処理 <header id="header">ヘッダー</header> ) }4.「Helmet」を使ってhtmlタグに
hoge
というクラス名を付けるhoge.jsimport React from "react" import { Helmet } from "react-helmet" import "../css/home.scss" export default () => { return( <div> <Helmet> <html className="hoge" lang="jp" /> </Helmet> //ページの処理 <header id="header">ヘッダー</header> </div> ) }以上です。
Helmetの使い方は「Gatsby Helmet」などで調べてみてください。おわりに
今回のやり方はかなり邪道な方法です。
お気づきかもしれませんが、このやり方はページ毎に個別に読み込んではおらず、
結局全てのCSSを読み込んでしまっています。
単純に、SCSSのネストでセレクタを指定することで、ページごとに適応するものを変えているだけです。
Gatsbyが提唱するサイトの高速化の手法をあえて無視するようなやり方です。今回はとりあえず、一般的な HTML, CSS, JavaScript で組まれたWEBサイトを
あまり手を加えずにGatsbyにコンバートすることを試してみました。
ですが、その作業がこんなにも大変だとは思いませんでした。WordPressみたいに、最初は静的ファイルでテストページを作成して、その後CMS化する
という手法はあまり馴染まないのかもしれないですね。ある程度初期の段階から、Gatsbyで組み上げていったほうが早いかもしれません。
次回は、GatsbyでjQueryを使う方法(邪道)を書きたいと思います。
- 投稿日:2020-09-28T16:26:28+09:00
jQuery Validationで分岐処理
Webページの状態によって入力チェックの内容を変更する
validation
ってif分岐出来ないんですか?と聞かれて調べたのでメモここ
に書かれていました。$("#sample").validate({ rules : { name : { required : $("#flag").val() == "0" } },の様に書けば良いらしいです。
例えば、
required
であれば上記の様にboolean
で返るようにする。
maxlength
であれば以下の様にnumber
になるようにすれば良いのかな?maxlength: function () { if ($("#name").val == "jugemu") { return 200 } else { return 100 } }試していないです。。
if分岐ではないですが、処理を分けることはできそうです。
- 投稿日:2020-09-28T14:06:35+09:00
Javascriptでボタンのクリックを待ち受ける方法
ボタンが押されるまで待ち受けて、押されたボタンの種類を返す処理
waitForClick() { return new Promise((resolve, reject) => { document.getElementById('button1').onclick = () => resolve('button1'); document.getElementById('button2').onclick = () => resolve('button2'); }); } const result = await waitForClick();
- 投稿日:2020-09-28T13:43:12+09:00
npm-scriptsをnpm-run-allで用途や環境毎に書く際の小技
- Web開発の際のタスク処理として、
package.json
内に記述して利用できるnpm-scriptsを利用しています。- またその際に、複数処理の直列化や並列化に便利なnpm-run-allを利用しています。
- 今回はそれを用いた用途や環境毎への記述を、明確かつ柔軟にする方法を記録します。
結果
- 先に結果の記述を示します。以下の通りです。
{ "scripts": { "build" : "run-s build:{sass,ts}", "build:sass" : "sass input.scss output.css", "build:ts" : "tsc main.ts", "watch" : "run-s watch:{sass,ts}", "watch:sass" : "sass --watch input.scss output.css", "watch:ts" : "tsc -w main.ts" } }内容
- 上記の結果例は、主にbuildとwatchを行うタスクです。
- こちらで利用している方法は、処理内容を波括弧で指定するということです。
波括弧での指定
- コロン(:)で用途毎に分けたタスクを一回で実行する際には、以下のようなやり方があります。
{ "scripts": { "build-basic" : "run-s build:sass build:ts", "build-glob" : "run-s build:*", "build-brace" : "run-s build:{sass,ts}", "build:sass" : "sass input.scss output.css", "build:ts" : "tsc main.ts", } }
- これらから私はbuild-braceのような波括弧で指定した方法を利用しています。
- そのメリットは以下の通りです。
- 非重複
run-s build:sass build:ts
のように言葉の重複が無く、今後同一のタスクが増えても、用途の記述だけで済む。- 明示化
run-s build:*
のようなアスタリスク指定と比べて、明示的に記述されているため、処理の内容が理解しやすい。- 順序化
- 波括弧内の順に処理を行ってくれるため、仮に
package.json
内でbuild:sass
とbuild:ts
を逆に記述しても問題無い。
run-s build:*
での指定では、処理順番がpackage.json
内の並び通りに行われるため、逆に記載してしまうとその順になってしまう。まとめ
- 上記のことから、タスクやscript記述においても可読性・明示化・非重複性を再認識しました。
参考
- npm-run-all
- https://www.mitsue.co.jp/knowledge/blog/frontend/202004/14_1408.html
package.json
のスクリプト例に使わせていただきました。
- 投稿日:2020-09-28T10:01:31+09:00
[Javascript] Const, Let, Varの違い(ES6関連)
Javascriptの変数
Javascriptには、変数を宣言するキーワードの
const
、let
、var
があります。
これらのキーワードは以下について違いがあります。・初期値
・重複した値割り当て
・呼び出し範囲まずconst, let, var すべての変数は下記のように
、コンマで区切って複数の変数を定義することができます。const category= "header", key= "content-Type", value= "application/json";Constについて
const
は値が変わらない変数を宣言するキーワードです。
const
は必ず初期値を設定しなければならず、
宣言した変数に対して、あとで値を割り当てることはできません。
const
で宣言した変数に値を再度割り当てる場合には、
次のようなエラー(TypeError)が発生します。const key = "content-Type"; key = "appId"; // Result => TypeError: invalid assignment to const 'key'変数に値を割り付ける必要がない場合には、
const
キーワードで変数宣言することを推奨します。ループなどの繰り返しの途中で特定変数が参照する値を変えなければならないときがあります。
その場合は変数に再割り当てできるlet
キーワードで宣言します。Letについて
let
は初期値を指定しなくても大丈夫です。
初期値を指定しない場合、undefined 値に初期化されます。let key; // `key` is initialized `undefined`
let
が宣言されたkey
という変数に"content-Type"
という文字列を代入しています。let key; key = "content-type";Varについて
var
キーワードは初期値を宣言しなくてもよく、
値を再割り当てしても良いという点でlet
に似ています。
しかし、var
キーワードは同じ名前の変数を定義し直すことができます。
let
とconst
は同じ名前の変数を定義することができず、
次のような構文エラー(Syntax Error
)が発生します。
したがって、ミスとして変数を二重に定義するミスを防ぐことができます。let key; let key; // => SyntaxError: redeclaration of let key
var
の場合には、同じ名前の変数を定義し直すことができます。
これは間違いで同じ変数の名前で定義しても間違いはなく、
以前に宣言した値を閉じてしまいます。var x = 1; var x = 2; // x is 2
let
は、変数を宣言する前にその変数を参照するとReferenceError
が発生します。console.log(x); //ReferenceError: can't access lexical declaration `x' before initialization let x = 1;
var
は変数を宣言する前に、その変数を参照してもundefined
値が割り当てられます。console.log(x); // => undefined var x = 1;まとめ
JavaScriptは変数を宣言するキーワードとして、
const
、let
、var
についてまとめました。・
const
は値を再割り当てできない変数を宣言する時に使用されます。
・let
、var
は再割り当てできる変数を宣言することができ、
初期値を宣言しなくてもかまいません。
・var
の場合のみ、同じ値を重複宣言することができます。
const
は再割り当て不可能な変数を定義するキーワードです。
再割り当てを禁止することで、誤って他の値を割り当てることで発生するバグを減らすことができます。したがって、変数を宣言する場合には、まず
const
で定義できないかを検討の上、
不可能な場合はlet
の使用をお勧めします。
- 投稿日:2020-09-28T08:44:25+09:00
Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #5 ログイン・ログアウトの実装
←Nuxt.jsで認証認可入り掲示板APIのフロントエンド部分を構築する #4 サインアップページの作成
ログアウト機能の実装
先にログアウトを作ります。
layouts/default.vue... <v-btn v-if="logged_in" icon + @click="logOut" > <v-icon>mdi-logout</v-icon> </v-btn> ... export default { ... this.$store.commit('setAuth', {}) }) } + }, + methods: { + logOut () { + this.$store.dispatch('logOut') + } } } </script>store/index.js... export const actions = { async signUp (_c, user) { return await this.$axios.$post('/v1/auth', user) + }, + async logOut ({ commit }) { + await this.$axios.$delete('/v1/auth/sign_out') + commit('setUser', null) + commit('setAuth', {}) + + this.$router.push('/') } }
v1/auth/sign_out
することでバックエンドでログアウトとします。
そしてフロントエンド側もstoreから削除し(同時にlocalStorageもクリアされます)、トップページに飛ばします。ログイン機能の実装
$ touch pages/log_in.vuepages/log_in.vue<template> <v-app id="inspire"> <v-main> <v-container class="fill-height" fluid > <v-row align="center" justify="center" > <v-col cols="12" sm="8" md="4" > <form @submit.prevent="logIn"> <v-card class="elevation-12"> <v-toolbar color="primary" dark flat > <v-toolbar-title>LogIn form</v-toolbar-title> </v-toolbar> <v-card-text> <ul v-if="errors"> <li v-for="(message, i) in errors" :key="i"> {{ message }} </li> </ul> <v-text-field id="email" v-model="email" label="email" name="email" prepend-icon="mdi-email" type="email" /> <v-text-field id="password" v-model="password" label="Password" name="password" prepend-icon="mdi-lock" type="password" /> </v-card-text> <v-card-actions> <v-spacer /> <v-btn color="primary" type="submit"> ログイン </v-btn> </v-card-actions> </v-card> </form> </v-col> </v-row> </v-container> </v-main> </v-app> </template> <script> export default { data () { return { email: '', password: '', errors: [] } }, methods: { async logIn () { try { const data = await this.$store.dispatch('logIn', { email: this.email, password: this.password }) this.$store.commit('setUser', data.data) this.$router.push('/') } catch (e) { this.errors = e.data.errors } } } } </script>store/index.js... export const actions = { ... async logOut ({ commit }) { await this.$axios.$delete('/v1/auth/sign_out') commit('setUser', null) commit('setAuth', {}) this.$router.push('/') + }, + async logIn (_c, user) { + return await this.$axios.$post('/v1/auth/sign_in', user) }layouts/default.vue... <v-icon>mdi-account-plus</v-icon> </v-btn> + <v-btn + v-if="!logged_in" + icon + to="/log_in" + nuxt + > + <v-icon>mdi-login</v-icon> + </v-btn> </v-app-bar> ...ほとんどsignUpのコピペでいけます。
これでログイン周りの必要最低限の機能は揃いましたね。
次回は連載最終回。記事の投稿・削除を行います。
続き
→
【連載目次へ】
- 投稿日:2020-09-28T00:53:08+09:00
FlaskにAjaxリクエストのFetch APIを組み込んだシンプルなアプリを作成してさくっと説明する
はじめに
・Flask と JavaScript を勉強し始めた方向けとなります
・TheCatAPI.com : Betaを使用して、猫の画像をAjaxリクエストで取得するアプリを作成しますFetch API で猫の画像を取得するFlaskアプリを作成する
Flaskを用意します。
Flaskがまだちょっとよくわからないという方は以下の記事を確認してください。
【Pythonで多分人気2位のWebアプリケーションフレームワーク】Flaskの基本をわかりやすくまとめる構成は以下です。
app.py templates └─hello.htmlapp.pyfrom flask import Flask, render_template app = Flask(__name__) @app.route('/') def hello_world(): return render_template('hello.html') if __name__ == "__main__": app.run(debug=True)hello.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>hello</title> <h1>hello</h1> </head> <body> </body> </html>上記でFlaskを起動させるとブラウザ上で以下の画面が出ます。
JavaScript内でAPIをたたく版
それではFetch APIで猫の画像を表示させていきます。
ボタンをクリックして猫の画像を出すようにします。HTMLの全体のコードが以下です
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>hello</title> <style> .w300 { width: 300px; } </style> </head> <body> <form id="form"> <div id="image"></div> <button id="lookCatButton" type="button">猫見る</button> </form> <script> const url = 'https://api.thecatapi.com/v1/images/search?size=full'; const options = { method: 'GET' } function getCatImage(url, options){ return fetch(url, options) .then( response => response.json() ); } async function getImage(url, options){ const response = await getCatImage(url, options); const imageDiv = document.getElementById("image"); const imageElement = document.createElement("img"); imageElement.src = response[0].url; imageElement.className = "w300"; imageDiv.appendChild(imageElement); } document.getElementById("lookCatButton") .addEventListener("click", () =>{ getImage(url, options) }) </script> </body> </html>説明
Fetch API では1つ目の引数にリクエスト先のURL、2つ目にoptionsを設定できます。
今回は以下のようにURLとoptionsを定義します。const url = 'https://api.thecatapi.com/v1/images/search?size=full'; const options = {method: 'GET'};optionsではリクエストのメソッドとしてGETを指定します。
optionについて詳しく知りたい方は以下を参照すると良いです。
https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch
https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/fetchfetchの返り値はpromiseで返ってくるため、.then()メソッドが使えます。
かつ.then()ではコールバック関数が使えるので、中にアロー関数で引数が1つなので () を省略し、かつ唯一のステートメント return なので {} を省略して書いています。fetch(url, options) .then( response => response.json() );省略しないアロー関数で書くと以下のようになります。
fetch(url, options) .then( (response) => { return response.json() });fetchを使用する際、リクエストを送ってレスポンスが返ってくる前に、その後ろに書いたコードが実行されることがあります。
そのためasyn/awaitを使用して、fetch を実行してレスポンスが返ってきてから後続のコードを実行させるようにしています。asyncファンクションを定義して、その中でfetchを使用した関数にawaitを付けて変数に入れます。以下の箇所です
async function getImage(url, options){ const response = await getCatImage(url, options);その後に猫ちゃんの画像URLをappendChildして表示させるようにしています。
一連の処理はボタンをクリックしてから実行させるようにしているため、addEventListenerでclickされたら実行するようにしています。
document.getElementById("lookCatButton") .addEventListener("click", () =>{ getImage(url, options) })これでボタンを押すたびに猫ちゃんの画像が表示されるようになりました。
あえてpython側でAPIたたく版
上述の通り、fetchでは1つ目の引数にリクエストを送るURLが必要であるため、Flaskのルーティングでリクエスト先のURLを作成します。
そこで猫ちゃんAPIのデータを取得するコードと、レスポンスとして返す際にjsonでダンプさせるためにjsonifyでreturnします。以下のコードにしました。
/get_dataを追加しています。from flask import Flask, render_template, jsonify import requests app = Flask(__name__) @app.route('/get_data') def get_data(): url = 'https://api.thecatapi.com/v1/images/search?size=full' #猫ちゃんAPI response = requests.get(url) cat_img_url = eval(response.text)[0]['url'] #ここでイメージURLを取得 response_data = { 'cat_img_url' : cat_img_url } return jsonify(response_data) #jsonifyでjs側に返却する @app.route('/') def hello_world(): return render_template('hello.html') if __name__ == "__main__": app.run(debug=True)JavaScript側では、リクエスト先のURLを、先ほど設定したルーティング先の ./get_data に変更します。
const url = './get_data';pythonからはjsonにダンプされた値が入るため、python側で設定した「cat_img_url」を取得するようにします。
imageElement.src = response.cat_img_url;それ以外はすべて同じにして、全体では以下のコードとなります。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .w300 { width: 300px; } </style> </head> <body> <form id="form"> <div id="image"></div> <button id="lookCat" type="button">猫見る</button> </form> <script> const url = './get_data'; const options = { method: 'GET' } function getCatImage(url, options){ return fetch(url, options) .then( response => response.json() ); } async function getImage(url, options){ const response = await getCatImage(url, options); const imageDiv = document.getElementById("image"); const imageElement = document.createElement("img"); imageElement.src = response.cat_img_url; imageElement.className = "w300"; imageDiv.appendChild(imageElement); } document.getElementById("lookCat") .addEventListener("click", () =>{ getImage(url, options) }) </script> </body> </html>これでボタンををクリックすると、python側で画像イメージを取得して表示させることができます。
ちなみに今回追加したルーティング先を直接アクセスしてみると以下の内容が表示されます。
おわりに
今回python側でリクエストするのとJavaScript側でリクエストするパターンの2つでfetch リクエスト、レスポンスをしてみたのは頭の整理としてとても良かったです。
参考文献
最新Ajaxリクエスト通信、Fetch APIについてメモ
【Pythonで多分人気2位のWebアプリケーションフレームワーク】Flaskの基本をわかりやすくまとめる
MDN web docs - Fetch API
MDN web docs - Fetch の使用
MDN web docs - Callback function (コールバック関数)
MDN web docs - アロー関数
MDN web docs - async function
- 投稿日:2020-09-28T00:10:03+09:00
お手頃高機能スライダーはSwiper使っておけばいい
概要
実装をする中で実装可能だけど、そこに時間あんまり費やしたくないなぁって時結構ありますよね。
画像のスライダー機能の実装でそのような状況になりました。
自作実装もできるけど。。アニメーションを場面ごと切り替えたりするのが結構手間><
そこで、よく使われているライブラリを探していたところSwiper
を見つけて実装がとても楽だったので共有したいと思います。実装例
スライダーで使うcssをimportする
index.tsximport "swiper/swiper.scss"; import 'swiper/components/pagination/pagination.scss';スライダー用のコンポーネントを実装する
SwiperComponent.tsximport * as React from 'react'; import SwiperCore, { Pagination, Autoplay } from "swiper"; import { Swiper, SwiperSlide } from "swiper/react"; SwiperCore.use([Pagination, Autoplay]); interface Props { imageData: Array<string>; // trueで自動でスライダーアニメーションが動く isAuto: boolean; // trueでpaginationクリックでスライダーアニメーションが動く clickable: boolean } const SwiperComponent: React.FC<Props> = (props) => { return ( <div> <Swiper pagination={{ clickable: props.clickable }} autoplay={props.isAuto}> {props.imageData.map((imageSrc, i) => { return ( <SwiperSlide key={`${imageSrc}${i}`}> <img key={`${imageSrc}`} src={imageSrc} /> </SwiperSlide> ); })} </Swiper> </div> ); }; export default SwiperComponent;これだけ!!
あとはスライダー用のコンポーネントをスライダー実装したい箇所に組み込んであげるだけ!
<SwiperComponent imageData={["image/image1.jpg", "image/image2.jpg"]} isAuto={true} clickable={false} />これで画像スライダーの完成!
とても簡単。他にも便利な機能が山ほどあります。
スライドアニメーションもたくさんありますので色々と試してみるといいかもです。まとめ
今回は一番シンプルなスライダーを
Swiper
を使って簡単な実装例と共に紹介しました。
ちょっと実装に時間かかりそうなところがめちゃくちゃシンプルに実装できましたね。
Vueにも対応しているみたい※注意点
ライブラリは便利な反面、何気なく使ってしまうと危険な時があります。
急に開発元が開発をやめたり、特定のバージョンや環境でしか動かなこともザラにあります。
ライブラリを使うときはドキュメントをしっかり読み、ライセンスの確認、使っているユーザーの数(githubスターの数)
さらには開発状況などを確認した上で慎重に使うことをお勧めします。
個人で試す、勉強で使う場合は問題ないと思いますが、
仕事として今後世に出ていくようなサービスで使う場合はその辺りは意識してライブラリは使っていくといいと思います。参照
- 投稿日:2020-09-28T00:10:03+09:00
お手頃・高機能スライダーはSwiper使っておけばいい
概要
実装をする中で実装可能だけど、そこに時間あんまり費やしたくないなぁって時結構ありますよね。
画像のスライダー機能の実装でそのような状況になりました。
自作実装もできるけど。。アニメーションを場面ごと切り替えたりするのが結構手間><
そこで、よく使われているライブラリを探していたところSwiper
を見つけて実装がとても楽だったので共有したいと思います。実装例
スライダーで使うcssをimportする
index.tsximport "swiper/swiper.scss"; import 'swiper/components/pagination/pagination.scss';スライダー用のコンポーネントを実装する
SwiperComponent.tsximport * as React from 'react'; import SwiperCore, { Pagination, Autoplay } from "swiper"; import { Swiper, SwiperSlide } from "swiper/react"; SwiperCore.use([Pagination, Autoplay]); interface Props { imageData: Array<string>; // trueで自動でスライダーアニメーションが動く isAuto: boolean; // trueでpaginationクリックでスライダーアニメーションが動く clickable: boolean } const SwiperComponent: React.FC<Props> = (props) => { return ( <div> <Swiper pagination={{ clickable: props.clickable }} autoplay={props.isAuto}> {props.imageData.map((imageSrc, i) => { return ( <SwiperSlide key={`${imageSrc}${i}`}> <img key={`${imageSrc}`} src={imageSrc} /> </SwiperSlide> ); })} </Swiper> </div> ); }; export default SwiperComponent;これだけ!!
あとはスライダー用のコンポーネントをスライダー実装したい箇所に組み込んであげるだけ!
<SwiperComponent imageData={["image/image1.jpg", "image/image2.jpg"]} isAuto={true} clickable={false} />これで画像スライダーの完成!
とても簡単。他にも便利な機能が山ほどあります。
スライドアニメーションもたくさんありますので色々と試してみるといいかもです。まとめ
今回は一番シンプルなスライダーを
Swiper
を使って簡単な実装例と共に紹介しました。
ちょっと実装に時間かかりそうなところがめちゃくちゃシンプルに実装できましたね。
Vueにも対応しているみたい※注意点
ライブラリは便利な反面、何気なく使ってしまうと危険な時があります。
急に開発元が開発をやめたり、特定のバージョンや環境でしか動かなこともザラにあります。
ライブラリを使うときはドキュメントをしっかり読み、ライセンスの確認、使っているユーザーの数(githubスターの数)
さらには開発状況などを確認した上で慎重に使うことをお勧めします。
個人で試す、勉強で使う場合は問題ないと思いますが、
仕事として今後世に出ていくようなサービスで使う場合はその辺りは意識してライブラリは使っていくといいと思います。参照