20210806のJavaScriptに関する記事は12件です。

【JavaScript】Macrotasks?Microtasks?どういうもの?

はじめに JavaScriptには2種類の非同期処理のキューが存在します。 それが、、MacrotasksとMicrotasksです。 それがどういったものかを見ていこうと思います! Macrotasksとは Macrotasksはタスクキューとも呼ばれており、1つずつタスクを実行します。 例えば、setTimeoutやsetIntervalなどのコールバック関数が該当します。 ※ジョブキューの後に実行される。 Microtasksとは Microtasksはジョブキューと呼ばれており、順番が回ってきたら全てのタスクを実行します。 こちらはPromiseなどが該当します。 ※タスクキューのより先に実行される。 動きの解説 以下のコードを利用して実行順序がどうなっているかの解説を行います。 // 非同期処理かつMacrotaskなのでタスクキューに追加 setTimeout(function task1() { console.log('task1'); }); // Promiseの即時関数を定義 new Promise(function promise(resolve) { // この部分は同期的に処理されるので一番早くコンソール出力する console.log('promise'); resolve(); }).then(function job1() { // 非同期処理かつMicrotaskなのでジョブキューに追加 console.log('job1'); }); // グローバルコンテキストが終了したのでここが実行される console.log('global end'); 実行の流れ ①まず、setTimeout関数は非同期処理のためタスクキューに追加される。(ここでは実行されない) ②次に、Promiseの中身である関数では同期的に処理されるので、一番最初に処理されます。 ③thenメソッドも非同期処理のため、タスクキューに追加されるため実行されません。 ④ここで、最後の行のコードであるconsole.log('global end');が実行されます。 ⑤setTimeout関数はMacrotaskで、thenはMicroTaskなので、thenが先に実行されます。 ⑥最後にキューに残っているsetTimeout関数の処理を実行して終了です。 ちなみに実行結果は以下の通りです。 "promise" "global end" "job1" "task1" 終わりに ややこしい部分ではありますが、ここを理解しておかないと実装時に意図しないエラーが発生することもあるので気をつけましょう! 参考 【JavaScript】Macrotasks と Microtasks JavaScript初心者でもよくわかる!コードの非同期処理
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ブラウザからAWS S3にマルチパートアップロードをする

はじめに Webアプリケーションでブラウザから直接S3にマルチパートファイルアップロードをする方法を備忘録的に残します。苦しんでる人の助けになればと思います。 動作する全てのコードはここにあります。 https://github.com/inunekousapon/s3_sts_upload_sample やること STSを利用したS3への直接アップロード マルチパートアップロード やらないこと マルチパートアップロードの自前実装 署名付きURLを利用したオブジェクトのアップロード ブラウザからS3に直接アップロードする方法 2つの方法があります。 署名付きURLアップロード AWS Security Token Serviceを使った方法 通常、署名付きアップロードを使うのが最適な選択肢になると思います。しかし、マルチパートアップロードを選択しようと思うと実装が難しいことがわかりました。 下記は署名付きURLを利用したマルチパートアップロードの記事です。 https://zenn.dev/kujime/articles/484b6e25d058fb このSDKのissueでは署名付きURLを利用したマルチパートアップロードが使いづらいという点について話し合われています。(2021.08.06現在解決していません) https://github.com/aws/aws-sdk-js/issues/1603 一方、AWSSDK for JavascriptにはManagedUploadというメソッドがあり、完全にマルチパートアップロードに対応しています。なぜ、署名付きURLアップロードに使えないのか理解に苦しみます。 The managed uploader allows for easy and efficient uploading of buffers, blobs, or streams, using a configurable amount of concurrency to perform multipart uploads where possible. This abstraction also enables uploading streams of unknown size due to the use of multipart uploads. マルチパートアップロードなどという面倒な実装はAWS公式のライブラリに任せたいので、「AWS Security Token Serviceを使った方法」を紹介したいと思います。 コード サーバー側 app.py import os import json import boto3 from flask import Flask, render_template app = Flask(__name__) @app.route('/', methods=['GET']) def upload_file(): sts_connection = boto3.client('sts', aws_access_key_id=os.getenv('AWS_ACCESS_KEY'), aws_secret_access_key=os.getenv('AWS_SECRET_KEY'), region_name='ap-northeast-1', ) b = sts_connection.get_federation_token( Name="Bob", DurationSeconds=900, Policy='{"Version":"2012-10-17","Statement":[{"Sid":"Stmt1","Effect":"Allow","Action":"s3:PutObject","Resource":"*"}]}' ) access_key_id = b['Credentials']['AccessKeyId'] secret_access_key = b['Credentials']['SecretAccessKey'] session_token = b['Credentials']['SessionToken'] return render_template('index.html', access_key_id=access_key_id, secret_access_key=secret_access_key, session_token=session_token, bucket_name='your bucket name', object_key='your object key', ) flaskによるサンプルです。 ブラウザで利用できる一時的な認証情報を取得するにはAsumeRoleまたはGetFederationTokenのどちらかを利用するといいと思います。今回はGetFederationTokenを利用しています。 (問題がある場合のご指摘お待ちしております) get_federation_tokenのPolicyをより厳密に書くことで、アップロードしたいキーのみ許可するなど署名付きURLによるアップロードと同等のアクセス制御を作ることができます。 FederationTokenを発行するには下記のアクセス権限が発行元のユーザーやロールに必要なので事前に設定する必要があります。 { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": "sts:GetFederationToken", "Resource": "*" } ] } クライアント側 index.html <!doctype html> <html> <head></head> <body> <title>Upload new File</title> <h1>Upload new File</h1> <input id="upload" type="file"> <button id="addFile" onclick="addFile()"> アップロード </button> <div id="progress"></div> <script src="https://sdk.amazonaws.com/js/aws-sdk-2.961.0.min.js"></script> <script type="text/javascript"> function addFile() { var files = document.getElementById("upload").files; if(!files.length) { return alert("No file."); } var bucket = "{{ bucket_name }}"; var file = files[0]; var key = "{{ object_key }}"; AWS.config.update({region: 'ap-northeast-1'}); AWS.config.credentials = new AWS.Credentials( accessKeyId="{{access_key_id}}", secretAccessKey="{{ secret_access_key }}", sessionToken="{{ session_token }}", ) var promise = new AWS.S3.ManagedUpload({ params: { Bucket: bucket, Key: key, Body: file } }).on('httpUploadProgress', function(evt) { var disp = "Uploaded :: " + parseInt((evt.loaded * 100) / evt.total)+'%'; console.log(disp); document.getElementById('progress').innerText = disp; }) .promise(); promise.then( function(data) { alert("Successfully uploaded file."); }, function(err) { return alert("There was an error uploading your file: ", err.message); } ); } </script> </body> </html> 自前でマルチパートアップロードを書くよりかなり記述量が少なくなったかと思います。 'httpUploadProgress'のイベントでアップロードの進捗状況を取得することができます。 まとめ 公式のライブラリにマルチパートアップロードする仕組みがあるから、それをなんとか使う方法を模索したほうが楽です。 セキュリティ的に盲点があるかもしれないため、問題点があるのならコメントがほしいです。 一緒にAWSで苦しんでいける仲間を募集しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptを基本からまとめてみた【8】【closest()メソッド】

はじめに 学習するに至った経緯 2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。 入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、 卒業後、フロントエンドのエンジニアを目指す事に。 Javascriptの学習した事を言語化し、認識の深化による備忘録として記載。 「closest」とは 『closest()』は、基本的に親要素を取得することができるメソッド。 ただし、検索性と高速性を兼ね備えているのが特徴で、指定した「タグ・属性」を持つ親要素を瞬時に探し出せる。 「closest」の使い方 直近の親要素を「closest」で取得する 一般的な記述方法としては、【要素.closest(セレクタ)】のように対象要素へセレクタを指定する。 sample.html <body> <div class="wrap"> <ul> <li>項目1</li> <li>項目2</li> <li>項目3</li> </ul> </div> <script> var result = $('li').closest('div'); console.log( result ); </script> </body> このli要素に対して、「.closest(‘div’)」と記述することで親要素に「div要素」があるかどうかをチェックできる。注意点は、li要素から最も近い場所にある対象のdiv要素だけを取得するという点で、親要素としてdivタグが複数あったとしても、最初に合致したdiv要素だけを取得する。 参考サイト 【jQuery入門】closest()で親要素を取得する方法まとめ!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

three.jsでVRツアーを作成する

の続きです Aframe や panolens.js の方がレスポンシブルで使いやすいが ビデオやcanvasと組み合わせ場合、複雑になるのでthree.jsから作った方が デバッグしやすいと考えて、作成 参考 https://threejs.org/examples/webgl_panorama_equirectangular.html https://threejs.org/examples/webgl_geometry_terrain_raycast.html  の function onPointerMove( event ) raycastで座標を取得 webgl_panorama_equirectangular.html を基に 変更 webgl_panorama_equirectangular.html let mesh; let group; const raycaster = new THREE.Raycaster(); const pointer = new THREE.Vector2(); mesh = new THREE.Mesh( geometry, material ); webgl_geometry_terrain_raycast.html  の function onPointerMove( event ) を onMouseDownへ変更して 追加 webgl_panorama_equirectangular.html window.addEventListener( 'mousedown', onMouseDown ); function onMouseDown( event ) { pointer.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1; pointer.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1; raycaster.setFromCamera( pointer, camera ); // See if the ray from the camera into the world hits one of our meshes const intersects = raycaster.intersectObject( mesh,true ); //const intersects = raycaster.intersectObject( group,true ); // Toggle rotation bool for meshes that we clicked if ( intersects.length > 0 ) { console.log( intersects[0].point.x + ", " + intersects[0].point.y + ", " + intersects[0].point.z ); console.log(intersects[0].object.name); } } 背景球を設置 少し小さくする webgl_panorama_equirectangular.html const geometry = new THREE.SphereGeometry( 500-50, 60, 40 ); console.logで配置したい座標を記録 記録した座標へspriteを配置 webgl_panorama_equirectangular.html group = new THREE.Group(); const map = new THREE.TextureLoader().load( "info.png" ); const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff, depthWrite: false} ); const sprite = new THREE.Sprite( material ); sprite.name = "point1"; group.add( sprite ); sprite.position.set( 214.48695923481648, -50.46751981995689, -447.88923840211703); sprite.scale.set(100, 100, 1); scene.add( group ); 重なっているので背景球の大きさを戻す webgl_panorama_equirectangular.html const geometry = new THREE.SphereGeometry( 500, 60, 40 ); onMouseDownへクリック判定と別画像をロード 追加 webgl_panorama_equirectangular.html //const intersects = raycaster.intersectObject( mesh,true ); const intersects = raycaster.intersectObject( group,true ); if (intersects[0].object.name=="point1"){ var material = mesh.material; material.map = new THREE.TextureLoader().load( './r2.jpg' ); material.map.needsUpdate = true; } ブラウザで確認
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unityを利用してthree.js用のパノラマ画像を作成する

VRツアーをthree.jsで作成しようとサンプル素材を探したところ 1フロア各所のパノラマ画像が全然なく Unityを利用してパノラマ画像を作成しました インストール Unity2020.3 Unity Recorderをpackageから 部屋のアセットを購入、インポート シーン設定 ライティングやマテリアルの設定で何度も録画するため、 タグ機能を使い複数の場所を同時に出力できるようにする タグをr1 - r7までつくり カメラの複製、位置移動、タグ設定を繰り返す Unity Recorder設定 Recording Mode -> Single Frame Capture Source -> 360 View Camera -> TaggedCamera Tag -> r1 * Output File File Name -> r1 * Add Recorderで、追加して*部分を割当 Recordしてファイル生成 three.jsに埋め込み コードは、公式サンプルの https://threejs.org/examples/webgl_panorama_equirectangular.html を参考 テクスチャのパスだけ変えて webgl_panorama_equirectangular.html const texture = new THREE.TextureLoader().load( 'textures/r1.jpg' ); ブラウザで確認 つづき
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[JavaScript]Promiseで簡単に非同期通信を実現する...!

はじめに 個人的に非同期通信にはニガテ意識がずっとありました。 そこで、Promiseというものを知り、それを理解することで、非同期通信も併せて理解できました! ここでは、Promiseの使い方を知って、JSの非同期通信の実装方法を学びながら併せて非同期通信についても理解しましょう! Promiseとは Promiseとは、非同期処理をより簡単に、可読性が上がるように書けるようにしたものです。 「非同期処理」と「コールバック処理」を組み合わせはよく使うのですが、構造が複雑化して可読性が低くなる欠点がありました。そこで誕生したのがPromiseです。 使い方 基本的な使い方は以下の例の通りです。引数はresolveとrejectを取ります。 resolve 処理成功時に実行する関数。thenにコールバックする。 reject 処理失敗時に実行する関数。catchにコールバックする。 finally Promiseオブジェクトが処理され終了する前に実行される処理。 引数を取ることが出来ない。 new Promise(function(resolve, reject) { resolve('成功'); reject('失敗'); }).then(function(data) { console.log(data); // => "成功" }).catch(function(data) { console.log(data); // => "失敗" }).finally(function() { console.log('終了'); // => "終了" }) thenを使用してコールバック処理 Promiseオブジェクトにthenメソッドを使うことで成功時のコールバック処理を行うことが出来ます。 new Promise(function(resolve) { resolve('成功'); }).then(function(data) { console.log(data); // => "成功" }) Promiseチェーンで処理を連結させる thenを繋げることで複数の非同期処理を順次実行することが出来ます。これによって、階層構造が複雑化しにくくコードの可読性も上がります。 ※thenメソッドの最後にはPromiseオブジェクトを返すようにする。 // Promiseオブジェクトを返す関数を定義 function promise(val) { return new Promise(function(resolve) { resolve(val); }) } promise(1).then(function(val) { console.log('成功その' + val++); // => "成功その1" return promise(val); }).then(function(val) { console.log('成功その' + val++); // => "成功その2" return promise(val); }).then(function(val) { console.log('成功その' + val++); // => "成功その3" }) allで複数のPromiseを実行 .all()メソッドを利用することで、複数の非同期処理を実行することもできます。 function sample1s() { return new Promise(function(resolve) { setTimeout(function() { resolve('1秒後に実行'); }, 1000) }) } function sample3s() { return new Promise(function(resolve) { setTimeout(function() { resolve('3秒後に実行'); }, 3000) }) } function sample5s() { return new Promise(function(resolve) { setTimeout(function() { resolve('5秒後に実行'); }, 5000) }) } Promise.all([sample1s(), sample3s(), sample5s()]) .then(function(data) { console.log(data); console.log('すべての処理が終了しました'); }) // => ["1秒後に実行", "3秒後に実行'", "5秒後に実行'"] // => "すべての処理が終了しました" catchを使用してエラーハンドリング Promiseオブジェクトにcatchメソッドを使うことでエラーハンドリングを行うことが出来ます。 new Promise(function(reject) { reject('失敗'); }).catch(function(data) { console.log(data); // => "失敗" }) 簡単な使い方(Async/Await) Async/Awaitを利用することで、Promiseによる非同期処理をより簡潔に効率よく記述することが出来ます。 Async 「async」を「function(){ }」の前に記述することで非同期処理を実行できる関数を定義できます。 Await Promise処理の結果が返ってくるまで一時停止してくれる。 // Promiseオブジェクトを返す関数を定義 function samplePromise(message) { return new Promise(function(resolve) { setTimeout(function() { resolve(message) }, 3000) }) } // async〜で関数を定義 async function sampleAsync() { // Promiseオブジェクトが返るまで待機し、返った値を変数に格納 const result = await samplePromise('成功'); console.log(result); } sampleAsync() // => "成功" 終わりに いや〜、ややこしい部分はありますが、非同期通信を簡単に実装できるのは嬉しいですね。。 これからの僕のJS人生は少し色付きました。 参考 Promise 【JavaScript】初心者にもわかるPromiseの使い方 【JavaScript入門】誰でも分かるPromiseの使い方とサンプル例まとめ! 【JavaScript】Macrotasks と Microtasks 【JavaScript入門】5分で理解!async / awaitの使い方と非同期処理の書き方
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js 16.6.0からArray.at()が使えるようになった

Changelog Reference .at()とは -1を渡すと末尾の要素を、-2を渡すと末尾から2番目の要素を返す、ブラケット[]の拡張。 Array[Array.length - 1] が Array.at(-1)のように書ける。簡単。嬉しい。 去年の11月からTC39 ProcessのStage 3に格上げされ、Chrome 92 および Firefox 90から利用可能となっている。 https://github.com/tc39/proposal-relative-indexing-method その他の提案 もっとシンプルに自由に配列にアクセスしたい、という思いから提案された仕様は他にもある。 ブラケットのスライス表記 元からあるslice()メソッドが分かりにくすぎる!という提案。 PythonやGolang等にある[1:3] [-1:]のような書き方を追加するというもの。 良さそうだけどドラフトになる気配なし… .lastItem .lastIndex その名の通り、最後の要素を指すlastItemと、最後のインデックスを指すlastIndexを追加する というもの。 .at()又はスライス表記のどちらかがStage 3に進めば、提案は破棄という予定だったので消滅。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javascriptでリテラルなArrayの前はセミコロンが必要です。

表題の通りなのですが、なぜ今まで一度も引っ掛からなかったんだろう?という奇妙だけどありそうなエラーに引っかかったので共有します。まあ、セミコロン省略しないで必ず書く人は引っかからないでしょう。 一部抜粋ですがこのコードはUncaught TypeError: Cannot read property 'forEach' of undefinedのエラーになります。 form.target = 'ServiceItemForm' [ { name: 'shop_id', value: this.props.currentShop.id }, { name: 'category', value: category }, { name: 'sub_category', value: sub_category }, { name: 'name', value: name } ].forEach(item => { //ここでエラー! .... }) どう見てもちゃんとしたArrayだしなんでだ?と思ったのですが、詳しく読み解いてみると・・・ //セミコロンがないので'ServiceItemForm'のプロパティーにアクセスしようとしてる form.target = 'ServiceItemForm'[...].forEach //[]の中は複数のオブジェクトをカンマで列挙してるので一番最後のオブジェクトが評価される form.target = 'ServiceItemForm'[{ name: 'name', value: name }].forEach //{ name: 'name', value: name }が文字列に変換される form.target = 'ServiceItemForm'['[object Object]'].forEach //'ServiceItemForm'['[object Object]']はundefined 今まで鬼のようにJS書いたけどこれは初だったかも。でも割とセミコロン書かない方なので不思議だなあ。 https://stackoverflow.com/questions/38908243/cannot-read-property-foreach-of-undefined またスタックオーバーフローに助けてもらいました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

素のJavaScript(node)だけでmicroCMSのデータを全て取得してみた

例えばNextJSのビルド前だったりGatsbyJSのgatsby-node.js(nodeしか使えないページ)、ライブラリが使えない、などの何らかの形で素のJSだけでお手軽にデータを取得したい時があります。 microCMSがそのケースでした。その時に少し工夫が必要だったので知見としてコードを載せてみました。 GETのデフォルトが10件までしか取得できない 通常は以下のようなコードで取得すると思います。 node.js const axios = require('axios').default; require('dotenv').config({ path: '../../.env' }); // package.jsonから動かす場合はpathが通っていると思われるので不要。必要であれば.envのあるファイルの相対パスを記載 const getMicroCMSdata = async() => { const url = `https://hoge.microcms.io/api/v1/hoge`; const apiKeyHeaderOption = { headers : { "X-API-KEY": process.env.MICROCMS_API_KEY }}; return await axios.get(url, apiKeyHeaderOption).then(r => r.data); } console.log(getMicroCMSdata().then(data => console.log(data))); しかし記事データを確認すると10件しか取得できていません。 取得したJSONの中身を確認すると { contents: [ {省略}... ], totalCount: 100, offset: 0, limit: 10 } となるように limit: 10 が返ってきています。確認したところやはり limit: 10 が取得できる件数を示していました。 したがって、この limit の上限を自身のコンテンツの数(totalCount以上)に設定する必要があります。 ただし、面倒であれば url に ?limit=1000 のような大きめの数字でオプションをつけてあげれば済みます。 ですがそれだとちょっと気持ち悪いので先に totalCount を取得してから ?limit=${totalCount} となるようなコードを書きました。 2回GETさせてみた node.js const axios = require('axios').default; require('dotenv').config({ path: '../../.env' }); // package.jsonから動かす場合はpathが通っていると思われるので不要。必要であれば.envのあるファイルの相対パスを記載 const getMicroCMSdata = async() => { const url = `https://hoge.microcms.io/api/v1/hoge`; const apiKeyHeaderOption = { headers : {"X-API-KEY": process.env.MICROCMS_API_KEY }}; const getUrlOption = (number, url) => { const UrlandOption = url + `?limit=${number}`; return String(UrlandOption); } // microCMSのコンテンツを引っ張ろうとするとデフォルトでlimit=10のオプションがついており全てのコンテンツを引っ張ってこれない。totalCountでコンテンツ総数をチェック const getTotalCountUrl = getUrlOption(0, url), totalCountUrlData = await axios.get(getTotalCountUrl, apiKeyHeaderOption).then(r => r.data), { totalCount } = await totalCountUrlData; // 2回目のGET const getContentUrl = getUrlOption(totalCount, url), contentUrlData = await axios.get(getContentUrl, apiKeyHeaderOption).then(r => r.data), { contents } = await contentUrlData; return contents; } console.log(getMicroCMSdata().then(data => console.log(data))); getUrlOption の関数で引数に応じた ?limit=${number} のオプションをURLに追加させています。 初回のGET時は ?limit=0 にして無駄なリソースを取得しないようにして、2回目のGET時には取得した totalCount の値を渡して実行するようにしました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Vue.js]トランジション

<head> <meta charset="utf-8"> <title>vue</title> <link rel="stylesheet" href="css/styles.css"> <!--これはアニメーションのために必要--> <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script> </head> <body> <script src="https://unpkg.com/vue@2.5.17"></script> <div id="app"> <pull-down-menu></pull-down-menu> </div> <script src="js/main.js"></script> </body> cssは好きに書いてね Vue.js var fff = { data: function () { return { isShown: false, name: 'カーソル', items: [ '1-1', '1-2', '1-3', ] }; }, template: ` <div @mouseleave="isShown = false"> <p @mouseover="isShown = true"><a href="#" class="menu">{{ name }}</a></p>     //イベントに対するイベントリスナーは <transition @before-enter="beforeEnter" @enter="enter" @leave="leave" > //isShownの時にリストが出現 <ul v-if="isShown"> <li v-for="item in items" :key="item"> <a href="#" class="menu-item">{{ item }}</a> </li> </ul> </transition> </div> `, methods: { //トランジションの対象となるDOM要素:el //初期状態 beforeEnter: function(el) { el.style.height = '0px'; el.style.opacity = '0'; }, enter: function(el,done) { // 3秒かけて、透明度と高さを変更して出現させる     //はじめ anime({ targets: el, opacity: 1, height: el.scrollHeight + 'px', duration: 10000, complete: done }); }, leave: function(el,done) { //終わり anime({ targets: el, opacity: 0, height: '0px', duration: 10000, complete: done }); } }, }; new Vue({ el: '#app', components: { PullDownMenu: fff } });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

vue.jsの使い方の基礎#5【v-onの使い方】

ドキュメントに沿って手を動かしたことを自分用教科書として書いていきます(イベントハンドラの部分) 公式ドキュメントとやっていることは基本的に同じです。 Vue.js基礎知識に関する記事を随時更新しています一覧はこちら。もしよければ参考にしてください。 v-onの基本的な使い方 v-onディレクティブを使うことで、DOM イベントの購読、イベント発火時の JavaScript の実行が可能になります。 <!-- ボタンを押下するとcounterを1つづ加算していく --> <div> <button @click="counter += 1">+1</button> <p>ボタン押下数 : {{ counter }}</p> </div> --- 以下略 --- メソッドを呼びたいとき 先ほどの例では、1づつ加算していく簡単な処理なのでいいですが、押下したらデータ登録する~などの処理を書いていたら良くないですよね。 v-onでは呼び出したいメソッド名を指定することができます。メソッドを呼ぶときは()をつける必要があります。 <template> <div> <button @click="addCounter()">+1</button> ---クリックされたらaddCounter()メソッドを呼ぶ <p>ボタン押下数 : {{ counter }}</p> </div> </template> <script> export default { data() { return { counter: 0 } }, methods: { addCounter() { this.counter ++ } } } </script> メソッドに引数に渡す引数を指定することもできます <template> <div> <button @click="addCounter(1)">+1</button> <button @click="addCounter(2)">+2</button> <p>ボタン押下数 : {{ counter }}</p> </div> </template> --- 略 --- <script> methods: { addCounter(num) { this.counter += num } } </script> 複数のメソッドを呼びたいとき 以下のようにカンマで区切ることで、複数のメソッドが設定できます。 以下の例では、ボタン押下するとone()とtwo()が実行されます。 <template> <div> <button @click="one(), two()">ボタン</button> </div> </template> --- 以下略 --- イベント修飾子 イベントハンドラ内でのevent.preventDefault()またはevent.stopPropagation()の呼び出しがしたいとき、イベント修飾子(event modifiers)が使用できます。 jsは正直そんなにやっていなかったのでevent.preventDefault()ってなんやねんってなりました。 フォームさんは優秀なので、デフォルトでフォーム内容送信などやってくれるのですが、この動作をキャンセルする目的で使うらしい。 この辺の記事がわかりやすかったです。 JavaScriptのpreventDefault()って難しくない?preventDefault()を使うための前提知識 【JavaScript】event.preventDefault()が何をするのか 修飾子一覧 修飾子は、ドット(.)で表記されます。 修飾子 内容 .stop event.stopPropagation()を呼ぶ .prevent event.preventDefault()を呼ぶ .capture ルート要素から順番にイベント実行 .self event.target が要素自身のときだけハンドラ呼び出し(子要素の場合は呼ばれない) .once 最大1回までハンドラを呼び出す .passive event.preventDefault()を呼び出さない(event.preventDefault()を含んでいたとしても) 書き方 以下公式の引用です。 <!-- クリックイベントの伝搬が止まります --> <a @click.stop="doThis"></a> <!-- submit イベントによってページがリロードされません --> <form @submit.prevent="onSubmit"></form> <!-- イベントリスナーを追加するときにキャプチャモードで使います --> <!-- 言い換えれば、内部要素を対象とするイベントは、その要素によって処理される前にここで処理されます --> <div @click.capture="doThis">...</div> <!-- event.target が要素自身のときだけ、ハンドラが呼び出されます --> <!-- 言い換えると子要素のときは呼び出されません --> <div @click.self="doThat">...</div> <!-- 最大1回、クリックイベントはトリガされます --> <a @click.once="doThis"></a> <!-- `onScroll` が `event.preventDefault()` を含んでいたとしても --> <!-- スクロールイベントのデフォルトの挙動(つまりスクロール)は --> <!-- イベントの完了を待つことなくただちに発生するようになります --> <div @scroll.passive="onScroll">...</div> 補足 以下のような書き方もできます。こちらも公式引用 <!-- 修飾子は繋げることができます --> <a @click.stop.prevent="doThat"></a> <!-- 値を指定せず、修飾子だけ利用することもできます --> <form @submit.prevent></form> また、修飾子を使用するとき、関連するコードが同じ順序で生成されます。 @click.prevent.selfを使用すると全てのクリックイベントを防ぐことはできますが、@click.self.preventは要素自身におけるクリックイベントを防ぐだけです。複数使用する場合は順序もしっかり考えましょう。 以下の注意もありました。 .passive と .prevent を一緒に使わないでください。.prevent は無視され、ブラウザにはおそらく警告が表示されます。.passive はイベントのデフォルトの挙動を妨げないことをブラウザに伝達することを思い出してください。 個人的にこの辺は理解が難しいのでjsをもう少し勉強してから学びなおそう。。。 キー修飾子 いろいろなイベントがある中で、特定のキーのチェック(enterを押下など)が必要な時にキー修飾子をつけることができます。 <!-- `key` が `Enter` のとき、`submit()` が呼ばれます --> <input @keyup.enter="submit" /> キー修飾子一覧 先ほどはkeyupを使用しましたが、キーボードイベントには以下があります。 修飾子 内容 keypress タイプしたとき keydown 押されたとき keyup 押し終わったとき 最も一般的に使用されるキーコードのエイリアスを提供してくれています 修飾子 内容 .enter enterキー .tab tabキー .delete delete と backspace キーの両方 .esc escキー .space スペースキー .up 方向キー上 .down 方向キー下 .left 方向キー左 .right 方向キー右 KeyboardEvent.keyで公開されている任意のキー名は、ケバブケースに変換することで修飾子として直接使用できるそうです。大体のイベントは使用できそうですね。 私はキャメル > スネーク > ケバブの順で好きです(いらない情報) 以下の例では、keyがPageDownのときにonPageDown()が呼ばれます。 <input @keyup.page-down="onPageDown" /> システム修飾子キー 次の修飾子を使用すると、対応するキーが押されたときにのみマウスもしくはキーボードのイベントリスナをトリガできます。 つまり、同じイベントでも異なったイベントとして扱うことができるようになる修飾子です。例えば、 enterを押下した時と、ctrl + enterを押したときで違う処理ができるわけです。 以下公式から引用 <!-- Alt + Enter --> <input @keyup.alt.enter="clear" /> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Do something</div> システム修飾子キー一覧 修飾子 内容 .shift shiftキー .ctrl ctrlキー .alt altキー .meta Mac:コマンドキー(⌘) windows:ウィンドウキー(⊞) .exact 修飾子のパターンを制限 .left マウス左クリック .right マウス右クリック .middle マウス真ん中(スクロールするところ)クリック .exactの書き方。以下公式引用です。 <!-- これは Ctrl に加えて Alt や Shift キーが押されていても発行されます --> <button @click.ctrl="onClick">A</button> <!-- これは Ctrl キーが押され、他のキーが押されてないときだけ発行されます --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- これは システム修飾子が押されてないときだけ発行されます --> <button @click.exact="onClick">A</button> 公式わかりやすいので今回引用多めでした。日本語で見れるのありがたい。 vueの記事ちょこちょこあげてるのでよかったらコメントなどいただけるととてもうれしいです。 最後まで読んでいただきありがとうございます!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Vue.js]グローバルフック関数

<div id="app"> <router-link to="/users">USER</router-link> <router-view></router-view> </div> Vue.js var router = new VueRouter({ routes: [ { path: '/users', component: { template: '<h1>ユーザーページです</h1>' } }, { path: '/top', component: { template: '<h1>トップページです</h1>' } }, ] }) router.beforeEach((to, from, next) => { // ユーザー一覧ページへアクセスした時に / topへリダイレクトする例 if (to.path === '/users') { next('/top') } else { // 引数なしでnextを呼び出すと通常通りの遷移が行われる next() } }) var app = new Vue({ router: router }).$mount('#app') これで、usersではなくてtopに遷移される
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む