- 投稿日:2020-08-07T23:53:29+09:00
Array.prototype.filterメソッドを甘く見ていた…
今まであまり意識しなかったのですが、配列要素を削除する際に5行以上かけていたのですが、1行でシンプルに完結できて感動したので共有します。
今までの自分のコード
const array = [0, 1, 2, 3, 4]; console.log(`before : array = ${array}`); array.forEach((item, index) => { if(item === 1) { array.splice(index, 1); } }); console.log(`after : array = ${array}`);今後
const newArray = array.filter(n => n !== 1);(*IEで動かすには、BabelやTypescriptでコンパイルする必要があります)
今まで自分が書いてたコードの拙さを思い知らされました…
関数型プログラミングという概念があります。
JavascriptでいうとElmが有名かと思います。
最近になって知り合いの話を聞くと、この関数型プログラミングを学んでおくと、かなりエンジニアとしての地力がつくと教えられました。
その知人は、Elmを学んだ事でTypescriptやReact, Reduxといった概念がスッと理解できるようになったとか。他にも、(知り合いの超スゴいエンジニアの方いわく)今や、JSでfor分を使うのはあまりパフォーマンスの観点からよくなくて、Array.prototype.reduceを使うのが良いらしいです。
調べて見たら、こちらも(使いこなせるようになるまで時間はかかりそうですが)体得できればよりシンプルにコードを書けそうです。
関数型プログラミングの一種だそうです。………コードの書き方1つとっても、奥が深くて覚える事がいっぱいだーーーー!!!!(だからこそ、プログラミングは面白い)
- 投稿日:2020-08-07T23:13:13+09:00
Reactでデータグリッド/テーブルを実装するときに見てほしいおすすめコンポーネント集
データグリッド
Reactでデータグリッドを実装したいときにおすすめしたいコンポーネント集です。
Material UIが好きなので、Material UIを使っている私の目線でのコメントが多いですが、ご容赦ください。まだ実装お試ししていないけど良さそうなものがいくつかあるので、少しづつ追加しますよ :D
コンポーネント集
見る専部門
データを見せることに向いている系です。
Material UI - Table Component
Table React component - Material-UI
MaterialUI純正のテーブルコンポーネントです。ソートやフィルタは自分で実装してイベントで差し込んでいく感じですね。仮想テーブルもできますが、他のライブラリとのあわせ技なので、このコンポーネントの特徴ってことでもないですね。なにより、Material UIの純正なので、Material UIをアプリの全体荷適用しているなら第一候補ですね。見た目もスッキリ統一感が出ますしね。あとはなんて言ったって、Material UIはデモページもAPIのページもとっても詳しい。ありがたい。React-Table
Reactのテーブルといえばこれですね。名前もそのままReact-Table。いろいろな方がコントリビュートしてくれているので、やりたいことはなんだってできるような印象です。デモページもとっても豊富でわかりやすいですね。Material UIにこだわらないなら、第一候補ではないでしょうか?ちょっと見た目の調整は頑張らないといけないかもしれないですね。Style差し込んで行きましょう。
Grid.js
Grid.js - Advanced table plugin
比較的新しいライブラリです。TypeScriptで実装されているのがいいですね!新しい割にGitHubスター数が結構多いので、これからグイグイくるんじゃないかなぁ、という期待と、TypeScriptを採用しているので仲良くなれそうだなぁという理由から、序盤で紹介させていただきました。見た目もかっこいいですね。
Material-table
Materialデザインを踏襲して実装されたテーブルコンポーネントですね。Material UIのサイトでも紹介されているので、公式もその良さを認めているのかな?テーブル自体の操作感はよく、いいコンポーネントだと思います。
mui-datatables
Material-table と対を成すのが、mui-datatablesです。テーブル自体の操作感はかなり良いです。デモページも結構見やすくて、見ているだけでも楽しくなるので、おすすめです。gregnb/mui-datatables
SpreadSheet寄り編
データを見ながらちょちょっと修正したいときに便利なコンポーネントです。ほとんどExcelじゃん、ってのもあります。
react-data-grid
React Data Grid · Excel-like data grid component built with React
Excelライクな感じになっているが、それなりにWeb感も残しています。Excelほど自由自在にコピペできる感じではないのがちょっと惜しい。
React Datasheet
かなりExcelライクな感じですね。テーブルのほとんどの要素を編集可能にしないといけないケースには向いていそうですね!
ブルジョワ編
金の力は偉大だ!!!
ReactGrid (有償)
なにもいうことはないです。すげーよ。
- 投稿日:2020-08-07T22:57:54+09:00
JSでHTML上の添付ファイル取得とダウンロード
JSで添付ファイルを拾うのと、ファイルを落とす処理の実装サンプル的ななにか
<html> <head> <meta charset='utf-8'> <title>js file up/dl example</title> <script> window.onload = () => { const fr = new FileReader(); const el = document.getElementById("test"); fr.onload = (ev) => { const dl = document.createElement('a'); dl.setAttribute('href', ev.target.result); dl.setAttribute('download', el.files[0].name); dl.style.display = 'none'; document.body.appendChild(dl); dl.click(); document.body.removeChild(dl); }; el.addEventListener("change", () => { fr.readAsDataURL(el.files[0]); }); }; </script> </head> <body> <input type="file" id="test"></input> </body> </html>
- 投稿日:2020-08-07T22:27:59+09:00
継続渡しスタイル(CPS)チートシート
例によって,少なくとも約1名(自分自身)には役立ちそうだったので,各言語の継続渡しスタイル(Continuation-passing style,CPS)のサンプル記述を記事としてまとめた.
Python(Python 3):解説付き
対話モードで,
x
に10を代入してから,x + 20
を評価させてみる.>>> x = 10 >>> x + 20 30このプログラム記述をファイルにしてPythonインタプリタに実行させても,何も表示されない.対話モード(REPL)では,式として評価されたものはその結果を表示するのに対し,ファイル実行(スクリプト)では,そのような表示は行わないためである.
C:\Users\hoge>type sample.py x = 10 x + 20 C:\Users\hoge>python sample.py C:\Users\hoge>もし,ファイル実行で評価結果を表示させたい場合は,評価結果を得た後に,たとえば
C:\Users\hoge>type sample.py x = 10 print(x + 20) C:\Users\hoge>python sample.py 30 C:\Users\hoge>ここで,式として記述する場合は,評価結果を処理する関数を必ず指定しなければならない仕組みを考える.次は,
x + 20
を評価したら,その評価結果を関数f
に引数として渡して呼び出す関数cadd20
を定義し,f
にC:\Users\hoge>type sample.py def cadd20(x, f): f(x + 20) x = 10 cadd20(x, print) C:\Users\hoge>python sample.py 30 C:\Users\hoge\python>このように,結果を処理する手続きをあらかじめ指定する仕組みを想定したプログラミング手法を『継続渡しスタイル』(continuation-passing style,CPS)と呼ぶ.このスタイルは,そうとは意識されない形を含め,様々な実装に応用されている.
- コールバック関数(指定する手続き)とハンドラー(呼び出す関数)
- 例外処理の
try
(呼び出す手続き)とexcept
(指定する手続き)- CPSに自動変換して明確となった値受け渡しからの中間言語記述生成
なお,関数のCPSへの変換は容易であるが,変換した関数を使用するには工夫が必要である.ここでは,既存関数のCPSへの変換と利用例を示す(このチートシートの本体).
from operator import add, sub, mul # func(x, y) = (x + y) * (x - y) def func(x, y): return mul(add(x, y), sub(x, y)) print(func(10, 20)) # => -300 def cps(f): def cps(x, y, c): return c(f(x, y)) return cps cps(add)(10, 20, print) # => 30 def cfunc(x, y, c): return cps(add)(x, y, lambda c1: # x + y -> c1 cps(sub)(x, y, lambda c2: # x - y -> c2 cps(mul)(c1, c2, c))) # c1 * c2 -> c cfunc(10, 20, print) # => -300Scheme(Gauche,Guile)
; func(x, y) = (x + y) * (x - y) (define (func x y) (* (+ x y) (- x y))) (display (func 10 20)) ; => -300 (define (cps f) (lambda (x y c) (c (f x y)))) ((cps +) 10 20 display) ; => 30 (define (cfunc x y c) ((cps +) x y (lambda (c1) ; x + y -> c1 ((cps -) x y (lambda (c2) ; x - y -> c2 ((cps *) c1 c2 c)))))) ; c1 * c2 -> c (cfunc 10 20 display) ; => -300Ruby(CRuby)
# func(x, y) = (x + y) * (x - y) def func1(x,y) (x+y)*(x-y) end p func1(10,20) # => -300 add = -> x,y { x+y } sub = -> x,y { x-y } mul = -> x,y { x*y } prn = -> x { p x } cps = -> f { -> x,y,c { c.(f.(x,y)) } } cps[add][10,20,prn] # => 30 cfunc = -> x,y,c { cps.(add).(x, y, -> c1 { # x + y -> c1 cps.(sub).(x, y, -> c2 { # x - y -> c2 cps.(mul).(c1,c2,c) }) }) # c1 * c2 -> c } cfunc[10,20,prn] # => -300JavaScript(Node.js)
// func(x, y) = (x + y) * (x - y) function func1(x,y) { return (x+y)*(x-y) } console.log(func1(10,20)) // => -300 add = (x,y) => x+y sub = (x,y) => x-y mul = (x,y) => x*y cps = f => (x,y,c) => c(f(x,y)) cps(add)(10,20,console.log) // => 30 cfunc = function(x,y,c) { return cps(add)(x, y, c1 => // x + y -> c1 cps(sub)(x, y, c2 => // x - y -> c2 cps(mul)(c1,c2,c))) // x * y -> c } cfunc(10,20,console.log) // => -300備考
記事に関する補足
- そのうち『Iコンビネータ』に関する説明を追加するかもしれない(謎).
参考文献
- お気楽 OCaml プログラミング入門:継続渡しスタイル
変更履歴
- 2020-08-09:Schemeの
call/cc
利用例削除(Twitterコメントより)- 2020-08-07:参考文献欄を追加
- 2020-08-07:JavaScriptの例を追加
- 2020-08-07:初版公開(Python,Scheme,Ruby)
- 投稿日:2020-08-07T21:10:47+09:00
Node.js (JavaScript)でセミコロンを付けていなかったことで "TypeError: require(...) is not a function"が発生していた(JavaScriptの構文について)
今日JavaScript(Node.js)を書いていたときに遭遇した出来事を備忘録がてら書き残しておく。
エラーになったコード
下記のコードはエラーになる。
const fs = require('fs') (async () => { console.log(fs) })()実行結果
(async () => { ^ TypeError: require(...) is not a function上のエラーを解決させたコード
JavaScriptは
;
を書こうが書かまいがが動く、と思っていたが、1行目の末尾に;
をつけることで、今回のコードは問題なく動くようになる。const fs = require('fs'); (async () => { console.log(fs) })()※実行結果は長くなるので省略。サンプルコードが悪かった...
"TypeError: require(...) is not a function"が出る仕組み
これはどういうことかなと思ったけど、考えてみれば単純なことだった。
JavaScriptは文末にセミコロンを付けなかった場合、その後の文が構文的に解釈可能な場合、解釈しようとする。
自分もここらへんは自信がないので、JavaScript Primer の記述も引用させていただく。JavaScriptには、特殊なルールに基づき、セミコロンがない文も行末に自動でセミコロンが挿入されるという仕組みがあります。 しかし、この仕組みは構文を正しく解析できない場合に、セミコロンを足すという挙動を持っています。 これにより、意図しない挙動を生むことがあります。そのため、必ず文の末尾にはセミコロンを書くようにします。
引用元のページ: https://jsprimer.net/basic/statement-expression/#statement-expression-summary
つまり先ほど私が書いたコードは下記のように解釈された形となる。
// require('fs')(/* ~ */) 的な解釈となっていた const fs = require('fs')(async () => { console.log(fs) })()余談: prettierでセミコロンを付けない設定をした際の挙動
気になったので試してみた。
prettier
の設定でsemi: false
にしたとき、;
はどこにつくのか?
結果は下記の通り。const fs = require('fs') ;(async () => { console.log(fs) })()あとがき
普段
;
は付ける派なのだが、なんとなくプロトタイプのコードを書いていてつけないでいた。後からprettier
かければ済む話だとか考えていたら、思わぬエラーに引っかかった。
おかげでJavaScriptのことを少し知ることができたので結果的に良かったと思う。
- 投稿日:2020-08-07T19:53:15+09:00
テキストからWindowsのファイル名に使えない記号を置き換えるコード
Windowsのファイル名に使えない記号
\ / : * ? " < > |
を全角記号に置き換えるだけのコードです。
テキストをstr
の中に入れてお使い下さい。テンプレートリテラルなので改行ありでも大丈夫です。
そのままブラウザからF12 → consoleに打ち込めば結果が出ます。コード
var str = ` text `; console.log( str.replace(/\\/g, "¥") .replace(/\//g, "/") .replace(/:/g, ":") .replace(/\*/g, "*") .replace(/\?/g, "?") .replace(/"/g, "”") .replace(/</g, "<") .replace(/>/g, ">") .replace(/\|/g, "|") );
- 投稿日:2020-08-07T18:54:29+09:00
【Nuxt.js】Nuxt実践編:あると便利なコピーボタンの作り方
? この記事はWP専用です
https://wp.me/pc9NHC-xv前置き
ここ最近は文法編に力を入れていたので
久しぶりの実践編です✨input内のテキストを
コピーするボタンを作ってみましょう♪
イベントアプリなどでページを作成し、
自動生成されたurlをコピーしたい時なんかに使えます?urlの自動生成まではやりません。
あくまでinputとコピーボタンのみ作成します??
スタイリングも省いてます、そこはお好みで♪まずはinputを作成
コピーボタンの作り方は
3通り用意していますが、
input部分はどれも共通です?divではダメなのか
今回はコピーボタンがあるので
値が見えなくても@clickでコピーさえできればOK⭕️
そのためinputでやっていますが、
urlを直接選択するような場合は
スクロールの効くdivで作成すると良いと思います?divで作る場合も後述しておきます✍️
解説
readonly属性
urlを間違って編集したりしないようにします⚠️:value
今回はユーザーが入力する必要がないので
@inputが不要、双方向バインディングが不要です?
値だけバインドできればOK⭕️class="text"
input要素ではありますが、
入力不要でテキスト表示の役割のため。
コンポーネントにする場合も
InputText.vueなどの命名にし、
$attrsを使うのが良いと思います?⬇️双方向バインディング、
v-modelについてはこちら
https://wp.me/pc9NHC-kIコード
index.vue<template> <div class="page"> <input id="input" :value="url" type="text" readonly class="text" > </div> </template> <script> export default { data () { return { url: 'https://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb', } }, } </script>コピーボタンを作る
コピーと言えばdocument.execCommand()ですが廃止!
なのでClipboard APIと
nuxt-clipboard2を使ってみましょう?document.execCommand()も
一応…最後に載せています?方法1: Clipboard API
? 続きはWPでご覧ください?
https://wp.me/pc9NHC-xv
- 投稿日:2020-08-07T13:39:25+09:00
VeeValidateを使ってVueアプリでバリデーションをする
VeeValidate
VeeValidateは以下の特徴を備えたVue.jsのバリデーションライブラリーです。
ドキュメントを読みつつ訳しながらまとめた内容です。https://logaretm.github.io/vee-validate/
- テンプレートベースのバリデーション
- 多彩なバリデーションルールがデフォルトで用意済み
- 一級のローカライゼーションサポート
- HTML5のinputフォームとカスタムコンポーネントのバリデーションが可能
- カスタムルールとエラーメッセージも作成可能
はじめよう
利用方法
まずVueのインスタンスに登録します。
import Vue from 'vue'; import VeeValidate from 'vee-validate'; Vue.use(VeeValidate);コンフィグ設定したいならこちらの方法。
import Vue from 'vue'; import VeeValidate from 'vee-validate'; const config = { // config that you want } Vue.use(VeeValidate, config);ベーシックな例
inputフォームに
v-validate
ディレクティブとname
属性を追加するだけでOKです。name
属性はエラーメッセージの生成に利用されます。
v-validate
ディレクティブにはルールを設定します。パイプ|
を間に挟むことで複数のルールが適用可能です。
以下は「必須、かつ、eメールの形式であること」の例です。<input v-validate="'required|email'" name="email" type="text">エラーメッセージを表示するには
errors.first
メソッドを利用することでその項目の最初のエラーが取得できます:<span>{{ errors.first('email') }}</span>Tips
v-validate
に定義された値はシングルクォートで囲われています。これはディレクティブに与えられた内容はJavaScriptとして評価されるためです。
シングルクォートで囲むことでString
型であることを明示的にする必要があります。
v-validate="required"
としてしまうとrequired
というおそらく存在しないであろう変数や関数を参照しようとしてしまいます。シンタックス
バリデーションルールは
String
型での定義や、プログラマブルにしたい時はObject
型での定義も可能です。// String const single = 'required' const multiple = 'required|numeric' // Object const single = { required: true } const multiple = { require: true, numeric: true }ルールのパラメーター
ルールの一部はパラメーターを持つことができます。パラメーターは複数の定義方法が可能です。
String
型ならカンマ区切りの値Object
型なら配列の値Object
型でより複雑なパラメーターならオブジェクト// String型のパラメーター const someRule = 'included:1,2,3,4'; // Array型のパラメーター const someRuleObj = { included: [1, 2, 3, 4] }; // Object型のパラメーター const someCplxObj = { email: { allow_utf8_local_part: true } };ルールの実例
上の内容を実例でみてみましょう。
- 必須のEメールの入力欄
<input v-validate="'required|email'" type="email" name="email"> <input v-validate="{ required: true, email: true }" type="email" name="email">
- 必須でないユーザー名の入力欄
<input v-validate="'alpha'" type="text" name="username"> <input v-validate="{ alpha: true }" type="text" name="username">
- 必須かつ最低6文字のパスワード入力欄
<input v-validate="'required|min:6'" type="password" name="password"> <input v-validate="{ required: true, min: 6 }" type="password" name="password">エラーの表示
エラーメッセージが生成されると、エラー表示簡易化のために用意された
ErrorBag
インスタンスに保存されます。デフォルトでは
ErrorBag
のインスタンスはerror
という名前で各コンポーネントのcomputed
プロパティにインジェクトされます。
error
という名前は競合を避けるためにコンフィグからカスタマイズ可能です。エラーメッセージを1つ表示する
一般的には1つのフォームに対して1つのエラーを表示することが多いと思います。これは
errors.first('fieldName')
メソッドでエラーを取得可能です。<input type="text" name="fieldName" v-validate="'required'"> <span>{{ errors.first('fieldName') }}</span>Tips
VeeValidateのデフォルトでは1フィールドに対して1エラーしか生成しません。これはバリデーションパイプラインの高速化が理由です。
複数のバリデーションエラーのメッセージを同時に生成したい場合はfastExit
オプションをコンフィグからカスタマイズしてください。
あるいは、特定のフォームだけに適用したい場合はcontinues
modifilerの適用も可能です。v-validate.continues="'required|numeric'"
エラーメッセージを複数表示する
1つのフォームに複数のエラーを表示したい場合は
errors.collect('fieldName')
メソッドが利用できます。
このメソッドは1つのフィールドに紐づくエラーメッセージを配列で返します。<input type="text" name="fieldName" v-validate.continues="'required|alpha|min:5'"> <ul> <li v-for="error in errors.collect('fieldName')">{{ error }}</li> </ul>全てのエラーメッセージを表示する
errors.all()
を使いフラットなエラーメッセージの配列を取得できます。<input type="text" name="first" v-validate.continues="'required|alpha|min:5'"> <input type="text" name="second" v-validate.continues="'required|alpha|min:5'"> <ul> <li v-for="error in errors.all()">{{ error }}</li> </ul>フィールド名ごとにグルーピングしたい場合は、
errors.collect()
を引数無しで利用します。
キーがフィールド名で値がエラーメッセージの配列のオブジェクトが取得できます。<input type="text" name="first" v-validate.continues="'required|alpha|min:5'"> <input type="text" name="second" v-validate.continues="'required|alpha|min:5'"> <ul> <li v-for="group in errors.collect()"> <ul> <li v-for="error in group">{{ error }}</li> </ul> </li> </ul>バリデーションルール
いっぱいあるよ。
https://baianat.github.io/vee-validate/guide/rules.html
カスタムコンポーネントのバリデーション
VeeValidateはHTML5のinput要素だけでなくカスタムコンポーネントのバリデーションも対応しています。
カスタムコンポーネントでの利用はいくつか注意が必要です。このトピックではその注意点について説明します。どう動くか
カスタムコンポーネントを入力欄として動作させるのに
v-model
を利用して値を扱うことは一般的です。
VeeValidateはこの値を$watch
APIを利用して監視していますが、$watch
には制限があります。
たとえば、v-for
のイテレーターの値はv-for
のループのコンテキストとしてしか存在していないため監視できません。VeeValidateは
value
のpropを監視するようフォールバックします。
もしコンポーネントがmodel
コンストラクタをカスタマイズしている場合でも、正しいプロパティを検出しそれを監視します。このデモはVeeValidateとVuetifyのカスタムコンポーネントを組み合わせた例です。
以上はほとんどのケースをカバーしますが、
v-model
を利用して値を取り回していない場合は対応できません。
そのようなケースではコンポーネントのコンストラクターオプションを利用することでより細かなバリデーションの挙動を設定することができます。コンポーネントのコンストラクターオプション
バリデーターのカスタムコンポーネントへの挙動をカスタマイズすることにより不要な属性の追加などを防ぐことができます。
これは$_veeValidate
フィールドをカスタムコンポーネントに定義することで実現します:export default { // ... data: () => ({ // コンポーネント内部のデータ innerValue: 'initial' }) $_veeValidate: { // バリデーションの対象とするデータ value () { return this.innerValue; } }, }
$_veeValidate
ではvalue
含めて以下が設定可能です。
プロパティ 種類 初期値 説明 name () =>
,string
undefined
エラーメッセージの生成に使われる名前 value () =>
,any
undefined
バリデーションの対象となる値 rejectFalse boolean
false
false
がrequired
に対してバリデーションエラーとなるかevents string
`input blur` validator string
new
ornull
コンポーネントがバリデータのインスタンスをどう得るか。 new
の場合は新しいバリデーターインスタンスを生成して利用する。
- 投稿日:2020-08-07T11:15:48+09:00
Puppeteer 文字列で 特定の要素を選択したい時、またその文字列の近くの要素をクリックしたい時
Puppeteer 文字列で 特定の要素を選択したい時、
またその文字列の近くの要素をクリックしたい時
なぜ文字列で選択したいか
・Xpath脳死コピペ
・HTMLタグ
・クラス名やID名
では限定しきれない時があるから例えば
Yahoo!広告アカウントに送られてくる特定の名前のレポートのみをクリックしたい時
(あくまで抽象化するための例)ポイントは2点
①文字列で選択する方法
②その文字列自体をクリック・抽出しても意味がない
aタグまでパスを渡す結論:Xpathあんま理解してなかったのが俺が悪い
app.jsconst reportPath = "//span[contains(text(), 'hogehoge')]/../..//a"; await page.waitForXPath(reportPath); const reportClick = await page.$x(reportPath); await reportClick[0].click();``
- 投稿日:2020-08-07T11:11:41+09:00
JavaScript + SimpleBar: スクロールバーのスタイルをカスタマイズする
SimpleBarはスクロールバーをカスタマイズするライブラリです。スクロールバーを独自につくるのではなく、CSSのスタイルを割り当てるので、おかしな挙動は起こらず、ネイティブなスクロールのパフォーマンスが保たれます。あくまで、スクロールバーの見栄えを変えるだけです。
デザインはCSSで定める
SimpleBarは純粋なCSSでスクロールバーのスタイルを定めます。CSSで与えられるスタイルでさえあれば、自由にカスタマイズできるのです。
軽量なライブラリ
6KBのとても軽いライブラリです。JavaScriptはスクロールの動きそのものには触れません。ネイティブな動きとパフォーマンスが得られます。
モダンブラウザをサポート
ChromeとFirefox、Safariなどのモダンブラウザに加え、Internet Explorer 11をサポートします。
ライブラリの概要はドキュメントとデモページでお確かめください。本稿でつくるのは、つぎのサンプルです。「JavaScript + CSS: ヘッダを上部に固定してカラムの中身はスクロールさせる」のコードにSimpleBarのスタイルを割り当てました。
See the Pen JavaScript + SimpleBar: Customizing scrollbar style by Fumio Nonaka (@FumioNonaka) on CodePen.
インストール
インストールには、npmやyarnが使えます。
npm install simplebar --save
yarn add simplebar
また、unpkgとjsDeliverからCDNで読み込むこともできます。JavaScriptとCSSのライブラリがそれぞれ必要です。
<link rel="stylesheet" href="https://unpkg.com/simplebar@latest/dist/simplebar.css" /> <script src="https://unpkg.com/simplebar@latest/dist/simplebar.min.js"></script> <!-- または --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simplebar@latest/dist/simplebar.css" /> <script src="https://cdn.jsdelivr.net/npm/simplebar@latest/dist/simplebar.min.js"></script>バージョンを固定したいときは、
@latest
をバージョン番号に置き替えてください。たとえば、本稿執筆時の最新リリース版であれば、@5.2.1
です。unpkgでバージョンのリストが確かめられます。なお、Webpackなどのモジュールローダーを使う場合には、JavaScriptとCSSのライブラリを
import
してください。import SimpleBar from 'simplebar'; import 'simplebar/dist/simplebar.css';data-*グローバル属性で設定する
SimpleBarのもっとも簡単な使い方は、スクロールバーを加えたい要素に
data-*
グローバル属性としてdata-simplebar
を与えることです。なお、スクロールさせる要素には、CSSでoverflow: auto
を定めてください。<div data-simplebar> <!-- コンテンツ --> </div>これだけで、要素にはSimpleBarのスタイルでスクロールバーが表示されます(図001)。デフォルトでは、要素にマウスポインタを重ねたときバーが表れる自動表示の設定です。
図001■設定されたスクロールバー
つねにスクロールバーを表示しておきたいとき、タグに加えるオプション属性は
data-simplebar-auto-hide
です。JavaScriptコードの場合には、autoHide
オプションを用います。<div data-simplebar data-simplebar-auto-hide="false"></div>JavaScriptコードでSimpleBarを要素に設定する
JavaScriptコードで要素にSimpleBarを設定する場合は、
SimpleBar()
コンストラクタに要素の参照を渡すだけです。new SimpleBar(document.getElementById('myElement'));オプションは、コンストラクタの第2引数のオブジェクトにプロパティとして渡します。たとえばつぎのコードはスクロールバーの自動表示(
autoHide
)をオフにする場合です(デフォルト値はtrue
)。new SimpleBar(document.getElementById('myElement'), { autoHide: false });CSSでスクロールバーのスタイルを変える
SimpleBarのスクロールバーのスタイルは、CSSにより定められています。つまり、見栄えがCSSで変えられるということです。ここでは、スクロールさせるスライダのカラーをグラデーションにしてみましょう(図002)。こうしてでき上がったのが、冒頭のCodePenのサンプルです。
.simplebar-scrollbar::before { background: linear-gradient(darkblue, skyblue); }図002■スライダのカラーがグラデーションになった
SimpleBarのスクロールバーのCSSは、つぎの4つのクラスをもとに組み立てられています。具体的な定めについては、ソースコード
simplebar.css
をご参照ください。
simplebar-content
スクロールするコンテンツを包むラッパーsimplebar-scroll-content
スクロールする要素が収められたコンテナsimplebar-scrollbar
ユーザーがコンテンツを操作するスクロールバーのスタイルの定めsimplebar-track
スクロールバーが置かれた領域のスタイル
- 投稿日:2020-08-07T11:02:55+09:00
やさしいりあくとのはじめかた
この記事は株式会社富士通システムズウェブテクノロジーが企画するいのべこ夏休みアドベントカレンダー 2020の27日目の記事です。本記事の掲載内容は私自身の見解であり、所属する組織を代表するものではありません。
はじめに
本記事ではFacebook社のJavaScriptのSPAライブラリのReactについて紹介したいと思っています。
プロジェクトでフロントエンド基盤を整備することを目的に2020年4月に0からReactを勉強してきました。
この経験を踏まえ、React興味あるけど勉強の仕方がわからない、SPAを作ってみたいという方にとって、React開発を始めるきっかけになれればいいと思っています。
SPA(Single Page Application)ってなに?
SPAとは単一のWebページでアプリケーションを構築するアーキテクチャです。
サーバーサイドWebとSPAと比較すると...
上の画像を見てわかる通り、SPAは極力サーバーへのリクエストを減らし、単一のWebページのみを使用して、効率よくWebページの表示ができます。今が熱いReact
3大SPAフレームワーク/ライブラリは、
- React.js
- Vue.js
- Angular.js
がありますけど、ランキングはこんな感じ
ダウンロード数(2020/08/06現在)
githubスター数(2020/08/06現在)
こんな感じでいろんな人がReactをダウンロードして開発している
npm trends react vs vue vs angular
https://www.npmtrends.com/react-vs-vue-vs-angularはじめてのアプリ作成
さっそく、Reactアプリケーションを作ってみよう!
準備
下記のツールを自分の端末にインストール!
YARNを導入
npm install --global yarn
もしくは
npm i -g yarn
プロジェクト作成
JavaScript版でReactプロジェクトを作成する場合
npx create-react-app [プロジェクト名]
TypeScript版でReactプロジェクトを作成する場合
npx create-react-app [プロジェクト名] --typescript
プロジェクト起動
作成したプロジェクトまで移動
cd [プロジェクト名]
プロジェクトの起動
yarn start
http://localhost:3000/ で下の画面が表示される!
Hello World!を表示する
src/App.js
もしくはsrc/App.tsx
を開いて、以下の内容を変更して保存!src/App.jsimport React from 'react'; import logo from './logo.svg'; import './App.css'; function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> - Edit <code>src/App.js</code> and save to reload. + Hello World! </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;ロゴ画像の下に「Hello World!」と表示される
とっても簡単。りあくとのはじめかた
Reactの習得する方法は以下の流れ
- JavaScriptの習得
- (TypeScriptの習得) ※必要がある人だけ
- Reactの習得
おすすめ勉強サイト/書籍
・現代の JavaScript チュートリアル
・りあクト! TypeScriptで始めるつらくないReact開発 第2版
・React 公式サイト
・TypeScript 公式サイトやってはいけないこと
- いきなり完成されたコードを読もうとする
- HTML、CSS、JavaScriptの知識がない状態でReactの開発に臨む
- Reactの設計思想を知らない状態で開発を始める
基礎からちょっとずつ進めることをお薦めします。
みんなの反応
2020年7月17日(金)にウェブテクデーを使用して、チーム内でReact勉強会を開催しました。
私が講師として進めていました。開催後のみんなの反応はこんな感じです。H・Hさん
従来型のウェブ開発ばかりやっていると、モダンなJavaScript(ES6以降)の知識がコードが全く読めないことを痛感した。新しい技術に触れないとだめだなと感じたし、特にフロントエンドは流れが素早いと思った。E・Hさん
C#やJavaScript(ES5以前)はやってみたことがあったが、
今日の勉強会を通して、JavaSciprt(ES6以降)は新しい言語で臨むつもりで勉強しないといけないと感じた。
ただ、JavaScriptの新しい機能は便利だと思ったし、SPAの仕組みについても知れてよかった。
家でももっとやりたいと感じた。T・Sさん
業務チームのある程度の水準でスキルを均一化をどう図るかが今後の課題になってくる。Y・Sさん(React学習経験あり)
私は山田と一緒に1週間ペアプログラミングを行い、Reactを学びました。短い期間ですが、体験してみて感じたことは技術を学ぶ際には、必ず基礎から始めるべきだとということです。いきなり完成されたコードを読み込んでも、読めなくて挫折するだけです。
私はReactの学習を下記の流れで行いました。私はこれである程度実装できるようになりましたよ!
① HTML、JavaScript(TypeScript)の知識を習得する
りあクト! TypeScriptで始めるつらくないReact開発 第2版 ← これ本当におすすめ!
② Reactの公式ドキュメントの最初のページを読んで、Reactで何ができるかを知る
③ React公式ドキュメントに記載されているチュートリアルを行い、小さいコンポーネントから開発おわりに
4月から勉強を開始して、2か月間がっつりReactを独学で勉強しました。
フロントエンドの開発自体、あまり経験がなく学習にすごく苦労しましたが、
最終的にはウェブテクデーで人に教えられるレベルまで成長できたので良かったです。
- 投稿日:2020-08-07T10:57:34+09:00
javascriptでアナログ時計を作成
今回はjavascriptでアナログ時計を作ってみました。
なぜ作ったか
アナログ時計なので
時間周りの処理が必要なのでそこらへんの勉強になるのと、
あまりwebサイトではアナログ時計を見ないですが、サイトにあったら意外とお洒落かもと思って
作ってみました。
作るアナログ時計の完成イメージ
基本的な丸型の時計です。
コード
html
まずはアナログ時計の元になるhtmlを書いていきます。
必要なhtmlはごく少量です。
大きく分けて、必要なのは
- 外枠
- 時針
- 分針
- 秒針
- 時間の文字
これだけです。
<div class="c-clock"> // 外枠 <span class="c-clock__hour"></span> <!-- 時計 --> <span class="c-clock__min"></span> <!-- 分針 --> <span class="c-clock__sec"></span> <!-- 秒針 --> <span class="c-clock__12">12</span> <!-- 時計文字 --> <span class="c-clock__3">3</span> <!-- 時計文字 --> <span class="c-clock__6">6</span> <!-- 時計文字 --> <span class="c-clock__9">9</span> <!-- 時計文字 --> </div>
ちなみにbem記法で書いてるので気になる方はこちらも
https://qiita.com/w-tdon/items/2ede0122286f88db472f
css
.c-clock { position: relative; width: 400px; height: 400px; border: 1px solid #333; border-radius: 50%; } .c-clock__hour { position: absolute; top: calc(50% - 150px); left: calc(50% - 5px); width: 10px; height: 150px; background: #333; transform-origin: bottom; } .c-clock__min { position: absolute; top: calc(50% - 180px); left: calc(50% - 2px); width: 4px; height: 180px; background: #333; transform-origin: bottom; } .c-clock__sec { position: absolute; top: calc(50% - 200px); left: calc(50% - 1px); width: 2px; height: 200px; background: #ff0000; transform-origin: bottom; } .c-clock__12 { position: absolute; top: 10px; left: calc(50%); transform: translateX(-50%); font-size: 18px; } .c-clock__3 { position: absolute; top: 50%; right: 10px; transform: translateY(-50%); font-size: 18px; } .c-clock__6 { position: absolute; bottom: 10px; left: calc(50%); transform: translateX(-50%); font-size: 18px; } .c-clock__9 { position: absolute; top: 50%; left: 10px; transform: translateY(-50%); font-size: 18px; }
- 外枠
- width,height値を決め、border-radius: 50%で丸枠を作っています。
- 時針
- 外枠にposition: relativeを仕込んでいるのでabsoluteを使い上下左右中央に配置しています。
- top: 50%だと時針の高さ分ずれてしまうのでcalcを使い時針の高さ分引いてます。
- 分針
- 分針も時針と同じです。
- 時間文字 ここはwidth、heightを使ってないのでcalc(50% - ○px)とかして上下左右中央に配置できません。 なのでtop: 50%;を設定し、transform: translateY(-50%)で要素の表示位置を要素の半分の大きさ分、上にずらします。
js
setInterval(() => { // 現在時間の取得 const now = new Date(); const h = now.getHours(); const m = now.getMinutes(); const s = now.getSeconds(); // 時、分、秒を元に角度を計算 const degH = h * (360 / 12) + m * (360 / 12 / 60); const degM = m * (360 / 60); const degS = s * (360 / 60); // 各要素を取得 const elementH = document.querySelector(".c-clock__hour"); const elementM = document.querySelector(".c-clock__min"); const elementS = document.querySelector(".c-clock__sec"); // styleを追加 elementH.style.transform = `rotate(${degH}deg)`; elementM.style.transform = `rotate(${degM}deg)`; elementS.style.transform = `rotate(${degS}deg)`; }, 10);
まず、タイマー処理でよく使われるsetIntervalを使用します。
setInterval関数は一定時間ごとに繰り返し処理を行う関数です。
似たものでsetTimeoutがありますが、こちらは一定時間後に処理を行うだけで繰り返しはしません。
setInterval(関数,時間の指定)という感じで使用します。
上のコードでは10ミリ秒(0.01秒)ごとに処理を繰り返していることになります。
次は中の処理ですが、
現在時間の取得
ここでは現在時間をnew Date();で取得しています。
console.log(new Date())などとすると現在の日付、時刻などが取得できているのがわかると思います。
それぞれ現在の時間、分、秒をget◯◯で取得しています。
時、分、秒を元に角度を計算
上で取得した現在の時間、分、秒を元に針の角度を割り出しています。
- 時間: 一周は360度なので現在の時間(360/時間)としています。ですがそれだけだとダメなので現在の分(360/時間(12)/分(60))を足しています。
- 分、秒数: ここそれぞれの現在の分数、秒数*(360 / 60)としています。
要素の取得
document.querySelectorで各クラスを指定し要素を取得しています。
style追加
最後に取得した要素にstyleを追加し、現在時間を元に出した角度を設定します。
transform: rotate${}deg;
これを実行してみるとしっかり時計が動いていると思います。
こんな感じでcssとかjsを使えば割となんでも作れるなと思いました。
↓
ふざけた内容ですがこんな記事も書きました。https://qiita.com/w-tdon/items/1023e159dafbc0fd960d
終わり
- 投稿日:2020-08-07T10:56:50+09:00
JavaScript: 「エラトステネスの篩」を読んで関数にしてみた
とくに必要というわけではないのですが、最近、素数づいてるので書きます。
「エラトステネスの篩」の説明の記事を読んで、全然頭に入ってこなくてもやっとしてしまったので。
(記事のせいではないです。だんだん理解力が...)...困ったときのwikipedia。
エラトステネスの篩アルゴリズム
(中略)
ステップ 1
探索リストに2からxまでの整数を昇順で入れる。
ステップ 2
探索リストの先頭の数を素数リストに移動し、その倍数を探索リストから篩い落とす。
ステップ 3
上記の篩い落とし操作を探索リストの先頭値がxの平方根に達するまで行う。
ステップ 4
探索リストに残った数を素数リストに移動して処理終了。だそうな。
やってみます。
たぶん末尾再帰案件だとあたりをつけました。const primesInner = primes => sieveds => sieveds[0] > Math.sqrt(sieveds[sieveds.length-1]) ? [...primes, ...sieveds] //ステップ3>>4 : primesInner( [...primes, sieveds[0]] )( sieveds.slice(1).filter( e => e % sieveds[0] != 0 ) ) //ステップ2 const primesUpTo = n => primesInner( [] )( [ ...Array(n + 1).keys() ].slice(2) ) //ステップ1 primesUpTo(100) /* [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 ] */ああ、こういうことね。これだったらわかるわ...
- 投稿日:2020-08-07T09:20:12+09:00
正式リリース前に総予習!! Vue3の変更点まとめ
8月上旬に正式リリース予定とされているVue3の変更点をいち早く理解できるように概要をまとめてみました。それぞれの項目ごとにvuejs/rfc又はVue3 Documentへのリンクを貼っているので索引的に使ってもらえると嬉しいです。
この記事は以下バージョン時点の情報です。
Composition APIの追加
おそらく一番大きな目玉となる変更はこちら。Composition APIという新しいAPIが追加されます(PluginでVue2系でも使用可能です)。
Composition APIはコンポーネントのロジックの柔軟な再構成を可能にする関数ベースのAPI群です。
なお、Vue2系のOptions APIのサポートも継続されるので、Vue2系からのVue3へのバージョンアップ時にComposition APIに書き換える必要はありません。<!-- Vue3 Composition API --> <template> <form> <input type="text" v-model="formState.name" /> <input type="text" v-model="formState.value" /> <p>{{ contentLength }}</p> <button @click="submit" type="submit">submit</button> </form> </template> <script lang="ts"> import { defineComponent, computed, ref, onMounted, reactive } from "vue"; export default defineComponent({ props: { maxContentLength: { type: String, required: true } }, setup(props, context) { // reactive data const formState = reactive({ name: '', content: '' }) // computed const contentLength = computed(() => `${formState.content.length} / ${props.maxContentLength}`) // emit const submit = () => context.emit('submit', formState) // lifecycle hook onMounted(() => { // .... }) return { formState, contentLength, submit }; } }); </script>Composition APIについてはこちらの記事でより詳細にまとめています。
先取りVue 3.x !! Composition API を試してみる - Qiita
Vue Composition APIで使えるリアクティブ関連のAPI一覧 - QiitaTeleportの追加
Teleportは定義したコンポーネントが属するDOMツリーとは別の場所に、まるでテレポートしたかのようにコンポーネントを移動できる機能です。Vue2系でもサードパーティのプラグインLinusBorg/portal-vueで実現されていました。
以下のようにモーダル表示をハンドルするコンポーネントで
<teleport>
を使うと、to
で指定したDOM要素に内部のコンポーネントを移動できます。<template> <div class="container"> <button @click="toggleModal">toggle modal</button> <teleport to="#teleport-target"> <MyModal v-if="isVisible"/> </teleport> </div> </template> <script lang="ts"> import { defineComponent, ref } from "vue"; export default defineComponent({ setup() { const isVisible = ref(false); const toggleModal = () => { isVisible.value = !isVisible.value; }; return { isVisible, toggleModal }; } }); </script>
to
で指定できるDOM要素は自身のVueインスタンスをマウントしたDOM要素以外も指定できます。<html lang="ja"> <body> <div id="app"></div> <!-- VueがマウントされるDOM --> <div id="teleport-target"></div> <!-- teleportで指定されているDOM。ここにMyModalが表示される--> <script src="/dist/main.js"></script> </body> </html>
teleport
を利用すると、いままでCSSのz-index
で調整していたDOMの重なり順制御を、宣言的に制御できるようになりz-index
の指定に悩まされることはなくなります。
Vue3を入れたらすぐに使いたいと思える実用的な機能ですね。こちらの記事でも詳細をまとめています。
Vue.js 3.0 の新機能を試す。 〜 Teleport 編〜 - QiitaFragmentsの追加
FragmentsはVue2系では実現できなかったmulti-root nodeのコンポーネントを可能にするものです。
Vue2系ではコンポーネントのroot要素は必ず1つという制約がありました。<template> <div> <header>...</header> <main>...</main> <footer>...</footer> </div> </template>Vue3ではFragmentsのおかげでその制約がなくなり、root要素に複数の要素を記載できます。冗長なdivでのラップなどが不要になります。簡潔で良いですね。
<template> <header>...</header> <main>...</main> <footer>...</footer> </template>ただ、注意点としてコンポーネントに直接Class指定をしていると、今まで自動的にroot要素にClassを当てられたのですが、それがfragmentsの場合は明示的な指定が必要になるというのがあります。
Suspenseの追加(実験的)
Suspenseは非同期処理が解決されるまでフォールバックコンテンツ(例えばLoading中アイコン)を表示してくれる特別なコンポーネントです。いままで、
v-if="loading === true"
などの状態変数を使って制御していたものを、状態変数を使わずに簡潔に書くことができます。Suspenseはまだ実験的な機能で、Vue3.0の段階では仕様が確定しておらず今後変更が入ることも考えられます。Vue 3.1での正式リリースを見越しているとのことです。
<template> <Suspense> <template #default> <AsyncComponents/> <!-- 非同期処理を実行するコンポーネント --> </template> <template #fallback> loading... </template> </Suspense> </template>Suspenseの詳細はこちらにまとめています。
Vue.js 3.0 の新機能を試す。 〜 Suspense 編〜 - Qiitav-modelの仕様変更
v-modelの機能が拡張され、ひとつの要素に複数のv-modelの設定が可能になります。
Vue2系のv-bind.syncで実現していたようなことがv-modelで実現できるようになるイメージですね。この機能によってv-bind.syncは代替されるので利用できなくなります。以下v-modelの複数バインドの例です。
v-model:xxxx
のxxxのところで明示的にバインドするプロパティを指定しています。<!-- 親コンポーネント --> <template> <UserForm v-model:name="name" v-model:message="message" /> </template><!-- UserFormコンポーネント --> <template> <form> <label>name</label> <input type="text" @input="$emit('update:name', $event.target.value)" > <label>message</label> <input type="text" @input="$emit('update:message', $event.target.value)" > </form> </template> <script lang="ts"> import { defineComponent } from "vue"; export default defineComponent({ props: { name: { type: String, default: '' }, age: { type: String, default: '' } }, setup() { return {} } }) </script>また、modifiersの機能が拡張され、
.lazy
,.number
,trim
のデフォルトのmodifiers以外に独自に,modifiersを定義できるようになりました。
以下はcapitalizeというmodifiersを設定している例です。v-model:name.capitalize=
とすることで入力値にcapitalizeを実行しています。<!-- 親コンポーネント --> <template> <form> <MyName v-model:name.capitalize="form.name"/> <!-- ... --> </form> </template><!-- MyNameコンポーネント --> <template> <input :value="name" @input="updateName" type="text" name="name" /> </template> <script> import { defineComponent } from "vue"; export default defineComponent({ props: { name: { type: String, default: '' }, nameModifiers: { default: () => ({}) } }, setup (props, { emit }) { const updateName = event => { let val = event.target.value if (props.nameModifiers.capitalize) { val = val.charAt(0).toUpperCase() + val.slice(1) } emit('update:name', val) } return { updateName } } } </script>scoped CSSの仕様変更
scoped CSSで使える擬似クラスの仕様変更・機能追加が行われます。
まず1つ目が::v-deep()
でこれは、今まで/deep/
として設定していた、子コンポーネントにスタイルを適用するための擬似クラスです。
/deep/
の記法がDEPRECATEDとなり、新たに::v-deep()
が追加されています。::v-deep(.foo) {}/* コンパイル後 */ [v-data-xxxxxxx] .foo {}2つ目が、
::v-slotted()
で、これはslotで受け取った親コンポーネントの要素にスタイルを適用するためのものです。Vue3からデフォルトではslotで受け取った要素は、子コンポーネントのスタイルが適用されなくなるため、こちらが追加されました。::v-slotted(.foo) {}/* コンパイル後 */ .foo[v-data-xxxxxxx-s] {}最後が、
::v-global()
で、これはscoped CSSの中でグローバルなスタイルの定義を可能とするものです。この擬似要素を設定したクラスには[v-data-xxxx]
が付与されないため、Scopedではなくグローバルに適応されます。::v-global(.foo) {}.foo {}$attrsの仕様変更
$attrs
の機能が拡張され、今まで$listeners
で参照していたネイティブイベントや別管理であったclass、styleも全て包括して$attrs
から取得できるようになりました。<MyButton @click="handleClick" @custom="handleCustom" v-model="value" type="button" class="btn" />// MyButton.vue $attrs: { class: 'btn' type: 'button', onClick: handleClick, onCustom: handleCustom, 'onUpdate:modelValue': () => { value = payload }, }そのため、
$listeners
はDEPRECATEDとなります。(実行時に警告がでます)
$listeners
を使って透過的なラッパーコンポーネントを作っていた場合は、$listeners
を削除し$attrs
への書き換えが必要です。<!-- Vue2系 --> <input v-bind="$attrs" v-on="$liseners" /><!-- Vue3 --> <input v-bind="$attrs" />Global APIの仕様変更
Vueの初期化処理が変わります。
createApp
でインスタンスを生成し、そのインスタンススコープでuse
やmixin
などが適応されるようになります。
これによってテストケースでのグローバル設定の汚染を防いだり、同一ファイル内で別設定のVueインスタンスの初期化が容易になります。import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // インスタンスを生成 app.config.isCustomElement = tag => tag.startsWith('app-') app.use(/* ... */) // インスタンススコープで設定される app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.config.globalProperties.customProperty = () => {} app.mount(App, '#app')filterの廃止
filterは、パイプ演算子
|
を使って関数適応をlinuxの標準入出力のパイプラインするものですがJavaScriptにはない独自構文で学習コストが増加する、構文解析を複雑にするという理由で削除されます。filterの処理は通常の関数適応で代替できます。
<!-- filter形式 --> <p>{{ msg | uppercase | reverse }}</p> <!-- 通常の関数適応形式 --> <p>{{ reverse(uppercase(msg)) }}</p>他の代替方法についてはrfcs/0015-remove-filters.md#alternativesをご覧ください。
Event Emitter系のAPIの廃止
Event Emitter系のAPI(
$on
,$off
,$once
)が削除されます。
グローバルなイベント管理としてEvent Emitterを仕様している場合は書き換えが必要です。
Event管理の代替にはMittなどの別のEvent Emitterライブラリの利用が推奨されています。Functional Componentの廃止
Functional Componentはdata等の状態を持たない代わりにレンダリングパフォーマンスの大幅な改善が行えるコンポーネントです。
Vue3ではFunctional Componentを作る際に使用するfunctional: true
のオプションや、<template functional>
が削除されます。Vue3では、通常のコンポーネントとFunctional Componentの性能差は大幅に縮小され、ほとんどのユースケースでは取るに足らないものとなったそうです。
SFC上でfunctionalを使用している場合は、functionalの属性を削除し、attrs、listnersの参照方法の修正が必要です。
<!-- Vue2 functional component --> <template functional> <component :is="`h${props.level}`" v-bind="attrs" v-on="listeners" /> </template> <script> export default { props: ['level'] } </script><!-- Vue3 --> <template> <!-- functionalを削除 --> <component v-bind:is="`h${props.level}`" v-bind="$attrs" <!-- attrs及びlistnersは$attrsにまとめられる --> /> </template> <script> export default { props: ['level'] } </script>終わりに
以上「正式リリース前に総予習!! Vue3の変更点まとめ」でした。
色々ワクワクするような新機能が追加されていてVue3のリリースが待ち通しいですね。
他にも諸々細かい点が変わってるのでより詳細な変更はvuejs/rfcをご確認ください。参考
- 投稿日:2020-08-07T09:04:48+09:00
ServiceNowからTeamsに通知を飛ばす
概要
ServiceNowではIntegrationHub にSlack Spoke, Microsoft Teams Spoke その他メッセージ送信するアクションがありますが、
別のサブスクリプションが必要なので、RESTメッセージを使用して実装できないか調べてみました。プラットフォーム
Paris
サンプルケース
変更要求のステータスが実装になるとTeamsに通知するというケースを想定
変更要求の更新をトリガーでビジネスルールでTeamsのWebhookにメッセージを送信します。手順
Webhookの設定
Webhookの設定は他の記事を参考にして
Microsoft Teams API (Incoming Webhook) で投稿エンドポイントをコピーしておく
RESTメッセージの設定
System Web Services > Outbound > REST Message から[New] ボタンを押してREST Messageを登録
コピーしたエンドポイントをここにペースト
登録後RESTメッセージ関数(HTTP Methods)を作成
今回はDefault GETを編集しました。
HTTPメソッドをPOSTにして更新
テスト送信
Script - Backgroundで実行してみます。
bg_script.jsvar restMessage = new sn_ws.RESTMessageV2("Teams通知", "メッセージ送信"); var message = "メッセージテスト"; var body = createBody(message); restMessage.setRequestBody(body); var response = restMessage.executeAsync(); function createBody(message) { var body = { type : "message", text : message }; return new JSON().encode(body); }ビジネスルールを設定
変更要求の更新をトリガーにしてメッセージを送信するビジネスルールを作成
実行タイミングは非同期にしています。
ChangesやChangesToは変更前が無いから非同期では使えないと思っていたのですが、コンディションビルダーで使用する場合には使えるらしいです。知らなかった。
https://docs.servicenow.com/bundle/paris-application-development/page/script/business-rules/reference/r_HowBusinessRulesWork.html
コードはこんな感じで書いてみる
send_change_implementation.js(function executeRule(current, previous /*null when async*/) { var restMessage = new sn_ws.RESTMessageV2("Teams通知", "メッセージ送信"); var message = createMessage(current); var body = createBody(current, message); restMessage.setRequestBody(body); var response = restMessage.executeAsync(); })(current, previous); function createMessage(current) { var url = gs.getProperty('glide.servlet.uri')+'/change_request.do?sys_id=' + current.sys_id; var message = '【お知らせ】以下の変更を実装します!<br/>' + '番号:<a href="' + url + '">' + current.number + '</a><br/>'; message += '作業名: ' + current.short_description + '<br/>'; message += '終了予定時刻: ' + current.end_date.getDisplayValue(); return message; } function createBody(current, message) { var body = { type : "message", text : message }; return new JSON().encode(body); }
- 投稿日:2020-08-07T08:19:50+09:00
console.logでJSONから特定の要素を取り出す方法
JavascriptでJSONから特定の要素を取り出す際の考え方が配列のときと少し異なるのでまとめました。
JSONとは
- JavaScript Object Notationの略。直訳すると「Javascriptオブジェクト記法」ということになる。JSONにおけるJavascriptオブジェクトとは基本的には、{}(オブジェクト)と[](配列)を組み合わせてデータ構造を表現したものをJSONとして扱うことができる。
→つまり、JSONとは、{}(オブジェクト)と[](配列)を組み合わせてデータ構造のこと。
JSONの特定の要素の取り出し方
example.tsxconst messageArrayContainer: any[] = [{ "text": ["Suzuki", "Yamada", "Miyazaki" ] "user": {"_id": 1, "avatar": "", "name": ""} }]; console.log('データ' + JSON.stringify(messageArrayContainer, replacer)); console.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) );//データ [{ "text": ["Suzuki", "Yamada", "Miyazaki" ] "user": {"_id": 1, "avatar": "", "name": ""} }] //userデータ {"_id": 1, "avatar": "", "name": ""}ここで、注意なのが、配列と同じように考えると、userデータのみを取り出したいときに、下記のように書きたくなるがこれだとundefinedが表示される。
example1.tsxconsole.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) ); //結果は,undefinedになるJSONは大きな一つの要素と考え、
example2.tsxconsole.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) ); //出力: userデータ{"_id": 1, "avatar": "", "name": ""}と書く。