- 投稿日:2020-06-26T23:46:13+09:00
とにかく、つかえるJS?JC?JK?あげるとかいうのいい?
Date.prototype.JST=function(){this.setTime(this.getTime()+(9*60*60*1000));return this}
これ?いいとおもう。
- 投稿日:2020-06-26T23:09:24+09:00
Jestでモジュールの特定の関数だけモックする
Jestでモジュールをモックするのは便利ですが、モジュールの一部をモックしたい場合に困ることがあります。
// my-module.js export function foo() { ... } export function bar() { ... } // bar だけモックしたいimport { foo, bar } from "./my-module"; jest.mock("./my-module", () => ({ bar: jest.fn(), })); describe("foo", () => { it("works", () => { expect(foo("yay")).toEqual("wow"); }); });上記のように書いた場合に、
TypeError: foo is not a function
といったエラーになってしまいます。それを回避するには以下のように書きます。jest.mock("./my-module", () => ({ ...jest.requireActual("./my-module"), // foo: jest.requireActual("./my-module").foo でも可 bar: jest.fn(), }));Jest的に認められた書き方なのかは怪しいですがとりあえず
bar
をモックしてfoo
はモックせず動かせます参照
https://github.com/facebook/jest/issues/936#issuecomment-613220940
https://jestjs.io/docs/en/jest-object#jestrequireactualmodulename
- 投稿日:2020-06-26T23:08:34+09:00
Reactアプリ - 文章中キーワード黒塗りはがし
はじめに
Reactを使って文章中の特定のキーワードの黒塗り文字列をクリックして黒塗りをはがして読めるようにするアプリを作りましたので紹介いたします。
このアプリは単純で、黒塗りをはがすためにはキーワードの黒塗り部分をクリックします。再びキーワードをクリックすると黒塗りに戻ります。
前提条件
node.jsがインストールされている事が必要です。まだインストールしていない場合には、インストールしておいてください。
Reactプロジェクトを作成します
以下のように
create-react-app
コマンドを実行します。少し、時間がかかります。
- macOS
terminal(base) macpro:dev teruroom$ cd /Users/teruroom/dev/react/ (base) macpro:react teruroom$ npx create-react-app blackout-peeling
- Windows10
powershellPS C:\> cd C:\dev\react\ PS C:\dev\react\> npx create-react-app blackout-peelingmacOS実行結果Creating a new React app in /Users/teruroom/dev/react/blackout-peeling. ・・・・・・・・途中省略・・・・・・・・・・・ Success! Created react-boardgame at /Users/teruroom/dev/react/blackout-peeling Inside that directory, you can run several commands: npm start Starts the development server. npm run build Bundles the app into static files for production. npm test Starts the test runner. npm run eject Removes this tool and copies build dependencies, configuration files and scripts into the app directory. If you do this, you can’t go back! We suggest that you begin by typing: cd react-boardgame npm start Happy hacking!デフォルトで生成されたファイルを全て削除します
- macOS
terminal(base) macpro:react teruroom$ cd blackout-peeling/src (base) macpro:src teruroom$ rm -f *
- Windows10
powershellPS C:\dev\react> cd .\blackout-peeling\src PS C:\dev\react\blackout-peeling\src> rm -Force *必要なJavaScriptとCSSファイルを作成します
- macOS
terminal(base) macpro:src teruroom$ touch index.css index.js
- Windows10
powershellPS C:\dev\react\blackout-peeling\src> New-Item -type file index.css PS C:\dev\react\blackout-peeling\src> New-Item -type file index.jsJavaScriptとCSSを実装します
以下のようにクラスの階層構造を設計しました
Page
クラス:ページ
|
+--Sentence
クラス:ページ内の文章
|
+--Keyword
クラス:文章内のキーワードindex.jsimport React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; const white = '#fff'; const crimson = '#880E4F'; const marginwidth = '5px'; const fontweight = 'bold'; class Keyword extends React.Component { constructor(props) { super(props); this.state = { value: null, forecolor: blackOutColor, backcolor: blackOutColor, margin: marginwidth, fontweight: fontweight, }; this.changeColor = this.changeColor.bind(this); } changeColor() { const newColor = this.state.backcolor === blackOutColor ? white : blackOutColor; this.setState({ forecolor: blackOutColor, backcolor: newColor }) } render() { return ( <span style={{ color: this.state.forecolor , background: this.state.backcolor , marginLeft: this.state.margin , marginRight: this.state.margin , fontWeight: this.state.fontweight }} onClick={() => this.changeColor()} > {this.props.value} </span> ); } } class Sentence extends React.Component { blackOut(keyString) { return <Keyword value={keyString} />; } render() { return ( <div> <div className="maintitle">ホゲホゲについて</div> <ol> <li className="subtitle">FOO</li> <ul> <li>FOOは、{this.blackOut('BAA')}システムから利用申請し、「{this.blackOut('利用許可')}」を得てから使用する</li> <li>FOOを{this.blackOut('ホゲ')}やハゲによる攻撃から守るため、BOO対策製品を導入する</li> </ul> 一部省略 </ol> </div> ); } } class Page extends React.Component { render() { return ( <div className="page"> <div className="page-sentence"> <Sentence /> </div> <div className="page-info"> <div>{/* status */}</div> <ol>{/* TODO */}</ol> </div> </div> ); } } ReactDOM.render( <Page />, document.getElementById('root') );
- index.css
index.cssbody { width: 1100px; font: 18px "Meiryo", "Century Gothic", sans-serif; margin: 0px; cursor: pointer; } ol, ul { padding-left: 30px; } td { width: 50%; } .maintitle { width: 100%; font-size: 30px; color: #fff; background: cornflowerblue; } .subtitle { width: 95%; font-size: 22px; font-weight: bold; color: rgb(26, 75, 182); background: rgb(210, 210, 211); margin: 4px; padding: 4px; } .page { display: flex; flex-direction: row; } .page-sentence { margin-left: 20px; } .page-info { margin-left: 20px; }React Webアプリを開発用に起動します
terminal(base) macpro:blackout-peeling teruroom$ npm startpowershellPS C:\dev\react\blackout-peeling> npm startWeb ブラウザで http://localhost:3000 が自動的に立ち上がりページが表示されます。以降、VSCodeで実装コードを変更し、保存するたびごとにWeb ブラウザの http://localhost:3000 が自動的に再読み込み(Reload)されるようになります
最適化ビルドを実行します
React Webアプリが完成したら、最適化ビルドを実行してから公開します
- macOS
terminal(base) macpro:blackout-peeling teruroom$ npm run build
- Windows10
powershellPS C:\dev\react\blackout-peeling> npm run build
- 実行結果
macOSの場合
省略Windows10の場合> security-compliance@0.1.0 build C:\dev\react\blackout-peeling > react-scripts build Creating an optimized production build... Compiled successfully. File sizes after gzip: 39.89 KB build\static\js\2.73f5bc0c.chunk.js 5.5 KB build\static\js\main.11e48eb2.chunk.js 782 B build\static\js\runtime-main.623a1e28.js 310 B build\static\css\main.3c6f1d95.chunk.css The project was built assuming it is hosted at /. You can control this with the homepage field in your package.json. The build folder is ready to be deployed. You may serve it with a static server: npm install -g serve serve -s build Find out more about deployment here: bit.ly/CRA-deployReact Webアプリを本番用に起動します
オプション
--host='0.0.0.0'
をつけてコマンドを実行し、インバウンドとして全てのIPアドレスからのリクエストを受け付けるようにします
- macOS ➡️ ubuntsサーバにデプロイ
terminal(base) macpro:blackout-peeling teruroom$ npm start --host='0.0.0.0'
- Windows10 ➡️ Windows Server 2016にデプロイ
powershellPS C:\dev\react\blackout-peeling> npm start --host='0.0.0.0'React Webアプリを利用します
WebブラウザでURL http://192.168.0.16:3000 (192.168.0.16はWebアプリを動かしているPCのIPアドレス)にアクセスします
macOSの場合
デフォルトWebブラウザの
Safari
や後からインストールしたChrome
で表示されますWindows10の場合
デフォルトWebブラウザの
Edge
や後からインストールしたChrome
で表示されます。IE11
では残念ながらそのままでは表示や動作が上手くいきません。react-app-polyfill
ライブラリを別途インストールし、index.js
ファイルの先頭で
import 'react-app-polyfill/ie11';` のようにインポートする必要があります。諸々の都合により
IE11
を既定のブラウザにしている場合には、以下のようにWindowsショートカットなどにURLを仕込んでおいてください。ショートカットを開くとEdge
によりReact Webアプリが開かれるようになりますmicrosoft-edge:http://hoge-foo.ad.baa.co.jp:3000/
- hoge-foo.ad.baa.co.jp:Active Directry内のReact Webアプリを起動しているPCの端末名
黒塗りをクリックすると剥がれてキーワード文字が読めるようになります
- 投稿日:2020-06-26T22:53:43+09:00
CentOS とOSXでphp, fetch,javascriptの挙動が違う
OSXはこれで行けたが、CentOSではダメ
Javascript
function checkNewOrder(uuid) { var res = fetch("./test.php", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ //引数が色々あって...。 }) }).then((response) => { if (response.ok) return response.json(); // レスポンスをテキストとして変換する }).then((rcvData) => { console.log("rcvData", rcvData); //とりあえず確認 if (rcvData.length > 0) { let msg = "新たにデータが入りました<br>\n"; //rcvData[i]["NAME"]とかを使って色々処理 } }); }php
$dbh->beginTransaction(); $stmt = $dbh->query("select * from TableName;"); $stmt->execute(); $dbh->commit(); $result = $stmt->fetchall(PDO::FETCH_ASSOC); echo json_encode($result, JSON_UNESCAPED_UNICODE);CentOSだとJSの
console.log("rcvData", rcvData);
のところで「rcvDataって何?」ってなってしまう。結局こうやって対応できた
Javascript
function checkNewOrder(uuid) { var res = fetch("./test.php", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ //引数が色々あって...。 }) }).then((response) => { if (response.ok) return response.text(); // jsonからtextに変更した }).then((rcvData) => { var rcv = JSON.stringify(rcvData); //JSONオブジェクトに変換 if (rcv.length > 0) { let msg = "新たにデータが入りました<br>\n"; //rcvData[i]["NAME"]とかを使って色々処理 } }); }
response.json();
をresponse.text();
にしてJSON.stringify
でオブジェクト化するとCentOSでOKだった。
OSXとCentOS で挙動が違うのはなぜ?でも、結局こっちかな
function checkNewOrder(uuid) { const response = fetch("./checkNewOrder.php", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ "uuid": ???; //パラメータとか }) }).then((response) => { if (response.ok) return response.json(); // JSON // return response.text(); }).then((response) => { console.log("response", response); //var rcvData=JSON.parse(response); //result.text() だったらこっち //何らかの処理; }); }
- 投稿日:2020-06-26T21:56:41+09:00
JavaScriptをすこーし勉強してみたので書き留める④
最低限の知識一応あるけど、復習も兼ねて書いてみることにするの巻その④
関数宣言と関数式(超ざっくり)
- 関数式
- 実行が関数式に到達された時に作成される。その後から使用できる。
- if文外で変数宣言⇨if文内で関数式を使用して代入する⇨あとで使える
- 関数宣言
- スクリプト/コードブロック全体で使用できる。
- 関数宣言は関数式より早く使えるようになる
- ブロック外だと使えない
アロー関数
アロー関数で書くと...
let func = (arg1, arg2, ...argN) => expression同じのを関数式で書くと...
let func = function(arg1, arg2, ...argN) { return expression; }使ってみよう!こんな感じ。
let sum = (a, b) => a + b; /* アロー関数は次よりも短い形式です: let sum = function(a, b) { return a + b; }; */ alert( sum(1, 2) ); // 3引数一つならかっこ省略でもっと短く。
// 次と同じです // let double = function(n) { return n * 2 } let double = n => n * 2; alert( double(3) ); // 6引数なしならかっこは必須。
let sayHi = () => alert("Hello!"); sayHi();アロー関数は引数式と同じように使用できる。
let age = prompt("What is your age?", 18); let welcome = (age < 18) ? () => alert('Hello') : () => alert("Greetings!"); welcome(); // ok now複数行のアロー関数
let sum = (a, b) => { // 波括弧を使って複数行の関数を書けます let result = a + b; return result; // 波括弧を使った場合、結果を得るには return を使います }; alert( sum(1, 2) ); // 3
雑になってしまった....
ちゃんと書けるようになって理解したら書き直そうかね。
- 投稿日:2020-06-26T21:11:41+09:00
Kinx Tips - UTF8 文字列のフォーマッティング
Kinx Tips - UTF8 文字列のフォーマッティング
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。Kinx で実装したちょっとした小技を紹介。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
そう、ちょっとした小技。
UTF8 文字列のフォーマッティングの問題
C 言語の printf
UTF8 はバイト数と文字幅が一致しないので、"%-20s" とかしても微妙に揃いませんよね。半角カナも試しに使ってみましょう。
#include <stdio.h> int main() { struct fruits { char *name; int price; } fruits[] = { { .name = "りんご", .price = 230 }, { .name = "みかん(1袋)", .price = 450 }, { .name = "グレープフルーツ", .price = 120 }, }; printf("01234567890123456789\n"); for (int i = 0; i < sizeof(fruits)/sizeof(fruits[0]); ++i) { printf("%-20s ... %3d 円\n", fruits[i].name, fruits[i].price); } return 0; }結果はこうなります。
01234567890123456789 りんご ... 230 円 みかん(1袋) ... 450 円 グレープフルーツ ... 120 円基本的にバイト数なので、日本語 3 バイトであれば 3 消費します。したがって幅が縮みます。
Ruby の sprintf
C と同じかと思いきや、違います。
fruits = [ ["りんご", 230], ["みかん(1袋)", 450], ["グレープフルーツ", 120], ] puts "01234567890123456789" fruits.each {|name, price| puts sprintf("%-20s ... %3d 円", name, price) }結果はこうなりました。
01234567890123456789 りんご ... 230 円 みかん(1袋) ... 450 円 グレープフルーツ ... 120 円バイト数ではなく文字数です。日本語も(何バイトであろうと) 1 文字で 1 消費します。なので、表示幅が増えます。文字数なので、半角カナだと実は一致します。
Kinx のフォーマッタ
Kinx では UTF8 の文字幅を確認してフォーマット文字列の数値部分を自動調整します。表示幅として機能します。
var fruits = [ ["りんご", 230], ["みかん(1袋)", 450], ["グレープフルーツ", 120], ]; System.println("01234567890123456789"); fruits.each(&(e) => { System.println("%-20s ... %3d 円" % e[0] % e[1]); });結果はこうなります。
01234567890123456789 りんご ... 230 円 みかん(1袋) ... 450 円 グレープフルーツ ... 120 円Qiita のコードブロックでは等幅で表示されていない感じなので微妙ですが、等幅フォントで見れば縦ラインはきちんと揃っています。東アジア文字幅(East Asian Width)に従って調整するので概ねうまく動くはず 1。
多くの人が期待する動作は コレ ではないでしょうか。
おわりに
なかなか忙しくて記事が書けないとき用に、こういった小ネタもストックしておこう。
ではまた、次回。
- 投稿日:2020-06-26T20:14:59+09:00
IndexedDB + Dexie.js で CRUDの作成、Vue CLI版
概要
IndexedDB で、Dexie.js ライブラリを使用した
CRUD の作成となります。
vue-router と組み合わせて、ほぼサーバレス的な構成にできるか検討してみました。・ブラウザ内の、LocalStorageと似ているイメージで
データは、他のPCから利用できない為。
オフライン機能で、何か作る場合は。良さそうでした・開発の面では、通常DBサービス起動も不要で
Vue-cli サービスのみで。開発できるので準備は楽でした
構成
Vue CLI
dexie : 3.0.1
vue: 2.6.11
vue-router参考
https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API
https://qiita.com/yamayamasan/items/a4297e724b86f4a00fd2
vuex 追加
npm install --save dexiepackage.json
https://github.com/kuc-arc-f/vue_spa3b_1crud/blob/master/package.json
実装など
・db定義
db-name, store ,db-version
storeは、テーブルみたいな扱いのようですvar db = new Dexie("friend_database"); db.version(1).stores({ friends: 'name,shoeSize' });・書く、読み込み
db.friends.put({name: "Nicolas", shoeSize: 8}).then (function(){ return db.friends.get('Nicolas'); }).then(function (friend) { alert ("Nicolas has shoe size " + friend.shoeSize); }).catch(function(error) { alert ("Ooops: " + error); });CRUD の参考
・create
https://github.com/kuc-arc-f/vue_spa3b_1crud/blob/master/src/components/DexieTasks/new.vue・index
https://github.com/kuc-arc-f/vue_spa3b_1crud/blob/master/src/components/DexieTasks/Index.vue・show
https://github.com/kuc-arc-f/vue_spa3b_1crud/blob/master/src/components/DexieTasks/show.vue・edit
https://github.com/kuc-arc-f/vue_spa3b_1crud/blob/master/src/components/DexieTasks/edit.vue
- 投稿日:2020-06-26T20:13:32+09:00
お絵かきできるSNSを作りたい!10
お絵かきできるSNSを作りたい後半戦、1つ前に戻すを作っていきます。
筆跡が分るようにjsonで座標を逐一保存しようかとも考えたのですが、管理が大変そうだったので1ストローク毎にcanvasの中身をスクリーンショットを撮る感じにしました。
まず、対処のボタンにイベントを追加します。
<a href="#" class="btn" onclick="doPrevCanvas();">1つ前に戻す</a>ローカルストレージを用意し、レイヤー1とレイヤー2をそれぞれ1ストローク毎に保存していきます。
// ストレージの初期化 var myStorage = localStorage; function initLocalStorage(){ myStorage.setItem("__layer", JSON.stringify([])); myStorage.setItem("__layer2", JSON.stringify([])); } function setLocalStoreage(){ var png = $("#canvas")[0].toDataURL(); var logs = JSON.parse(myStorage.getItem("__layer")); setTimeout(function(){ logs.unshift({png}); myStorage.setItem("__layer", JSON.stringify(logs)); }, 0); var png2 = $("#canvas2")[0].toDataURL(); var logs2 = JSON.parse(myStorage.getItem("__layer2")); setTimeout(function(){ logs2.unshift({png2}); myStorage.setItem("__layer2", JSON.stringify(logs2)); }, 0); } function doPrevCanvas(){ var logs = JSON.parse(myStorage.getItem("__layer")); if(logs.length > 0){ logs.shift(); setTimeout(function(){ myStorage.setItem("__layer", JSON.stringify(logs)); ct.clearRect(0, 0, $("#canvas").width(), $("#canvas").height()); if (logs.length == 0) { draw("canvas",logs["png"]); } else { draw("canvas",logs[0]["png"]); } }, 0); } var logs2 = JSON.parse(myStorage.getItem("__layer2")); if(logs2.length > 0){ logs2.shift(); setTimeout(function(){ myStorage.setItem("__layer2", JSON.stringify(logs2)); ct2.clearRect(0, 0, $("#canvas2").width(), $("#canvas2").height()); if (logs2.length == 0) { draw("canvas2",logs2["png2"]); } else { draw("canvas2",logs2[0]["png2"]); } }, 0); } } function draw(target,src) { var img = new Image(); img.src = src; img.onload = function() { if (target == "canvas"){ ct.drawImage(img, 0, 0); } else { ct2.drawImage(img, 0, 0); } } }あとは初期化の中でローカルストレージの用意し、線の書き終わりにレイヤー1と2の情報を保存します。
次回は小技(ショートカットの実装)を予定しています。
また気が向いたときにお会いしましょう。
- 投稿日:2020-06-26T20:11:11+09:00
【Vue】学習開始4週目で覚える内容
4週目で学ぶべきこと
- フック関数
- カスタムディレクティブ
- フィルター
- ミックスイン
- Vue Router
フック関数
- フック関数:プログラムの中に
独自の処理を割りこませる
ために用意されている仕組み。
関数名 詳細 bind 初めて対象のhtmlタグに紐づいた時に、呼ばれる inserted カスタムディレクティブと紐づいた要素が親Nodeに挿入された際に呼ばれる update コンポーネント内でデータ更新が行われたタイミングで呼ばれる
子コンポーネント更新される前componentUpdated コンポーネント内でデータ更新が行われたタイミングで呼ばれる
子コンポーネント更新された後unbind htmlタグとの紐付けが解除された時点で呼ばれる カスタムディレクティブ
- 引数は
el, binding, vnode, oldVnode
。 ※基本はel, binding
を使う- フック関数の中で、
bind, update
は頻出のため、function関数
で省略可能el
はhtmlタグ
のことを指す。main.js//カスタムディレクティブ定義方法① Vue.directive("sample", { bind(el, binding) { el.style.color = 'red'; } }); //カスタムディレクティブ定義方法② Vue.directive("sample", function(el, binding) { el.style.border = 'red'; });◆ binding.value
App.vue<template> <!-- "v-sample"は、カスタムディレクティブ --> <p v-sample="red">Home</p> </template>main.jsVue.directive("sample", function(el, binding) { //v-sample="red"の値を、binding.valueで受け取る el.style.color = binding.value; });◆ 引数:arg
App.vue<template> <!-- "v-sample:solid"で、引数を指定する --> <p v-sample:solid="red">Home</p> </template>main.jsVue.directive("sample", function(el, binding) { //"v-sample:solid"の引数を"binding.arg"を用いて取得する el.style.samplestyle = binding.arg; });フィルター
Vue.filter
で、フィルターを作成し、パイプ
を使って適用するmain.js//フィルター名:"UpperCase" input値を"大文字"に変換する Vue.filter("UpperCase", function(value) { return value.toUpperCase(); });App.vue<template> <!-- "Vue.filter"で定義した"UpperCase"を挿入する --> <h1>{{ answer | UpperCase }}</h1> </template> <script> export default { data() { return { //属性値:answer 初期値:"hello world!" answer: "hello world!" } } }; </script>ミックスイン
export const
を用いてミックスイン
を定義する- ミックスインを定義したファイルを
import
,export
を使って反映させるsample.js//ミックスイン名:sampleを定義する export const sample = { data() { return { //属性値:answer 初期値:"hello world!" answer: "hello world!" } } };App.vue<template> <p>{{answer}}</p> </template> <script> //ミックスインを定義したファイル名をインポート import { sample } from "@/sample"; export default { //ミックスインで定義した内容をエクスポートし、反映させる mixins: [sample] }; </script>Vue Router
◆ router.js
router.js//vue-routerをインポートする import Vue from "vue"; import Router from "vue-router"; import Home from "./views/Home.vue"; //Router(プラグイン)を適用する Vue.use(Router); //new Routerによって、パスルーティングを指定 export default new Router({ routes: [ { //path, componentを指定 path: "/", component: Home } ] })◆ main.js
main.js//vue-routerを追加する import router from "./router" new Vue({ //routerを追加 router: router, render: h => h(App) }).$mount("#app");◆ App.vue
App.vue<template> <!-- "router-view"を使用することで、設定したルーティングを適用する --> <router-view></router-view> </template>同シリーズ
参考文献
- 投稿日:2020-06-26T19:26:01+09:00
JSで配列の検索と削除のメモ
よく使う機会あったので備忘メモ
配列のobjectでID一致したらそこを削除するメモ一致データを削除サンプル
datas = [{id:1,content:"AAA"},{id:2,content:"BBB"},{id:3,content:"CCC"}]; deleteData (id) { const result = this.datas.findIndex( (item) => item.id === id ); if (-1 < result) { this.datas.splice(result, 1); } }参考サイト
ES6でよく使う、配列の中身を操作・検索する関数
https://qiita.com/pentla/items/a87383903a30d7baa282#findindex
JavaScript - 配列の要素を削除する
https://murashun.jp/blog/20191110-18.html#chapter-3
- 投稿日:2020-06-26T19:12:13+09:00
typescriptの導入 + classについてのメモ
TypeScriptのインストール
npm install typescripttypescriptの実行
.tsファイルを.jsファイルにコンパイルし、作成された.jsファイルを実行する。
tsc ファイル名.ts node ファイル名.jstypescriptでclassの練習
practice.ts//クラスを作成 class Animal { //プロパティ 名前:型 name: string; age: number; //intではない //コンストラクタはインスタンスに引数を持たせる場合に必要 constructor(name: string, age: number) { this.name = name; this.age = age; } } //インスタンスを作成 var cat = new Animal("Cat", 7); console.log(cat.name); //Cat console.log(cat.age); //7 //コンストラクタは省略が可能 class Animal_no_constructor { name: string = "Dog"; age: number = 3; } //コンストラクタを省略した場合は、インスタンスに値を持たせることが出来ない var dog = new Animal_no_constructor(); //プロパティを出力 console.log(dog.name); //Dog console.log(dog.age); //3 //メソッドの使い方 class Human { name: string; score: number; constructor(name: string, score: number) { this.name = name; this.score = score; } judge() { var message: string; if (this.score > 50) { message = this.name + "は合格"; } else { message = this.name + "は不合格"; } console.log(message); } } var takeshi = new Human("Takeshi", 100); takeshi.judge(); //Takeshiは合格 var taro = new Human("Taro", 45); taro.judge(); //Taroは不合格 //継承 class Oya { name: string; constructor(name: string) { this.name = name; } hello() { console.log("こんちわー"); } } class Kodomo extends Oya { constructor(name: string) { //Oyaのthis.nameを受け継ぐ super(name); this.name = name; } say() { //親クラスOyaのhelloメソッド super.hello(); console.log("あの" + this.name + "!?"); } } var yoshida = new Kodomo("yoshida"); yoshida.say(); //こんちわー あのyoshida!? //デフォルト引数 class Menu { item_number: number; constructor(item_number: number = 0) { this.item_number = item_number; } say_item_name() { var array = ["ラーメン", "うどん", "蕎麦"]; console.log(array[this.item_number]); } } var soba = new Menu(2); soba.say_item_name(); //蕎麦 var wasureta = new Menu(); wasureta.say_item_name(); //ラーメン(引数がないので自動で0に)
- 投稿日:2020-06-26T19:02:01+09:00
jsonのPHP、JSでのエンコードとか
- 投稿日:2020-06-26T18:41:16+09:00
完成!!初めてReact.jsでWebサイト作った!!
とりあえず完成!
つまずいた点たくさんありました...
ハマったポイントを記事にしたのはまだ1つだけですが,今後作ってきます一通り完成したので報告致します.<--急にかしこまる
https://shinnosuke7031.github.io/react-test/意識したのは,ページ遷移しないで表示内容を変えること!
デザインはまだまだですが...
ぜひアドバイスとかいただけると幸いです
- 投稿日:2020-06-26T17:03:40+09:00
【Nuxt.js】Nuxt文法編:v-slot(中級)
分割代入
簡単にいうと別の場所で
別の変数名をきめれて
値を代入できること
MDN分割代入というより見た方が早いですね?
親で子の値を使えちゃいます!❓どんな時に使うか
まとまったdataを子で管理したい時に使います!Text.vue<template> <div class="title title-page"> <slot v-bind:user="user"> {{ user.lastName }} </slot> </div> </template> <script> export default { data () { return { user: { firstName: 'first', lastName: 'last', }, } }, } </script>index.vue<template> <div class="page"> <Text> <template #default="sample"> {{ sample.user.firstName }} </template> </Text> </div> </template> <script> import Text from '~/components/Text.vue' export default { components: { Text, }, data () { return { } }, } </script>動的なスロット名
まずは動的引数を理解しましょう?
https://jp.vuejs.org/v2/guide/syntax.html#動的引数【解説/index.vue】
・ リンク
これと全く同じです❗️
リンクLink.vue<template> <a :[attributeName]="url"> リンク </a> </template> <script> export default { data () { return { attributeName: "href", url: "/" } }, } </script>index.vue<template> <div class="page"> <Link /> </div> </template> <script> import Link from '~/components/Link.vue' export default { components: { Link, }, } </script>これをslotで…
できるのですが、
簡単な方法があります!笑v-bind="$attrs"
これを使います!【解説】
属性自体を親から渡したい時
v-bind="$attrs"を使います?
今回の場合はaタグの
href属性ごと渡してます。Link.vue<template> <a v-bind="$attrs">リンク</a> </template> <script> export default { } </script>index.vue<template> <div class="page"> <Link href="/" /> </div> </template> <script> import Link from '~/components/Link.vue' export default { components: { Link, }, } </script>まとめ
置き換えのできる3つをまとめました!
slot:テキスト
props:それ以外、クラス付与などに便利
v-bind="$attrs":属性自体
- 投稿日:2020-06-26T16:21:52+09:00
ℹ NuxtJS collects completely anonymous data about usage.
ℹ NuxtJS collects completely anonymous data about usage. This will help us improving Nuxt developer experience over the time. Read more on https://git.io/nuxt-telemetry ? Are you interested in participation? (Y/n)なんかこういうのが出るようになった。
ちょっと鬱陶しい。表示されるリンクを見るだけなんだけれども。
https://github.com/nuxt/telemetry#opting-out3の
nuxt.config.js
に設定するやり方で出なくなった。export default { telemetry: false }
- 投稿日:2020-06-26T16:11:06+09:00
【javascript】配列メソッド
書籍のアウトプットとして。
Array.fromを使って配列を作成
数値の平均を求める関数お作成しているとして、以下のような関数の定義はうまく実装されません。
function avg() { const sum = arguments.reduce(function(a, b) { return a + b; }) return sum / arguments.length; }なぜならargumentsオブジェクトは配列ではなく、配列のようなオブジェクトだからです。。
"arguments.reduce is not a function"
というエラーは、argumentsオブジェクトを配列に変換する必要があるということです。配列のようなオブジェクトを配列に変換するには
Array.prototype
のslice
メソッドを適応させます。
sliceを引数無しで呼び出すと、配列のシャローコピーを作成します。これを配列のようなオブジェクトに適応しても、配列が作成されます。
またArray.prototype.apply
でもうまくいきます。配列のようなオブジェクト
配列でないものの、lengthプロパティを持ち、添字によるアクセスができ、forループで処理もできるオブジェクトのこと。Array.prototype.slice.call(arrayLikeObject); //または [].slice.call(arrayLikeObject);これを使用して先の関数を修正します。
function avg() { const args=[].slice.apply(arguments); const sum = args.reduce(function(a, b) { return a + b; }) return sum / arguments.length; }以下はArray.fromを使用してバージョンです。
function avg() { const args=Array.from(arguments); const sum = args.reduce(function(a, b) { return a + b; }) return sum / arguments.length; }Array.fromは配列のようなオブジェクトを配列に変換します。
Array.from
とdocument.querySelectorAll
との組み合わせdocument.querySelectorAllのオブジェクト型は
NodeList
であり、配列ではありません。Array.fromはlengthプロパティを持つオブジェクトであれば、どのオブジェクトでもうまくいきます。
配列にしたい対象がlengthプロパティを持ってさえいれば配列に変換できるということです。Array.from({length:50})これにより
new Array(50)
と同じ新しい配列が作成されます。
これは長さが50の配列です。Array.ofを使って配列を作成
以下のコードを執行するとどうなるでしょう。
let a=new Array(1,2,3) let b=new Array(1,2) let c=new Array(1)aとbは普通の配列が作成されるが、cの結果は
empty
となり、1つの値を持った配列を作成できません。
これはArrayのコンストラクタの振る舞いです。
これを回避する方法としてArray.ofファクトリメソッドを使用します。let a=Array.of(1,2,3) let b=Array.of(1,2) let c=Array.of(1)こうすることで1つの値を持つ配列を作成できます。
「そんなことしなくても配列リテラルをつ開けばよいのでは?」と思うかもしれないです。
let a=[1,2,3] let b=[1,2] let c=[1]しかしこれがうまく行かない状況があります。
その一つは配列のサブクラスを使用しているときです。
AwesomeArrayというArrayのサブクラスを使用しているとします。
するとAwesomeArrayはnew AwesomeArray(1)が使えません。更に配列リテラルも使用できません。
配列リテラルを使用するとAwesomeArrayではなくArrayのインスタンスになってしまうからです。しかしArray.ofは使用できるため、1つの値に1つだけ含まれたAwesomeArrayのインスタンスが返されます。
Array.prototype.fillを使って配列を作成
ここでは三目並べゲームを作っていきます。
具体的な構成は以下です。
- 9個のマスは長さ9の配列を使用
- マスにおけるのは"x"と"o"、マスは空("")で表現配列をboardとするとこのように初期化できる。
const board = new Array(9).map(function(i) { return ' '; })map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/mapnew Array(9)で9この値を持つ配列を初期化すると、すべての値がundefinedになるので、mapでundefined値をそれぞれスペースに変換します。
しかしこの方法はうまくいきません。new Array(9)を実行すると実際には9個のundefinedが追加されるのではなく、lengthプロパティに9が設定された新しい配列が作成されるだけだからです。
どういうことかというと、例えば['a','b','c']という配列を作成したとすると内部ではこうなっています。
{ length:3, 0:'a', 1:'b', 2:'c', }new Array(9)を実行すると配列の内部では下記のようになっていると思ってしまいます。
{ length:9, 0:undefined, 1:undefined, 2:undefined, 3:undefined, 4:undefined, 5:undefined, 6:undefined, 7:undefined, 8:undefined, }しかし実際にはこうです。
{ length:9 }lengthプロパティが設定されているだけで、値は含まれていません。
欠けている値は穴(hole)と呼ばれます。
mapには対応しないのはこれが原因です。配列に特定の値を設定するにはfillを使用します。
const board = new Array(9).fill(' ');Array.prototype.includeを使って配列を検索する
String.prototype.includeと同様に配列にもincludeが同じように機能します。
Array.prototype.includeメソッドは配列のいずれかのインデックス位置に含まれている値が、指定された値を同じかどうかをチェックします。
これまではindexOfが使用されていました。
indexOfは結果に-1が含まれていた場合の比較を忘れてしまうバグが有りましたが、includeはブーリアンを返します。
- 投稿日:2020-06-26T15:40:21+09:00
コールバック関数不要「JSONP」取得関数(webページで複数回JSONPを使いたい人に)
Google Apps Scriptで作った複数の疑似APIからのJSONP取得が面倒(コールバック関数をその分だけ用意する必要があるなど)かつjQuery拡張のjQuery-JSONPを使いたくなかったので、コールバック関数無しにJSONPからJSONを取得する関数をピュアなJavaScriptで作ってみました。この関数を使えば、もう、JSONP取得のためにわざわざコールバック関数を用意する必要はありません。
大元のコード
JavaScript//引数 //url: jsonpのurl //cbName: jsonpを起動することになっているはずのコールバック関数の名前 function JSONP(url, cbName="callback") { return new Promise(function(_r, _e) { window[cbName] = function(j) { delete window[cbName]; _r(j); } var s = document.createElement("script"); s.src = url; document.head.appendChild(s); s.onerror = function(e) { delete window[cbName]; _e(e); s.remove(); } }); }minified版
JavaScriptfunction JSONP(url,cbName="callback"){return new Promise(function(i,r){window[cbName]=function(n){delete window[cbName];i(n)};var u=document.createElement("script");u.src=url;document.head.appendChild(u);u.onerror=function(n){delete window[cbName];r(n);u.remove()}})}使い方
JSONP関数はPromiseオブジェクトを返すので、返り値はthenで受けます。
分からない方のために念の為補足すると、thenの中に書かれた処理は、JSONPからJSONを取得した「直後」に起動します。
JSONPのURL
JavaScriptvar url = "https://script.google.com/macros/s/XXXXX/exec?callback=cbFunc"; //この例では、"cbFunc"がリクエストしたコールバック関数名 //サーバー側でコールバック関数名が指定されている(ヒエッ…)場合は、その名前を把握しておく使い方
JavaScript/*使用例その1*/ JSONP(url, "cbFunc") .then(function(r) {//jsonp読み込み成功時の処理 console.log(r);//返り値(r)はJSONオブジェクト })JavaScript/*使用例その2*/ JSONP(url, "cbFunc") .then(function(r) { console.log(r); }) .catch(function(e) {//jsonp読み込み失敗時の処理 console.log(e);//返り値(e)はonerrorのイベントオブジェクト })JavaScript/*使用例その3-α*/ //ネストであれば、同じコールバック関数名を使ってもヨシ! //ネストで無いならば、コールバック関数名は被らないように JSONP(url, "cbFunc") .then(function(r) { console.log(r); JSONP(url, "cbFunc") .then(function(r) { console.log(r); }) }) /*使用例その3-β*/ //IEを気にする必要が無いなら、アロー関数を使うのもアリ JSONP(url, "cbFunc").then(r=>{console.log(r),JSONP(url, "cbFunc").then(r=>console.log(r))});
- 投稿日:2020-06-26T15:40:21+09:00
コールバック関数&jQuery不要「JSONP」取得関数(webページで複数回JSONPを使いたい人に)
Google Apps Scriptで作った複数のAPIからのJSONP取得が面倒(コールバック関数をその分だけ用意する必要があるなど)かつjQuery拡張のjQuery-JSONPを使いたくなかったので、コールバック関数無しにJSONPからJSONを取得する関数をピュアなJavaScriptで作ってみました。この関数を使えば、もう、JSONP取得のためにわざわざコールバック関数を用意する必要はありません。
大元のコード
JavaScript//引数 //url: jsonpのurl //cbName: jsonpを起動することになっているはずのコールバック関数の名前 function JSONP(url, cbName="callback") { return new Promise(function(_r, _e) { window[cbName] = function(j) { delete window[cbName]; _r(j); } var s = document.createElement("script"); s.src = url; document.head.appendChild(s); s.onerror = function(e) { delete window[cbName]; _e(e); s.remove(); } }); }minified版
JavaScriptfunction JSONP(url,cbName="callback"){return new Promise(function(i,r){window[cbName]=function(n){delete window[cbName];i(n)};var u=document.createElement("script");u.src=url;document.head.appendChild(u);u.onerror=function(n){delete window[cbName];r(n);u.remove()}})}使い方
JSONP関数はPromiseオブジェクトを返すので、返り値はthenで受けます。
分からない方のために念の為補足すると、thenの中に書かれた処理は、JSONPからJSONを取得した「直後」に起動します。
JSONPのURL
JavaScriptvar url = "https://script.google.com/macros/s/XXXXX/exec?callback=cbFunc"; //この例では、"cbFunc"がリクエストしたコールバック関数名 //サーバー側でコールバック関数名が指定されている(ヒエッ…)場合は、その名前を把握しておく使い方
JavaScript/*使用例その1*/ JSONP(url, "cbFunc") .then(function(r) {//jsonp読み込み成功時の処理 console.log(r);//返り値(r)はJSONオブジェクト })JavaScript/*使用例その2*/ JSONP(url, "cbFunc") .then(function(r) { console.log(r); }) .catch(function(e) {//jsonp読み込み失敗時の処理 console.log(e);//返り値(e)はonerrorのイベントオブジェクト })JavaScript/*使用例その3-α*/ //ネストであれば、同じコールバック関数名を使ってもヨシ! //ネストで無いならば、コールバック関数名は被らないように JSONP(url, "cbFunc") .then(function(r) { console.log(r); JSONP(url, "cbFunc") .then(function(r) { console.log(r); }) }) /*使用例その3-β*/ //IEを気にする必要が無いなら、アロー関数を使うのもアリ JSONP(url, "cbFunc").then(r=>{console.log(r),JSONP(url, "cbFunc").then(r=>console.log(r))});
- 投稿日:2020-06-26T15:20:59+09:00
クロスオリジンエラーの解決
- 投稿日:2020-06-26T15:17:08+09:00
IE11だとNodeListがforEachで回らない問題
はじめに
IEの配布元であるマイクロソフトを始め、 IEが1日も早く滅んでほしい、なぜIE拡散禁止条約がないのか、早くWTOで世界IE禁止宣言を採択してほしい と世界中のweb系エンジニアは強く祈っていることだとは思いますが、様々な事情をお持ちの顧客のために日夜IE対応に心を砕いていることと存じ上げます。
それでもIEの最終バージョンであるIE11はまだマシな方なんだとは思いますが、あらゆるpolyfillをブチ込んでbabelをまわさないとイマドキ文法で書かれたJSは動きません。今宵もそんなフロントエンドエンジニアたちの天を貫く喜び、悲しみ、怒りを抱え、欲望の果へ向かいbabelが唸りをあげます。BUCK-TICKの宗教ソング「BABEL」の歌詞が、babelを使いの気持ちを余すところなく表現してて最高なので、ぜひご一読ください。
http://j-lyric.net/artist/a0006e7/l0438a2.htmlNodeListにforEachメソッドが居ない(ただしIEに限る)
ある時「IEでJSが死んでるぞ」と庭でマンボウが死んでるくらいのテンションで報告を受けました。
しゃーないな、と思ってテスト用のVMを立ち上げて見てみたら見事に死んでいたのですが、どうやら「NodeListにforEachなんてメソッドないで」というやつでした。
マジで?と思ったらマジでした。
https://developer.mozilla.org/ja/docs/Web/API/NodeList/forEach孔明先生もショックです。
NodeListって何?
document.querySelectorAll()
の戻り値として返ってくるDOMノードの集合体です。
https://developer.mozilla.org/ja/docs/Web/API/NodeListArrayで返ってきてもいいんじゃないのか?とは多少思いますが、ActionScriptで言うところのArrayListっぽい作りになっています。なので、Arrayに変換自体は可能です。
jQueryでclassで引っ掛けると配列ではなくてjQueryオブジェクトで返ってきて、そいつに
each()
しないと走査できないのと感覚は同じです。解決策
まあ、さっきのページにpolyfillがかいてあるので、それをそのまま入れてもいいのですが、なんか癪なのでnpmにpolifill居るんじゃね?と思って探したらいました。
https://www.npmjs.com/package/nodelist-foreach-polyfill
まあ、なのでこいつをnpmで入れてimportすれば万事解決です。
コマンドライン$ npm install nodelist-foreach-polyfill --save-devimport 'nodelist-foreach-polifill' class Hoge{ static init() { const hogelist = document.querySelectorAll('.hoge'); hogelist.forEach( e => e.classlist.add('fuga') ); } } Hoge.init();
- 投稿日:2020-06-26T15:14:08+09:00
「Unary operator '++' used」←eslintにこんなこと言われた時
- 投稿日:2020-06-26T15:03:15+09:00
[Javascript]iframeによって読み込まれているか判別する方法
はじめに
自分がiframeによって読み込まれているときだけ行いたい処理があったので、iframeによって読み込まれているかどうかを判別する方法を調べました。
自分用の備忘録も兼ねてまとめます。結論
初めに結論です。
window != window.parentで判別できます。
true
ならiframeによって読み込まれているということになります。解説
簡単に解説を書きます。
まず、iframeについてMDNに書かれていることをまとめると次のようになります。
- iFrameは閲覧コンテキスト(browsing context)を表現する
- 閲覧コンテキストは、セッション履歴(History)と文書(Document)をもつ
- 他の閲覧コンテキストを埋め込んでる閲覧コンテキストは親閲覧コンテキストと呼ばれる
- 最上位の閲覧コンテキストは、Windowオブジェクトで表される
つまり、
iFrameによって読み込まれている時、window.parentはiframeの親閲覧コンテキストになるので、windowにはなりません。間違いや指摘があれば、コメントにお願いします。
- 投稿日:2020-06-26T14:46:52+09:00
関数合成とReactコンポーネントとReact hooks
はじめに
Reactが好まれる理由の一つとしてただの関数としてかけるからというのがあります。Reactの関数コンポーネントは関数のように合成できます。React hooksもただの関数ですので合成できます。簡単な例で説明できたら分かりやすいのではないかと思い、書いてみます。
普通のJavaScript
関数がない(一つだけ)の場合は、例えば次のようになります。
const main = (args) => { const a = args[0] * 2; const b = args[1] * 2; console.log([a, b]); return a + b; };関数は、再利用性を増すために使うことができます。
const double = (x) => x * 2; const main = (args) => { const a = double(args[0]); const b = double(args[1]); console.log([a, b]); return a + b; };また、たった一度しか使わない関数であっても、名前をつけて読みやすくするために関数化する場合があります。
const double = (x) => x * 2; const printForDebug = (x) => console.log(x); const main = (args) => { const a = double(args[0]); const b = double(args[1]); printForDebug([a, b]); return a + b; };簡単な例ですが、これが普通のJavaScriptの場合です。
Reactコンポーネント
ReactコンポーネントはReactNodeを返す関数として書くことができます。JSXで書くことが多いので、それにならうと例えば次のようになります。
const App = () => { return ( <div> <h1>Hello</h1> <h2>World</h2> </div> ); };これを関数に分割して合成するには次のように書けます。
const Title = () => <h1>Hello</h1>; const Subtitle = () => <h2>World</h2>; const App = () => { return ( <div> {Title()} {Subtitle()} </div> ); };これは完全に同じ結果を生み出します。ただの関数ですから。
しかし、このパターンはあまり見たことがないでしょうし、実際非推奨です。推奨される書き方は、次のようになります。
const Title = () => <h1>Hello</h1>; const Subtitle = () => <h2>World</h2>; const App = () => { return ( <div> <Title /> <Subtitle /> </div> ); };見慣れた書き方かと思われます。こちらが推奨される理由は、TitleやSubtitleの関数を呼び出すタイミングをReactが制御できるからです。
<Title />
はcreateElement(Title, null)
と同等です。(執筆時点) 参照この書き方は、Reactコンポーネントを関数合成する際の制約とも言えます。関数として直接合成するのではなく、createElementを介して合成することで、Reactのスケジューリングの恩恵を受けることができます。
React hooks
では、React hooksの場合はどうなるでしょうか。同じように簡単な例を考えます。
const App = () => { const [a, setA] = useState(0); const incrementA = () => { setCountA((c) => c + 1); }; const [b, setB] = useState(0); const incrementB = () => { setCountB((c) => c + 1); }; useEffect(() => { console.log([a, b]); }); return ( <div> {a} <button onClick={incrementA}>+1</button> {b} <button onClick={incrementB}>+1</button> </div> ); };共通している処理があるので関数に切り出してカスタムフックにしてみましょう。
const useCount = (initialCount) => { const [count, setCount] = useState(initialCount); const increment = () => { setCount((c) => c + 1); }; return [count, increment]; }; const App = () => { const [a, incrementA] = useCount(0); const [b, incrementB] = useCount(0); useEffect(() => { console.log([a, b]); }); return ( <div> {a} <button onClick={incrementA}>+1</button> {b} <button onClick={incrementB}>+1</button> </div> ); };場合によっては、共通処理でなくてもカスタムフックにすることで見通しが良くなるかもしれません。
const usePrintForDebug = (x) => { useEffect(() => { console.log(x); }); }; const App = () => { const [a, incrementA] = useCount(0); const [b, incrementB] = useCount(0); usePrintForDebug([a, b]); return ( <div> {a} <button onClick={incrementA}>+1</button> {b} <button onClick={incrementB}>+1</button> </div> ); };Reactコンポーネントの関数合成に制約があったように、React hooksにおける制約もあります。 Rules of Hooks に詳しく書かれていますが、この制約の範囲内でしかカスタムフックは作れないことになります。
React hooksの制約は直感的ではないと言えるかもしれませんが、Reactコンポーネントの(緩い)制約も決して直感的とは言えないでしょう。制約の数は少ない上、パターン化されているので迷いは少ないと思いますが。React hooksの制約は eslint plugin でほぼチェックできますので、これを使うことが「パターン」として必須と言えるでしょう。
おわりに
React hooksを使う際にどの程度で関数化すなわちカスタムフック化したらいいかは、一言で答えられない問題かと思います。一言で答えるなら、Reactコンポーネントを分割するように分割したらいいのではないかと言います。つまり答えになっていませんが。私自身は関数は小さくしたい派なので、コンポーネントもカスタムフックも小さく分割して合成することを目指します。この辺りはReactとしての制約はなく柔軟なので、プロジェクトでの方針や規約を決めるといいかもしれません。(コンポーネントが大きすぎるとパフォーマンスに影響は出そうです。カスタムフックが大きすぎてもパフォーマンスには関係なさそう)
コンポーネントの場合はAtomic Designなどの方法論があるのでカスタムフックにもそのような方法論があったり、アレンジして適用できるかもしれません。
- 投稿日:2020-06-26T12:59:24+09:00
ビルド不要のドキュメントサイトジェネレーター「docsify」の個人的まとめ
この記事は、
ドキュメント静的サイトジェネレーターである docsify の使い方について
個人的にまとめたものです。はじめに
想定読者
- Markdown について知っている
- 開発が活発にされなくなった gitbook-cli の代替を探している
- 日本語検索に対応している 静的サイトジェネレーター が欲しい
この記事で得られること
- docsify の基本的な使い方
- お手軽なドキュメント作成方法
この記事で得られないこと
- 公式ドキュメントに記載されている細かい仕様
- 他の静的サイトジェネレーターについて
- Node.js の環境準備方法
docsifyの特徴
docsify とは
「docsify」は、公式を直訳すると 魔法のドキュメントサイトジェネレーター です。
すなわち、ドキュメントを作成するツールです。
どのあたりが魔法かというと、
- markdown などから html を生成する 静的サイトジェネレーターと違って、ビルド不要
- シンプルで比較的軽量
- 全文検索プラグイン付き
- 複数テーマ有り
- プラグインシステムが使える
- 絵文字やIE11のサポート
- サーバーサイドレンダリングも可能
とのことです。
なぜ docsify 紹介してるの
ことの発端は、ある時、Node.jsのバージョンを上げた際に、開発がもうあまり活発ではない gitbook-cli を使おうとしたら、ついにエラーが起きてしまったんですね。
旧バージョンであれば使えるので、まあいいか、とも思ったのですがこれを機に、新たなツールを模索していた際に出会ったのが docsify でした。
Rust製の mdbook もいい なと思ったので、使い分けしていこうと思っていますが、
docsifyの手軽さと、日本語検索に対応しているという点で魅力を感じ、
使い方を整理しておこう! といった流れで今に至ります。また、
npx
を使って、ライブラリのインストール不要で利用できる 点も個人的に高評価ですね。
Node.js が動く環境でさえあれば、利用できるわけです!さらに言えば、Node.jsが無くても動作します。
docsifyの一番簡単な使い方
説明はこれくらいにして、使い方を見ていきましょう。
一番シンプルな例です。
index.html
とREADME.MD
の2つを用意するだけでシングルページを作成できます。. ├── README.md └── index.htmlindex.html
index.html
は、次の内容で作成します。index.html<!-- index.html --> <!DOCTYPE html> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="width=device-width,initial-scale=1"> <meta charset="UTF-8"> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/vue.css"> </head> <body> <div id="app"></div> <script> window.$docsify = { //... } </script> <script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script> </body> </html>README.md
README.md# これはサンプルです。 ドキュメント静的サイトジェネレーターである **docsify** の使い方について 個人的にまとめたものです。 ## はじめに ### 想定読者 * Markdown について知っている * 開発が活発にされなくなった gitbook-cli の代替を探している * 日本語検索に対応している 静的サイトジェネレーター が欲しい ### この記事で得られること * [docsify](https://github.com/docsifyjs/docsify) の基本的な使い方 * お手軽なドキュメント作成方法 ### この記事で得られないこと * [公式ドキュメント](https://docsify.js.org/#/)に記載されている細かい仕様 * [他の静的サイトジェネレーター](https://www.staticgen.com/)について * Node.js の環境準備方法ローカルプレビュー( Python を使用した例)
Pythonを使用した場合の、ローカルサーバープレビューです。
python -m http.server 3000めちゃくちゃ簡単ですね。
npx を使った docsify の使い方
npx
を使った場合の例です。
上の「一番簡単な使い方」のファイル作成部分をコマンドから自動でやってくれる点で便利です。※ もちろんインストールして使用することも可能なのでその場合は、公式のわかりやすいクイックスタートを参照してください!
初期化
npx docsify-cli init ./docs. └── docs ├── .nojekyll ├── README.md └── index.html# ./docs/.nojekyll (Github Page用)※
docs
は任意フォルダです。ローカルサーバープレビュー
npx docsify-cli serve docs# http://localhost:3000にアクセスすると、README.mdの内容が表示されるdocsifyのカスタマイズ
基本的な使い方は、理解していただけたかと思います。
実際にドキュメントを作成していくと、サイトの表記やデザインなどをカスタマイズしたくなるかと思います。
サイトのデザインやプラグインなどの設定は、
index.html
を編集することでカスタマイズできます。docsifyの設定
docsifyの設定は、
window.$docsify = {}
内で行うようです。<script> window.$docsify = { //... } </script>個人的ベストプラクティスのの方針が固まったら、当記事を随時更新したいと思います。
それまでは、公式ドキュメント - カスタマイズ- を参照くださーい。(手抜き)
デプロイ方法
公式ドキュメント - デプロイ - にいくつか、方法が紹介されています。
わかりやすいので、読めばわかると思いますので、これも手抜きしちゃいます。おわりに
使いながら、より良い設定値なんかを更新できたらいいなと思います。
以下は、その他の参考です。
参考
- 投稿日:2020-06-26T11:40:49+09:00
30行のJavaScriptコードでスマートホームシステムを構築する方法
この記事では、IoTトレンドの成長を探り、わずか30行のコードでスマートホームシステムを構築する方法を紹介します。
本ブログは英語版からの翻訳です。オリジナルはこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。
スマートホームをはじめとする多くのIoT(Internet of Things)アプリケーションは、5Gなどの技術の台頭により、今年に入って急速に人気を集めています。スマートウォッチやテレビなど、「スマート」と表示される製品が増えており、人々が「スマート」という言葉を生活様式に変えていることを示しています。
一般的なスマートホームのソリューションには、デバイス(モノ)、クラウド、アプリケーションがあります。ソリューションの中には、ビッグデータやAIも含まれています。従来のIoT開発は「順序」を重視しており、つまり、デバイス、クラウド、アプリケーションでデータを順次処理していく必要がありました。今日では、Alibaba Cloud IoT Platformの「Thing Specification Language(TSL)」に基づいて、IoT開発の両端を並行して実行することができ、人件費や材料費を大幅に節約できるようになっています。
並行して実行することは明らかに魅力的ですが、一歩進んで、すべての開発を一人の人間に任せることはできるのでしょうか?答えはイエスです。私たちが自由に使えるすべての技術があれば、ウェブサイトを構築するのと同じように、スマートホームを自分たちで簡単に設計して構築することができるようになりました。Alibaba Cloud IoT Platformを利用すれば、30行のコードでスマートホームソリューションを完成させることができます。
現在、多くのインターネット開発者が、C/C++言語の基礎などの組み込み開発能力の不足により、IoTの門戸に足を止めています。アリババクラウドIoTプラットフォームが提供する「Embedded Javascript Tool」を利用することで、JavaScriptを利用したデバイス開発を迅速に行うことができ、これらの開発者が直面している最大の問題をシームレスに解決することができます。また、フロントエンド開発やバックエンド開発に不慣れな組み込み開発者のために、Alibaba Cloud IoT Platformが提供する「Visual Building」アプリケーションなどのクイックスタート機能を利用することで、ゼロコードでのアプリケーション開発が可能となり、学習の手間を大幅に軽減することができます。
サービスを有効にする
まず、Alibaba Cloudアカウントを申請し、ワンストップ開発プラットフォーム「IoT Studio」を有効にしてログインします。
次に、「Create Project」(好きな名前でOK)>「Device Development」>「Add Product」>「Category」を選択します。必要に応じて「Lighting」または「Temperature & Humidity Meter」を選択し、通信方式はWi-Fiを選択し、データ形式はAlinkを選択します。
Device Development>Add Debugging Devicesを選択し、デバイスのトライタプルをメモします。
デバイス開発
組み込みJavaScriptのオンラインワークベンチを開き(開発環境を構築する必要はありません)、新規プロジェクトを作成します。
index.js
のコードを置き換えます。Lighting
var deviceShadow = require('deviceShadow'); var ledHandle = GPIO.open("led1"); deviceShadow.bindDevID({ "productKey": "123", deviceName: "", deviceSecret: "" }); function main(err){ if(err){ console.log("failed to connect to the platform"); }else{ console.log("the main program started"); deviceShadow.addDevSetPropertyNotify("LightSwitch", function (lightStatus) { GPIO.write(ledHandle, 1-lightStatus); }); var mainLoop = setInterval(function () { var ledStatus = GPIO.read(ledHandle); deviceShadow.postProperty("LightSwitch", 1-ledStatus); }, 2000); } } deviceShadow.start(main);Temperature and Humidity Meter
var deviceShadow = require('deviceShadow'); var shtc1 = require('shtc1'); var handle = new shtc1('shtc1'); var ledHandle = GPIO.open("led"); deviceShadow.bindDevID({ productKey: "a17vi82MmxP", deviceName: "0001", deviceSecret: "tYUngSMqYeDxODgtX3DNKkQ7920I3t4T" }); function main(err) { if (err) { console.log("failed to connect to the platform"); } else { console.log("the main program started"); var mainLoop = setInterval(function () { var val = handle.getTempHumi(); console.log('shtc1:temp=' + val[0] + ' humi:' + val[1]); deviceShadow.postProperty("CurrentTemperature", val[0]); deviceShadow.postProperty("RelativeHumidity", val[1]); }, 2000); } } deviceShadow.start(main);デバイス(ESP32など)をコンピュータに接続し、"Connect "と "Run "をクリックします。起動後、デバイスが自動的にindex.jsを読み込んで実行し、同時にAlibaba Cloud IoT Platformにデータを報告します。
アプリケーション開発の様子
システムはアプリケーションなしでは動作しません。ビジュアルビルディング機能を使えば、コードゼロでアプリケーションを素早く完成させることができます。ダッシュボードにドラッグしてコンポーネントを順番に切り替え、画像を入れ替え、デバイスをバインドするだけですべての操作が完了します。
わずか30行のコードで構築されたエンドツーエンドのスマートホームシステムが完成し、保存して公開した後、他の人と共有することができます。
Embedded Javascript ToolとIoT Studioを使用することで、開発者は新しいプログラミング言語を習得することなく、シームレスかつ迅速にIoTの開発を開始することができ、Alibaba Cloud IoT Platformの包摂性と独創性を実証しています。
アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ
- 投稿日:2020-06-26T11:31:05+09:00
JavaScript中級者になるために参考になるサイトをまとめてみた。
対象者
JavaScript初心者を抜け出したい方
変数やメソッドなどの基礎的なところはわかっている方
progateを終えて次のステップに進みたい方なぜ書いたか
プログラミングを一通り勉強してきて、初心者という枠を抜け出したいと思い、いろいろ調べている中でとても良いサイトや動画に出逢ったので自分と同じように中級者へステップアップしたい方向けに記事を書こうと思った次第であります。
youtube
いきなり動画かよと思う方がいらっしゃるかもしれませんが、対象が初心者なので学びやすい動画を先に持ってきました。(筆者も初心者から中級者になろうとしている最中なのでとても参考にさせていただいております。)
しまぶーのIT大学さん
プログラミングはもちろんですが、そのほかにもJavaScriptの歴史の背景の部分を解説してくれているので、なぜこの技術が必要となったのか理解することができます。たにぐちまことさん
JavaScript以外にもたくさんの動画を出されている方でとてもわかりやすく、本当に初心者の方はこの方の動画から入るのが良いのではないでしょうか?Web万屋エンジニアチャンネルさん
例えが的確すぎてとてもわかりやすいのが特徴です。
特にレキシカル環境を卵に例えた話は目から鱗がボロボロ落ちました笑
動画の対象は初心者から中級者の手前向けといった感じでしょうか。Code Mafiaさん
JavaScript中級者への道という動画をだしている方で、初心者から中級者になるためにつまずくところをとてもわかりやすく解説してくれています。Webサイト
初心者から上級者までお世話になるサイトです。
初心者を抜け出したければ必ず目を通しましょう。ただ、難しいところも多いです。
初心者の方で読んだことある方は毛嫌いしているサイトであるかもしれません。気持ちはとてもよくわかります。
でも逃げていては初心者から抜け出すことはできません。筋トレと一緒で負荷をかけなければ成長はしません。筋肉痛だと思って頑張りましょう。現代のJavaScriptチュートリアル
初歩的なところから深いところまで一通り学べるサイトです。
練習問題もあるので理解できたかの確認ができます。
量がとても多く難しいところも多いので少しずつ進めていきましょう。タイトルにあるようにJavaScriptで中上級者を目指すためのサイトになっております。目次をみてみてどういったものがあるか確認してみると良いでしょう。
最後に
JavaScript中級者へのステップアップを目指されている方の参考になれば幸いです。
千里の道も一歩から
がんばっていきましょう!
- 投稿日:2020-06-26T09:17:51+09:00
【JavaScript】 js 繰り返し文 for / while
【ゴール】
JavaScriptで使える繰り返し文
【メリット】
■ javascript理解度向上
■ リーダブルコード実現【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7【コード】
※1-100まで1つずつ足されていくという処理を例にします。
while
※()に条件
※{}に出力処理 & 加算処理hoge.jswhile(number <= 100){ console.log(number); number ++ ; }for
※forは条件を()内に全て記述、シンプルで◎
hoge.jsfor(number = 1; number <= 100; number ++){ console.log(number); }以上!!!
コードライン色付けしてみました!!!【合わせて読みたい】
■ 【jQuery】初心者でもよく理解できたやつ
https://qiita.com/tanaka-yu3/items/a03734b248c3f2ee8461■ 【メソッド集】 rails メソッド まとめ 基礎 随時追加
https://qiita.com/tanaka-yu3/items/89abad875187494bec53■ 【JavaScript】javascriptの基本
https://qiita.com/smkhkc/items/5e3729cffab6591f34c6
- 投稿日:2020-06-26T09:01:40+09:00
tusdとtus-js-client, uppyを使ったファイルアップロードをapache2.4のCentOS7で構築する(https編)
目的
- でかくて一杯ある音データをユーザ毎にサーバにアップロードしたいので、MITライセンスの
tusd
を使いたい。- 実運用にはhttpsが必須です。クッキーでセッション管理して大容量・複数ファイルの処理をユーザ毎に行いたいからです。
- 前回ではhttpで動くことを確認しました。
- この記事はhttpsでのトライアルです。クッキーには対応していません。
環境
- CentOS7
- apache 2.4.41
- browser Firefox77 (MacOS)など
- tusd 1.0
- tus-js-client v2
参考
注意(この方法はtus.ioで記載されている方法とは違います。参考程度にお願いします)
- apacheのconfはここに書いてあります。tusd/examples/apache2.conf
- tus-js-clientのサンプルはここにありますtus-js-client/docs/usage.md
インプリの概要
- uppy/tus-js-clientはCORS(Cross Origin Resource Sharing)が解決しないとブラウザは動いてくれません。そのための
Header
にいつもの"このサイトは大丈夫だからね!Header always set Access-Control-Allow-Origin "https://www.my-site.net"
"を記述をします。- tusdはhttpベースでhttp:0.0.0.0:1080を監視しているので、クライアントとサーバのやり取りをhttpsで行う場合、サーバでhttpsからhttpにスキーム変換させるためにリバースプロキシを立てます。このときうまくいったコードでは、リバースプロキシはクライアントからの
https:/www.your-site.net/files
への要求をhttp://localhost:1080/files/
に渡すので、クライアントはポート番号を指定しないことでうまく行きました。- スキームの変換はapacheの
ssl.conf
に記載します。- tusdはproxyの後ろで動いているとオプションを渡して起動させます。
この5つの設定でうまく行きました。うまくいったapach2.4の
httpd.conf
、ssl.conf
、tus
の起動スクリプト、tus-js-clientのhtml
の例を次に記します。セキュリティのため、適当に書き換えていますので、読み替えてください。記載は本質的なところに限りました。apache2.4の設定ファイル
- sslの設定はLet's encryptで動いていますので、そちらを参考にしてください。
httpd.conf(部分)
httpd.confListen 80 ... Include conf.modules.d/*.conf ServerName www.my-site.net:80 IncludeOptional conf.d/*.conf ... <Directory /var/www/files> Header always set Access-Control-Allow-Origin "https://www.your-site.net" </Directory>この/var/www/filesにupload fileが入ります。
ssl.conf(部分)
ssl.conf... <VirtualHost _default_:443> ... ServerName www.your-site.net ... SSLEngine on SSLCertificateFile your-cert.pem SSLCertificateKeyFile your-privkey.pem Include your-options-ssl-apache.conf SSLCertificateChainFile your-chain.pem RequestHeader set X-Forwarded-Proto "https" ProxyPreserveHost on ProxyRequests off <LocationMatch "/files"> ProxyPass http://localhost:1080/files ProxyPassReverse http://localhost:1080/files </LocationMatch> </VirtualHost> SSLProtocol all -SSLv3 SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-$:HIGH:MEDIUM:!MD5:!RC4 SSLHonorCipherOrder on SSLCompression off # OCSP Stapling, only in httpd 2.3.3 and later SSLUseStapling on SSLStaplingResponderTimeout 5 SSLStaplingReturnResponderErrors offセキュリティの設定(SSLCipherSuite、OCSPなど)は適当です。
tusdの起動スクリプト
tusdを立ち上げる時のログとコマンドをスクリプト化しました。リバースプロキシに対応させるため引数(
-behind-proxy
)を加えています。run_tusd.bash#!/bin/bash -vxeu # tusdをオプション込みで起動する exec &> /var/www/log/$(basename $0).$(date '+%y%m%d_%H%M%S').$$.bash sudo -u apache /usr/local/bin/tusd -upload-dir /var/www/files -behind-proxy &クライアントサイド
これがtus.ioの方法と一番違います。tus.ioでは
tttps://www.my-site.net:1080/files/
とポート番号を指定してアクセスするように書いていますが、apache2.4ではどうもうまく行きません。サンプルはapache2.2のようなので振る舞いが違うようになったのかもしれませんが私にはわかりません。動いたコードは下記です。tus-js-clientのindex.html41行目:オリジナル <input type="text" id="endpoint" name="endpoint" value="https://www.your-site.net:1080/files/"> 41行目:変更後 <input type="text" id="endpoint" name="endpoint" value="https://www.your-site.net/files/">同様にuppyもendpointをポート番号1080を消して
https:www.you-site.net/files/
に指定したらうまく行きました。uppy.htmlvar uppy = Uppy.Core() ... .use(Uppy.Tus, { endpoint: 'https://www.your-site.net/files/', ... })参考
apacheのデバックはとても大変です。LogLevelをdebugにしてもよくわかりません。そこで教えてもらったのが
curl
です。CORSでOPTIONSの反応が全然わからないのでしたがterminalでpreflightのテストができるようになってからかなり素早く試行することができました。それとサーバのconfファイルの編集はrootでデフォルトのviでなくvimを使うほうが断然早いですね。curlのOPTIONSの反応は下記で見えます。ブラウザからどんな要求が出ているのかは FireFoxの表示メニュー → 開発メニュー → ネットワーク でヘッダを確認できました。$ curl --verbose https://www.your-site.net/files/ -X OPTIONS -H 'Host: www.your-site.net' -H 'Origin: https://your-site.net' 1> /dev/nullどなたの参考になれば嬉しいですが、これが正しい設定なのかわかりません。apacheの仕組みも正確にわかっておらず多分そうだろうと思って書きました。間違いの指摘などご意見いただけましたら幸いです。
- 投稿日:2020-06-26T08:58:01+09:00
Akashic Engine にて作成したニコ生向けゲームをiOSアプリ用に移植する方法
はじめに
本記事では、実質ニコ生ゲーム用のゲームエンジンであるAkashic Engineを使用した
ゲームをiOSアプリに移植したときの備忘録です。
HTML5で作られた他のエンジン製のゲームでも応用できるかと思います。
なお、Akashic Engineのマルチプレイ機能を用いたゲームは対象外です。※当記事のやり方では審査を通らない可能性が高いです。ご了承ください
AkashicEngine 2.7
XCode 11.5手順
1.Akashic Engineのゲームをスタンドアローン形式で出力。
https://akashic-games.github.io/tutorial/v2/7-export.html
akashic export html --magnify --output ../mygame2.XCodeで新規プロジェクト作成
File→New→Project
iOSタグ→Single View App
※User Interface を Storyboardとすること3.1で作成したファイルをプロジェクト直下に配置する
1で作成したmygameフォルダをそのままドラッグで良い
4.WKWebViewを配置し、ローカルのhtmlを表示する
ViewController.swiftimport UIKit import WebKit class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate { var webView: WKWebView! override func loadView() { let webConfiguration = WKWebViewConfiguration() //WKWebView に Configuration を引き渡し initialize webView = WKWebView(frame: .zero, configuration: webConfiguration) //WKUIDelegate の移譲先として self を登録 webView.uiDelegate = self //WKNavigationDelegate の移譲先として self を登録 webView.navigationDelegate = self //view に webView を割り当て view = webView } override func viewDidLoad() { super.viewDidLoad() // 読み込み開始 if let html = Bundle.main.path(forResource: "mygame/index", ofType: "html") { let url = URL(fileURLWithPath: html) let request = URLRequest(url: url) webView.load(request) } } }5.横画面表示のみとする
TARGETS→General→Deployment Info
のDeviceOrienttatitonのチェックボックスを
Landscape LeftとLandscape Rightのみとするこれで大体完成です。
アイコン等を設定すればストアに申請できます。
ただし、通りません。Guideline 4.2 - Design - Minimum Functionality
となってしまいます。
何か機能を追加すれば通るかもしれません。以上。