- 投稿日:2019-08-04T23:53:13+09:00
React Component について(React基礎講座3)
はじめに
今回は、React Component について書きます。
シリーズ
本記事はReact基礎講座のための連載になっています。気になる方のために、前の章は以下です。
JSXで変数を展開させたい場合やアロー関数について(React基礎講座2) - Qiita
最初の記事は、以下です。
Reactを使ってJSXの内容をレンダリングする(create-react-app)(React基礎講座1) - Qiita
コンポーネントとは
コンポートの概念は、関数と似ています。つまり、inputがあって、なんらかの処理をした結果を、Outputするパーツや部品のことをコンポーネントと言います。そして、このコンポーネントを組み合わせて、より大きなアプリケーションを構築します。
シンタックス
まずは、通常の React Element を作成して、そして次に React Component を作成しましょう。
React Element
import React from "react"; import { render } from "react-dom"; const returnTxt = () => { return <p>sample txt</p>; }; render(returnTxt(), document.getElementById("root"));では、これを React Component で書いてみましょう。
React Component
定義する際は、いくつかルールがあります。
- const で宣言する場合や、renderの第1引数のJSXとして渡す際、文頭を大文字にします
- renderの第1引数のJSXとして渡す際、タグで囲みます(閉じタグも書く) 例:
<Tag />import React from "react"; import { render } from "react-dom"; const ReturnTxt = () => { return <p>sample txt</p>; }; render(<ReturnTxt />, document.getElementById("root"));結果は同じになりますが、
React Componentが作成されている点が異なります。では、話を進めて、
React Componentに何か値を渡してみましょう。その場合は、renderの第1引数のJSXの中に
key="value"的な感じでReact Componentに引数的な値を渡します。index.jsimport React from "react"; import { render } from "react-dom"; const ReturnTxt = props => { return <h1>{props.title}</h1>; }; render(<ReturnTxt title="My Blog" />, document.getElementById("root"));引数を複数渡すこともできます。
index.jsimport React from "react"; import { render } from "react-dom"; const ReturnTxt = props => { return ( <div> <h1>{props.title}</h1> <p>{props.body}</p> </div> ); }; render( <ReturnTxt title="My Blog" body="hello, world" />, document.getElementById("root") );
React Componentの中でpropsをの中身をみてみましょう。console.log(props)コンソールには、以下のように出力されます。
Object {title: "My Blog", body: "hello, world"} title: "My Blog" body: "hello, world"
titleとbodyに、値が代入されているとわかります。
propsとして、受け取る以外の受け取り方もあります。先にコードを書いてみます。index.jsimport React from "react"; import { render } from "react-dom"; const ReturnTxt = ({title, body}) => { return ( <div> <h1>{title}</h1> <p>{body}</p> </div> ); }; render( <ReturnTxt title="My Blog" body="hello, world" />, document.getElementById("root") );何が違うかと言うと、アロー関数の引数を受け取る部分に、なみ括弧(ブレース)
{ }で受け取ることで、今回であればtitleとbodyという変数にオブジェクトされた中身を入れて、直接この変数名で展開することができます。
propsで書くより、上記のように何を受け取っているかわかるのがいいと思います。参考
- 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで | 山田 祥寛
- 投稿日:2019-08-04T22:37:32+09:00
最短でElectron入門
Electron用のプロジェクト作成から1画面(メインウィンドウ)表示までの内容です。
「とりあえず起動させるまで」が目的なので、中身は普通のJavascriptです。準備
まずはプロジェクト用のフォルダを作ります。
シェルとかコマンドプロンプトとかで中に入って次のコマンドを叩きます。npm init色々聞かれますが、デフォルトでOKです。
するとpackage.jsonが作成されるので、中身を変更します。こんな感じの行を消して
"test": "echo \"Error: no test specified\" && exit 1"代わりにこれを付け加えます。
"start": "electron ."これでコマンドラインで"npm start"って叩いたら起動します。
これで準備完了です。開発
まずはメインとなるindex.jsを作成します。
この後もいくつかファイルを作りますが、今回は全のファイルを最初に作ったプロジェクト用フォルダ直下に作成します。この時、npm initで作ったメインファイルの名前にする必要があります。(デフォルトがindex.js)
もし「俺、変えちゃったよ!でも、何にしたか忘れたよ!」って言う、うっかりさんはpackage.jsonの"main"の値を確認してね。それではindex.jsの中身です。
index.js// 必要な機能の追加 const electron = require('electron'); const url = require('url'); const path = require('path'); const {app, BrowserWindow} = electron; // メインウィンドウの名前。後々使いまわすので、ここで初期化。 let wndMain; // 処理本体 app.on('ready', function(){ // インスタンス化 wndMain = new BrowserWindow({}); // 画面用のHTMLファイル読み込み wndMain.loadURL(url.format({ pathname: path.join(__dirname, 'wndMain.html'), protocol: 'file', slashes: true })); })こんな感じです。
1画面出すだけなのでコードも少ない上、JavaScript開発者なら大体雰囲気がつかめると思います。
で、次は画面です。wndMain.htmlって名前のファイルを作ります。
別にインスタンスと名前を合わせなくてもいいのですが、
pathname: path.join(__dirname, 'wndMain.html'),で指定しているのと合わせる必要はあります。wndMain.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Main Window</title> </head> <body> <h1>Hello Work!</h1> </body> </html>titleタグがウィンドウ名になります。
必要ならCSSも追加してください。
普通のWEBデザインと同様に、head内に<link rel="stylesheet" type="text/css" href="style.css">で追加できます。
はい。これで終了です。
起動
それじゃー起動してみましょう。
次のコマンドを叩きます。npm startするとこんな感じの画面が出てくるはずです。
よく見るとメニューがついてます。(ヘッダー下の黒いところ)
これ、デフォルトで勝手に付いてくるやつです。最初にも言いましたが、「とりあえず起動させるまで」が目的なので機能的な事などは別の機会に!
- 投稿日:2019-08-04T22:35:39+09:00
【JavaScript】nodebrew経由でNode.jsとnpmをアップデートする
以前にnodebrew経由でNode.jsをインストールしていたのですが、それをアップデートしました。
以下、昔書いた記事です。
Homebrew
最初にnodebrewを管理しているHomebrewをアップデートします。
$ brew updateNode.js
現在のバージョンを確認します。
$ nodebrew list v10.1.0 current: v10.1.0アップデートします。
$ nodebrew install-binary stable再度確認すると、現在nodebrewで管理されているNode.jsのバージョンが増えました。
$ nodebrew list v10.1.0 v12.7.0 current: v10.1.0安定版を使います。
$ nodebrew use stable use v12.7.0バージョンの切り替えが確認できました。
$ node -v v12.7.0npm
現在のバージョンを確認します。
$ npm -v 5.6.0アップデートします。
$ npm update -g npmバージョンの切り替えが確認できました。
$ npm -v 6.10.2参考記事
Node.jsのアップデートはこちらの記事を参考にしました。
nodebrewでNode.jsをアップデートするこちらの記事で紹介されているNode.jsのバージョン管理ツールは
nというツールです。
今回はnpmのアップデート部分のみ参考にさせていただきました。
Node.jsとnpmをアップデートする方法各ツールの繋がりがとっても分かりやすく説明されています。
npm とか bower とか一体何なんだよ!Javascript 界隈の文脈を理解しよう
- 投稿日:2019-08-04T22:29:38+09:00
JSXで変数を展開させたい場合やアロー関数について(React基礎講座2)
はじめに
今回は、アロー関数について書きます。
シリーズ
本記事はReact基礎講座のための連載になっています。気になる方のために、前の章は以下です。
Reactを使ってJSXの内容をレンダリングする(create-react-app)(React基礎講座1) - Qiita
JSXの中で変数を使いたい場合
変数の中身を展開させたい場合、なみ括弧(ブレース)
{ }で囲うと展開されます。const greeting = "Hello, React"; // 変数代入 const jsx = <h1>{greeting}</h1>; // 変数の中身を展開JSXの中は1つのタグで囲う
なので、以下だとエラーになります。
const greeting = "Hello, React"; const introduction = "My Name is JS"; const jsx = <h1>{greeting}</h1><p>{introduction}</p>;エラーメッセージは
Adjacent JSX elements must be wrapped in an enclosing tag. Did you want a JSX fragment <>...</>?タグは複数ある場合は、それを囲むタグを用意せよと。では、
divタグで囲って見ましょう。index.jsimport React from "react"; import { render } from "react-dom"; const greeting = "Hello, React"; const introduction = "My Name is JS"; const jsx = ( <div> <h1>{greeting}</h1> <p>{introduction}</p> </div> ); render(jsx, document.getElementById("root"));これでエラーは出なくなりました。
JSXで関数を使いたい場合
展開の仕方は変数と同じです。今回は、JSに最初から定義されているDateクラスの関数を使ってみます。
import React from "react"; import { render } from "react-dom"; // 今日の日付で Date オブジェクトを作成 let now = new Date(); const greeting = "Hello, React"; const introduction = "My Name is JS"; const jsx = ( <div> <h1>{greeting}</h1> <p>{introduction}</p> <p>This Year is {now.getFullYear()}</p> </div> ); render(jsx, document.getElementById("root"));今年の年号が展開されましたね。なみ括弧(ブレース)
{ }で囲うと、変数だけでなく関数やオブジェクトも使えると言うことがわかりました。アロー関数で定義した中身を表示させたい場合
文字列とセットで今日の年号を返すアロー関数を定義して見ました。
import React from "react"; import { render } from "react-dom"; // 文字列とセットで今日の年号を返すアロー関数 const returnThisYear = () => { // 今日の日付で Date オブジェクトを作成 let now = new Date(); return `This Year is ${now.getFullYear()}` } const greeting = "Hello, React"; const introduction = "My Name is JS"; const jsx = ( <div> <h1>{greeting}</h1> <p>{introduction}</p> <p>{returnThisYear()}</p> </div> ); render(jsx, document.getElementById("root"));呼び出すときは、今回もブレースで囲みます。
{returnThisYear()}正しく呼び出されたと思います。
アロー関数とは
アロー関数は ES2015(ES6) 以降生まれた 関数を定義するためのシンタックスです。
thisの挙動をコントロールしやすくなるなどの利点があり利用されています。シンタックス
昔からある関数の定義と比較して見ましょう。両方とも、文字列を返すだけの単純な関数です。
// 昔の関数 const mukashi_func = function() { return "昔の関数" } console.log(mukashi_func); // => function mukashi_func() {} // => <constructor>: "Function" // => name: "Function" // アロー関数 const arrow_func = () => { return "アロー関数" } console.log(arrow_func); // => function arrow_func() {} // => <constructor>: "Function" // => name: "Function"アロー関数で引数を渡す場合
const arrow_func = (param) => { console.log(param) } arrow_func('test'); // => test引数が1つなら、かっこを省略できます。
const arrow_func = param => { console.log(param) } arrow_func('test'); // => test引数が2つの場合は
()を省略できません。const arrow_func = (param1, param2) => { console.log(param1, param2); }; arrow_func('first', 'second' ) // => first second1ライナーでの書き方
const arrow_func = () => { console.log("one line"); } arrow_func(); // => one line上記は、
returnするだけなので、以下のように1行で書くことができます。const arrow_func = () => console.log("one line"); arrow_func(); // => one lineアロー関数の色々な書き方(省略形)を紹介しました。
React でアロー関数を使用する
引数を2つ渡して、アロー関数でもらった引数を整形して、
render()中のJSXに返す処理を書きます。import React from "react"; import { render } from "react-dom"; const arrow_func = (no, name) => { return `no is ${no}, name is ${name}` } render(arrow_func(1,'taro'), document.getElementById("root"));参考
- 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで | 山田 祥寛
- 投稿日:2019-08-04T21:49:58+09:00
[HTML/CSS] ある要素をWindowに無理やり合わせつつ、拡大率に対応する
はじめに
「普段は画面の横幅いっぱいに表示されてほしいけど、ブラウザの拡大率を操作したら拡大はされてほしい」を出来るだけ簡単に(雑に)実現する(ブラウザ依存、PC以外の動作は見ていません)
背景
普通は、
- 要素のwidthを100%にする
- Viewportで調整する1
で、解決すると思いますが、
例えば、対象の要素を直接触れないとか、画面ないの一部の要素だけに適用したいとかで使えない想定。方針
transformでどんなサイズでも合わせてしまえばいいじゃない
結果
CSSだけで実現できないかと思ったが、一旦、断念してJavascriptを利用。
(Javascriptを絡めてしまうと如何様にもやり方はあると思うが)
- スクロールバーに対応してない
- ほかのWidth:100%のものと横幅が合わなくなる
あたりは対応していない。
Windowにfitするように試してるのでCodePenだと確認し辛い。See the Pen Element Window Fit Test by minilabo (@minilabo) on CodePen.
試したこと
CSSだけで実現
最初はCSSだけで実現できないかと試したが、scale + calcを上手く扱えず、時間がかかりそうだったので断念
example.css/* 計算結果の単位のせいか適用されない */ .ng { transform: scale(calc(100vw/2)) } /* これだと動く */ .ok { transform: scale(calc(100/2)) }諦めてJavascript使って動的に適用する
Javascriptで大きさを合わせるだけだと拡大率などに関わらず、Windowに合うだけなので、そのあたりの情報を調査する。
- 拡大しているかの判定
innerWidthが表示領域、outerWidthがwindowの大きさを表すので、 ブラウザの機能で拡大するとinnerWidthが小さくなるので、outerWidthに比べてinnerWidthが小さい場合、拡大されている。2main.js// スクロールバーなどが含まれる為、このまま計算すると少しずれる(が、雑に丸める) const zoom = Math.round(window.outerWidth / window.innerWidth);
- transformでサイズを変更しても親の要素のサイズに反映されない
element.getBoundingClientRect()で高さを取得して、親要素に適用(単純にelement.offsetHeightだと、transform前の大きさがとれる)
この関数はとても便利だが、環境によってはダメかも?(参考: https://developer.mozilla.org/ja/docs/Web/API/Element/getBoundingClientRect)main.js// tramsformの適用後の高さを取得して、親要素に適用してスペースを確保(今回は高さのみ) parent.style.height = element.getBoundingClientRect().height;
Viewportで初期の拡大率を1以下にすると問題があるよという記事を見たので参考に > もう逃げない。HTMLのviewportをちゃんと理解する ↩
スクロールバーなどが含まれる為、このまま計算すると少しずれる ↩
- 投稿日:2019-08-04T19:53:12+09:00
Nuxt+Typescript+Auth0で認証してみる
はじめに
「Auth0を使って認証機能を実装」
Nuxt+Javasrciptで動作する記事は見かけたのですが、Nuxt+Typescriptで動作する記事が見つからなかったので、記載してみました。
下記にソースを置いています。
https://github.com/ryuzo-nakata/nuxt-auth00.環境
下記のバージョンで動作しています。
$ npm -version 6.9.0 $ node -v 12.1.0 $ nvm --version 0.34.01.Nuxtを使えるようにする
1-1.初期化
nuxt-auth0というフォルダを作成して、npm installでpackage.jsonを作成します。$ mkdir nuxt-auth0 $ cd nuxt-auth0 $ npm init1-2.npxインストール
npxをインストールされていない方は、下記のようにインストールしてください。
$ npm install -g npx1-3.create-nuxt-app
Nuxt.js プロジェクトの雛形を作成します。
$ npx create-nuxt-app自分の環境では、
nuxtのバージョンが2.8.1になっていました。2. Typescriptを使えるようにする
2-1. Typescriptをインストール
Typescriptに必要なものをインストールします。
$ npm install @nuxt/typescript ts-node vue-property-decorator2-2. tsconfig.jsonの作成
nuxt-auth0/tsconfig.jsonを作成します。nuxt-auth0/tsconfig.json{ "compilerOptions": { "target": "esnext", "module": "esnext", "moduleResolution": "node", "lib": [ "esnext", "esnext.asynciterable", "dom" ], "esModuleInterop": true, "experimentalDecorators": true, "allowJs": true, "sourceMap": true, "strict": false, "allowSyntheticDefaultImports": true, "noImplicitAny": false, "noEmit": true, "baseUrl": ".", "resolveJsonModule": true, "paths": { "~/*": [ "./*" ], "@/*": [ "./*" ] }, "types": [ "@nuxt/vue-app", "@types/node" ] } }2-3. nuxt.config.tsへ変更
nuxt.config.jsからnuxt.config.tsへ変更します。中身は下記のように変更します。
nuxt-auth0/nuxt.config.tsimport NuxtConfiguration from '@nuxt/config' const config: NuxtConfiguration = { // Type or Press `Ctrl + Space` for autocompletion } export default configこれでTypescriptが使えるようになりました。
3. Auth0を使えるようにする
3-1 Auth0のDomainとClient ID
Auth0(https://auth0.com/jp/)
サインアップし、Applicationsを選択すると、下記の図のように表示されます。DomainとClient IDの値を、のちほど使います。
3-2 Auth0のCallback
次に、Callbackを下記のように設定します。
3-3. Auth0をインストール。
nuxtへauthに必要なものをインストールします。
$ npm install @nuxtjs/axios @nuxtjs/auth3-3. nuxt.config.tsにAuthの設定を追加する
nuxt-auth0/nuxt.config.tsに下記の設定を追加します。
auth0のdomainとclient_idは、上記の図の値をいれます。nuxt-atuth0/nuxt.config.tsmodules: [ // Doc: https://axios.nuxtjs.org/usage '@nuxtjs/axios', '@nuxtjs/auth' ], auth: { strategies: { auth0: { domain: 'Your Domain', client_id: 'Your Client ID' } }, redirect: { login: '/', // 未ログイン時のリダイレクト先 logout: '/', // ログアウト後のリダイレクト先 callback: '/callback', // コールバック home: '/home', // ログイン後のページ } }, router: { middleware: 'auth' },3-4. ページの作成
auth0の使い方を見たいだけなので、ログイン画面、ログイン後の画面、コールバックの画面を作成します。
ログイン画面
nuxt-atuth0/pages/index.vue<template> <div> <h1>Login Page</h1> <button @click="authenticate">Login</button> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({}) export default class Index extends Vue { authenticate() { this.$auth.loginWith('auth0') } } </script>ログイン後の画面
nuxt-atuth0/pages/home.vue<template> <div> <h1>Login Success</h1> <p>User Name: {{this.$auth.$state.user.name}}</p> <button @click="logout">Logout</button> </div> </template> <script lang="ts"> import { Component, Vue } from "vue-property-decorator"; @Component({}) export default class Logout extends Vue { logout() { this.$auth.logout(); } } </script>コールバックの画面
nuxt-atuth0/pages/home.vue<template> <h1>callback</h1> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator' @Component({}) export default class CallBack extends Vue {} </script>3-5. 各ページ認証してるか確認する
nuxtのmiddlewareを実装します。
nuxt.config.tsのrouterで、authを読み込むように設定しています。nuxt-atuth0/middleware/auth.tsexport default function ({ store, redirect }) { if (!store.state.auth.loggedIn) { redirect('/'); } }3-6. storeにindex.tsファイルを追加する
storeにindex.tsファイルがないとエラーになるので、下記のようにファイルだけ追加しておきます。
nuxt-atuth0/store/index.ts3-7. $authをプロパティに追加する
エディタ上で
$authプロパティをうまく認識してくれず、エラーを表示してしまします。。。このままでも動作はするのですが、なんでだろう?教えてすごい人。
ひとまず、エラーを出さないようにするために、下記のように
$authプロパティを自分で設定して回避しました。nuxt-atuth0/nuxt.config.tsdeclare module 'vue/types/vue' { interface Vue { $auth: any } }4. 動作
ローカルホスト上で動作してみましょう。
npm run dev
http://localhost:3000/へアクセスすると、NuxtがTypescriptで動作しています。ログイン画面
loginボタンを押すと、Auth画面へ遷移します。
Auth画面
auth0を使って、Signup / Login できます。
ログイン後の画面
ログイン後に表示されます。
おわりに
Nuxt+Typescript+Auth0で認証できるようになりました。
nuxt.config.tsのstrategiesを追加すれば、ソーシャルログインをいろいろ増やすことができるので、サービスによって追加してみましょう。
- 投稿日:2019-08-04T18:09:43+09:00
XHRでのcsvファイルの複数同時読み込み
仕事柄csvファイルを簡易DBとした読み込み処理をすることが多いのですが、複数のcsvファイルを読み込みたいときも多々あります。
すぐ忘れるので覚書として書いておきます。XMLHttpRequestで複数ファイルを読み込み
const f = (function(){ let xhr = new Array(), i; for(i = 0; i < 2; i++){ (function(i){ xhr[i] = new XMLHttpRequest(); url = "test" + i + ".csv"; xhr[i].onreadystatechange = function(){ if (xhr[i].readyState === 4 && xhr[i].status === 200){ //処置内容 } }; xhr[i].open("GET", url); xhr[i].overrideMimeType("text/plain; charset=Shift_JIS"); xhr[i].send(); })(i); } })();オフィス内ではExcelが標準的に使われるのがほとんどで、csvファイルをExcel側で再読み込みすることも多々あります。
文字コードなんぞやという方が殆どですので、Excelに合わせて文字コードはcsvファイルはShift_JISのままの方が良いです。
コーディングは当然utf-8ですけど。
いい加減officeもutf-8が標準になってくれればもっとシームレスになるんですけども(´・ω・`)あ、どうでもいいですが「"」「'」は「"」派です。
だってShiftから近いんですもの(´﹃`)
- 投稿日:2019-08-04T16:47:02+09:00
変数に入れてない整数を桁数表示する方法(JavaScript)
- 投稿日:2019-08-04T15:24:02+09:00
Reactを使ってJSXの内容をレンダリングする(create-react-app)(React基礎講座1)
はじめに
webページにレンダリングをする必要最小限の
React Appを実装するのに必要なことを書いていきます。開発環境
- codesandbox(POPULAR TEMPLATESはReactでCreateする)
不要なファイルは削除しています。
importについて
import自体は、ES2015(ES6)から導入されたメソッドで、これを使うと、JSのパッケージ(モジュール)の中身(関数や変数やクラスなど)を使えるようになります。なので、読み込めばこのファイル
index.jsで定義されていない関数や変数やクラスなどの、JSのモジュールをindex.jsで使えるようになります。index.jsimport React from "react";これは、
reactというパッケージ(モジュール)から、Reactをimportしていると言うことになります。上記を追加することで、Reactを読み込んでrenderメソッドなどを使えるようにしています。
render()についてindex.jsimport { render } from "react-dom";これは、
react-domというパッケージ(モジュール)から、renderというページにレンダリングするメソッドをimportしていると言うことになります。
render()は2つの引数を必要とします。render(JSX, target)
- JSX: JSの拡張言語で、HTMLのようなもの
- target: 作成したReactアプリを、どこの
DOM Elementsに紐づけるかの指定と言うことで、結果、以下のようになります。
render(<h1>Hello, React</h1>, document.getElementById('root'))このよう書くと、React(のrennder)が、
index.htmlにあるタグの中の<div id="root"></div>の中に、JSXで記入した内容をレンダリングします。コード
index.jsimport React from "react"; import { render } from "react-dom"; render(<h1>Hello, React</h1>, document.getElementById("root"));結果
JSX は HTML ではない
JSXですが、とてもHTMLに近いシンタックスですが、JSのファイルのなので、本来HTMLはかけないし、実際、HTMLではありません。
では、なぜwebページにHTMLぽく表示されるのかというと、babelなどの開発環境がJSXをReact Element(JSのオブジェクト)にトランスパイルしてくれているからです。JSのオブジェクトなので、変数代入や、console.logでの表示など、JSの操作が可能になります。JSのオブジェクトになった段階で、
render()メソッドでレンダリングを可能にしています。例えば、JSXを変数(
jsx)に代入して、console.logさせることも可能です。jsにおけるオブジェクトとは
詳細には記述しませんが、オブジェクトとは、名前をキーにした配列です。Rubyでいうハッシュです。連想配列と言ったりもするJSのデータ型の1つです。
参考
- 改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで | 山田 祥寛
- 投稿日:2019-08-04T13:33:21+09:00
javascriptのPromiseをpythonで実装する方法
Motive
seleniumでスマホ版でブラウザを起動しようと思った時、sp_args = "--user-agent=" sp_args_list = ["Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X)", "AppleWebKit/602.3.12 (KHTML, like Gecko)", "Version/10.0 Mobile/14C92 Safari/602.1"] sp_args += " ".join(sp_args_list)と設定するだけでは一部のサイトではレスポンシブになっているため対応しない場合があります。
そのため、
widthを450くらいにしてリロードをするとスマホ版の表示になるのですが、ブラウザ設定 → スマホ画面の大きさを設定 -> リロードの順に一つのプロセスが完了したことがcompleteになった状態で次のプロセスに移す実装ができないかと思ったわけです。で、 javascriptの非同期処理で使われる
Promiseと同等のものがpythonでできないかと考えたわけっす。Preparetion
pipで探すと早速パッケージが見つかりました。ふつーにpip install Promiseで良いです。
Model
参考にしたサンプルコードですが初めてのJavaScript 第3版 ――ES2015以降の最新ウェブ開発 14章 非同期プログラミングにあったロケット発射モデルを題材にしました。
元コードからブラウザに表示する編集等々でちょっと変えています。
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script type="text/javascript" src="./sample.js"></script> </head> <body> <h3>apolonX</h3> <div class="box"> </div> </body> </html>$(()=>{ countdown(10) .then(()=>{ return new Promise((resolve, reject) => { setTimeout(() => { //大気圏突入 resolve(insertBox("atmosphere...")); }, 2000); }); }) .then(()=>{ //成功 insertBox("success!!"); }); }); //カウントダウン function countdown(seconds){ let dst = new Promise( (resolve, reject) => { for (let i=seconds;0 <=i;i--){ setTimeout(() => { if(i>0){ insertBox(countSign(i)); } else { resolve(insertBox(goSign())); } }, (seconds-i)*1000); } } ); return dst } function insertBox(src){ let p = $("<p>") p.text(src); $(".box").append(p); } function countSign(index){ return index + "..."; } function goSign(){ return "GO!"; }で約2秒ごとにブラウザにメッセージが表示されます。
Method
from promise import Promise import time def main(): countdown(10).then(go()).then(Promise.resolve(atmosphere())).then(success()) def countdown(seconds): def myfunc(resolve, reject): for i in reversed(range(0,seconds + 1)): if 0 < i: print( str(i) + "..." ) time.sleep(2) else : resolve() return Promise(myfunc) def go(): time.sleep(1) print("GO") def atmosphere(): time.sleep(1) print("atmosphere") def success(): print("success!!") if __name__ == '__main__': main()
countdown(10).then(go()).then(Promise.resolve(atmosphere())).then(success())でチェイン化しています。
Future
複数のAPIでデータ取得後に一括処理して文章生成するなどのケースであったら、全てのAPIのデータ取得後に一括処理する一貫性が保たれるので何かと良い。
簡易的なトランザクション処理ですかね。Reference
promise
promise:github
初めてのJavaScript 第3版 ――ES2015以降の最新ウェブ開発 14章 非同期プログラミング
Python の Promise 実装とその活用方法について / How to implement Promise by Python and how to use it
- 投稿日:2019-08-04T13:09:25+09:00
RPGアツマールのグローバルシグナル
概要
RPGアツマールには非同期ネットゲームを想定したAPIが存在します
その中の「グローバルシグナル」を使ってみた記事です以前、ユーザーシグナルについての記事を書いているので
基本的な解説は重複しているところがあります作ったもの
- レイドバトル(エンディング後の要素にしています)
- https://game.nicovideo.jp/atsumaru/games/gm9445
- ボスに与えたダメージをグローバルシグナルで送りあってレイドバトルを実現しています
作ったものの具体的な説明については別な記事で書こうと思います
シグナルとは
- 公式のドキュメントはこちらです
ユーザー間での情報のやり取りを、シグナルという機能によって行えます
シグナルには100byte以内の情報(文字列)を入れることができます例えば、送り側で以下のようなjsonの文字列を作って送信します
{ SignalId:1, SaveIdx:1, Hp:10000 }受け側ではシグナルを取得すると送られた上記の文字列を取得できます
jsonを解釈することで、送り側から送られたSignalIdとSaveIdxとHpの値が分かるという流れです送り側のユーザーIDや名前はこれとは別に付与されているので含めなくて大丈夫です
シグナルには「ユーザーシグナル」と「グローバルシグナル」があります
ユーザーシグナル
指定したユーザー間で情報をやり取りするときはユーザーシグナルを使います
送り先のユーザーIDを引数に指定して目的のユーザーに送信します
使い方のイメージは以下の記事にまとめていますグローバルシグナル
全ユーザーに対して情報を送るときにはグローバルシグナルを使います
ユーザーシグナルとの違いは
- 全ユーザーに対して送信する
- 自分発信のシグナルを受信する
という辺りです
グローバルシグナルの動き
本記事ではグローバルシグナルを解説します
全ユーザーに対して送る「グローバルシグナル」の動きを解説します送り側は
window.RPGAtsumaru.experimental.sendSignalToGlobal()
を実行します1回送ると全ユーザーが取得できるようになります
送り側とたくさんの受け側(自分も含む)がいて
1件送るとこうなって・・・
また1件送るとこうなって・・・
サーバーに蓄積されていくイメージです
受け側は
window.RPGAtsumaru.experimental.getGlobalSignals()
を実行します各ユーザーごとに、
1回の実行で先程送られた2件を全部取得しますまたこの後に、送り側から3件目、4件目を送信してから、
受け側でシグナルの取得を行うと、受け側では1~4件目を全部取得してしまいますAPIの実行では全部取得してしまうので、
ゲーム側で新しいシグナルだけを読みたい場合は、
どこまで取得したかの情報をクライアントで持っておく必要があります公式プラグインの
AtsumaruGlobalSignalExperimental.jsが、
この辺りの制御をうまくやっていて、全シグナルを取りつつ、
ゲーム側には新しいシグナルしか渡さないようになっていますシグナルの情報が移動するイメージはユーザーシグナルとほぼ同じですが、
送る時はユーザーIDを指定せずに全員が取得できるように送ります
全員が取得できるということは自分も取得できてしまいます公式プラグインを読み解く
ユーザーシグナルのものとほぼ同じです
上記の解説記事をご参照くださいすべてのシグナルを取得できない可能性がある
こちらはユーザーシグナルもグローバルシグナルも同じですが
以下のことに注意してゲームの仕様を決める必要があります
- 一定の件数/容量を超えると古いものから削除される仕様のためシグナルは全て受け取れない可能性がある
- 件数や容量の詳細は公式の制限詳細を参照してください
特にグローバルシグナルの場合全ユーザーのシグナルが来るので
古いものが欠落する可能性が高くなると思います自分発信のシグナルを受け取る
グローバルシグナルはユーザーシグナルと違って全員が取得できるシグナルのため、自分が発信したシグナルを自分が受け取ることになります
例えば「誰かがログインしました」的な通知はグローバルシグナルで実現できると思いますが、自分のログイン通知をゲーム画面に出さなくてもよい仕様なのであれば、自分発信のシグナルを受け取ったときに除外するようにします
シグナルには発信者のユーザーIDが付与されているので、それが自分のユーザーIDと一致したら処理しない、とすればよいです
まとめ
グローバルシグナルの仕組みの説明と、使うときの注意点をまとめてみました
公式プラグインを使うだけであってもどういう動き方をしているのかが分かれば使い方のイメージがしやすいかなと思います
- 投稿日:2019-08-04T12:28:40+09:00
イベントオブジェクトfunction(e)のeとthisの違いについて 簡易メモ
この記事について
jQueryの学習中に気になったことを調べ、解決したので
メモとして書いています。・違いについて調べた経緯
ブラウザが元々持っている処理をキャンセルするメソッド
preventDefault()についての学習で以下の
コードが書かれていた。script.js$(function() { $('form').on('submit', function(e) { console.log('送信ボタンが押されました'); e.preventDefault(); }); });このコードを見たときにeのイベントオブジェクトをfunctionの第一引数として持たせているが、thisでもいいのでは?
と思い,
イベントオブジェクトfunction(e)のeとthisの違いについて
調べました。eとthisの違いについて
・this
関数の中に記述することでイベント発生元の要素を取得することができ、関数内で使用できる。上記のコードだと$('form')の要素。
script.js$(function() { $('form').on('submit', function() { this == $('form')//←イメージ }); });・イベントオブジェクトe
function(e)と記述することでイベント発生元の要素だけでなく押されたキーの情報なども取得できる。
script.js$(function() { $('form').on('submit', function(e) { e == $('form').on('submit',//←イメージ }); });
- 投稿日:2019-08-04T10:49:37+09:00
GASでSlackボット作成
Slack APIを使いこなす
postMessage
messageをSlackチャンネルにポストする関数
var postMessage = "https://slack.com/api/chat.postMessage"; var app_auth_token = "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; var channel = "#xxxxxxxx"; var message = "It is sample message!!"; function postMessageToSlackChannel(app_auth_token, channel, message){ const params = { "token" : app_auth_token, "channel" : channel, "text" : message }; const payload = JSON.stringify(params); const options = { "method" : "post", "contentType" : "application/json", "headers" : {"Authorization" : "Bearer "+ app_auth_token}, "payload" : payload };files.upload
fileをSlackチャンネルにポストする関数
postMessageと違ってoptionsの指定channelが複数形になっていないと指定されたチャンネルにアップロードされなくてつまづいた。
仕様書はよく読みましょうということ。※今回はSpreadSheet上のファイルをアップロードする。
var postMessage = "https://slack.com/api/files.upload"; var app_auth_token = "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; var channel = "#xxxxxxxx"; var wsName = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名"); var charts = wsName.getCharts(); var filename = 'chart.png' var file = charts[0].getBlob().getAs('image/png').setName(filename); function uploadFileToSlackChannel(app_auth_token, channel, file){ const payload = { "token" : app_auth_token, "channels" : channel, "file" : file }; const options = { "method" : "post", "payload" : payload }; return UrlFetchApp.fetch(uploadFileUrl, options); }
- 投稿日:2019-08-04T10:07:43+09:00
Typescript(Javascript)でURLクエリパラメーターを更新する
URLクエリパラメーターを更新するクラス
※ Typescriptで書いてます。Javascriptの場合は型指定あたりを削除すれば動くと思います。
class MySearchParams { static update(key: string, value: string): boolean { const params = MySearchParams.toObject(); params[key] = value; const url = "?" + Object.keys(params).map( (key: string) => key + "=" + params[key]).join("&"); history.replaceState('', '', url); history.pushState('', '', url); return true; } static get(key: string): string { const params: any = MySearchParams.toObject(); return params[key]; } static toObject(): Object { let vars = {}, max: number, hash: any, array: any = ""; let url = window.location.search; if (url.length === 0) { return vars; } hash = url.slice(1).split('&'); max = hash.length; for (let i = 0; i < max; i++) { array = hash[i].split('='); vars[array[0]] = array[1]; } return vars; } }使い方は以下のとおり
指定パラメーターの更新
MySearchParams.update(key, value)全てのパラメーターを連想配列で取得
MySearchParams.toObject()指定パラメーターの取得
MySearchParams.get(key)ブラウザのバージョンなどによっては、動作しないかもです。問題点などありましたら、コメントなどで指摘していただけると助かります<m(_ _)m>
- 投稿日:2019-08-04T01:32:59+09:00
ドットインストールjavascript~ヘルスケアwebサービスを自分で作る医者の日記~
数字タッチゲーム8の途中から


















