20210119のJavaScriptに関する記事は16件です。

JavaScript E6【基本文法】~Part 2~

初めに

Part1に引き続き、JavaScriptの個人的に大事だと思った文法をまとめて行きます。
(前回の記事はこちら->https://qiita.com/m-yamashita613/items/0e28d4c033b9a11cd6d3)

目次

・アロー関数

・コールバック関数

アロー関数

アロー関数を使う事でE6以前よりも簡単に関数の定義が出来るようになった。

const 関数名 = () => {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返す値;
};

仮引き数の数や処理の量によっても省略出来る部分が変わる

// 仮引数の数と定義
const  func = () => {}; //仮引数がないとき
const func = x => { };  //仮引数が1つのみのときは()を省略可能

// 値の返し方
const mulA = x => { return x * x; }; // ブロックの中でreturn
const mulB = x => x * x;            // 1行のみの場合はreturnとブロックを省略できる

コールバック関数

関数はその場で作った匿名関数を関数の引数(値)として渡すことができる。 引数として渡される関数のことをコールバック関数と呼び、コールバック関数を引数として使う関数やメソッドのことを高階関数と呼ぶ。

function 高階関数(コールバック関数) {
    コールバック関数();
}

たとえば、配列のforEachメソッドはコールバック関数を引数として受け取る高階関数である。 forEachメソッドは、配列の各要素に対してコールバック関数を一度ずつ呼び出す。

const array = [1, 2, 3];
const output = (value) => {
    console.log(value);
};
array.forEach(output);

参考記事

https://jsprimer.net/basic/function-declaration/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

アクションパラメータを利用して、スプレッドシートのデータをWeb画面に出力する

はじめに

 以前、こちらの記事に、スプレッドシートのデータをWeb画面に表示する方法を紹介しました。
 そして今回はアクションパラメータを用いて、出力する内容に変化が生じるものを作ってみます。

下準備

 まずWeb画面に表示させる表を作成します。
 今回使用するデータは人気レストラン「サイゼリヤ」のホームページにあるメニューから引用しました。量が多くなるので省略するが、サラダ、スープ、前菜、ピザ、パスタ、ハンバーグ、デザートを何件か登録します。

種類 商品名 値段
サラダ 彩りイタリアンサラダ 350
サラダ チキンとブロッコリーサラダ 350
サラダ ワカメとオクラのサラダ 350
サラダ 小エビのサラダ 350
スープ コーンクリームスープ 150

 本記事ではアクションパラメータで渡される値から種類を絞って出力される処理にする。

デフォルト状態

 次にアクションパラメータが無い状態でどのように表示されるコードを記述します。用意するのはサーバー処理を行うweb.gs(ソースコードではweb.jsと表記)とテンプレートになるindex.html、それに紐づくcommonCss.html(ソースコードではcommonCss.cssと表記)を作成します。

web.js
const ss = SpreadsheetApp.getActiveSpreadsheet();

const Menu = function(kind, name, cost){
  this.kind = kind;
  this.name = name;
  this.cost = cost;
}

const getMenus = () => {
  const sh = ss.getSheetByName("menu");
  const menus = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getValues();
  menus.shift();
  return menus.map(e => new Menu(e[0], e[1], e[2]));
}

function doGet() {
  const html = HtmlService.createTemplateFromFile("index");
  html.menus = getMenus();
  return html.evaluate().setTitle("Getテスト");
}
index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('commonCss').getContent(); ?>
  </head>
  <body>
    <div>
      <? menus ?>
      <p>データ一覧</p>
      <table>
        <tr>
          <th>種類</th>
          <th>商品名</th>
          <th>価格</th>
        </tr>
        <? for(menu of menus){ ?>
          <tr>
            <td class="left"><?= menu.kind ?></td>
            <td class="left"><?= menu.name ?></td>
            <td class="right">\<?= menu.cost ?></td>
          </tr>
        <? } ?>
      </table>
    </div>
  </body>
</html>
commonCss.css
<style>
  table{
    width: 30%;
    border-collapse: collapse;
  }

  th{
    text-align: center;
    border: 1px solid #000;
  }

  td{
    border: 1px solid #000;
  }

  .left{
    text-align: left;
  }

  .right{
    text-align: right;
  }
</style>

 この状態でWebサイトを開いてみます。
 するとスプレッドシートに表記したデータが全て表示されていることがわかります。
1.png

アクションパラメータの実装

 次はアクションパラメータに応じて表示される内容が変化するコードを修正します。
 アクションパラメータはdoGetメソッドが実行された時、つまりWebサイトを開いた時に実行されます。
 なので今回はWeb.gsを以下のようなコードに修正することでアクションパラメータに応じて変化する処理が実装できます。

web.js
const ss = SpreadsheetApp.getActiveSpreadsheet();

const Menu = function(kind, name, cost){
  this.kind = kind;
  this.name = name;
  this.cost = cost;
}

const getMenus = (val) => {
  const sh = ss.getSheetByName("menu");
  const menus = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getValues();
  menus.shift();
  return menus.map(e => new Menu(e[0], e[1], e[2])).filter(e => e.kind === val);
}

function doGet(e) {
  // アクションパラメータから渡される値が半角数値にするため追加
  const category = {
    "1":"サラダ",
    "2":"スープ",
    "3":"前菜",
    "4":"ピザ",
    "5":"パスタ",
    "6":"ハンバーグ",
    "7":"デザート"
  }
  let param = e.parameter;
  // アクションパラメータが無い場合、デフォルト値に変換
  if(Object.keys(param).length === 0){
    param = {
      "category": 1
    };
  }

  const html = HtmlService.createTemplateFromFile("index");
  html.menus = getMenus(category[param.category]);
  return html.evaluate().setTitle("Getテスト");
}

 この状態でデプロイまたは「デプロイをテスト」でWeb画面を開きます。すると、Webサイト上ではデータが絞られた状態で表示されているのかと思います。
2.png

 次にURLに以下の文字列を書き加えてブラウザを実行してみると表示されている内容が変化されていることがわかります。

デプロイ時に発行されるURL?category=2

 categoryに適応させている値を1~7の間で書き換えると表示される内容が変化したのが確認できたかと思います。

Formの追加

 前項では直接URLを変更することで画面表示を切り替えましたが、こちらは正当な方法とはいえません。というのもアクションパラメータを実践で運用する際には複数個有り、中にはハッシュ関数を用いて本来の値が外部にわからないように加工するからである。
 なのでここではForm要素を追加することでURLを直接弄ることなく、アクションパラメータを付与する方式を取りたいと思います。

web.js
const ss = SpreadsheetApp.getActiveSpreadsheet();

const Menu = function(kind, name, cost){
  this.kind = kind;
  this.name = name;
  this.cost = cost;
}

const getMenus = val => {
  const sh = ss.getSheetByName("menu");
  const menus = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getValues();
  menus.shift();
  return menus.map(e => new Menu(e[0], e[1], e[2])).filter(e => e.kind === val);
}

// URLを動的に取得
const getMyUrl = () =>{
  return ScriptApp.getService().getUrl();
}

function doGet(e) {
  console.log(e);
  // アクションパラメータから渡される値が半角数値にするため追加
  const category = {
    "1":"サラダ",
    "2":"スープ",
    "3":"前菜",
    "4":"ピザ",
    "5":"パスタ",
    "6":"ハンバーグ",
    "7":"デザート"
  }
  let param = e.parameter;
  // アクションパラメータが無い場合、デフォルト値に変換
  if(Object.keys(param).length === 0){
    param = {
      "category": 1
    };
  }

  const html = HtmlService.createTemplateFromFile("index");
  html.menus = getMenus(category[param.category]);
  return html.evaluate().setTitle("Getテスト");
}
index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <?!= HtmlService.createHtmlOutputFromFile('commonCss').getContent(); ?>
  </head>
  <body>
    <div>
      <form method="get" action="<?= getMyUrl() ?>">
        <select name="category">
          <option value="1">サラダ</option>
          <option value="2">スープ</option>
          <option value="3">前菜</option>
          <option value="4">ピザ</option>
          <option value="5">パスタ</option>
          <option value="6">ハンバーグ</option>
          <option value="7">デザート</option>
        </select>
        <input type="submit" value="変更">
      </form>
      <? menus ?>
      <p>データ一覧</p>
      <table>
        <tr>
          <th>種類</th>
          <th>商品名</th>
          <th>価格</th>
        </tr>
        <? for(menu of menus){ ?>
          <tr>
            <td class="left"><?= menu.kind ?></td>
            <td class="left"><?= menu.name ?></td>
            <td class="right">\<?= menu.cost ?></td>
          </tr>
        <? } ?>
      </table>
    </div>
  </body>
</html>

 コードを書き換えたら、前項と同じようにWeb画面を開いたら、以下のような画面が表示されているのかと思います。
 セレクトボックスの中身を変換し、ボタンをクリックすると表示される画面が切り替わります。
3.png

最後に

 今回、アクションパラメータを変化させることで出力させる内容を変化させる方法をざっくりと紹介しました。
 アクションパラメータを用いる長所はURLの内容だけで動的挙動を持たせることができることにあります。それにより軽量かつ再現性の高いWebアプリが作成できる。
 この記事では種類別で置き換えたが都道府県別や職業別等、色々と応用できる範囲は広いので、参考になれば幸いです。またフリーアカウントではできないが、Google_Workspaceの法人向けアカウントであれば同じドメインアカウント以外アクセスできない制御ができる。それを利用しアクションパラメータに直接ユーザーアカウントを埋め込むのも、社内サービスに絞れば選択肢に加えることができる。

 もし理解不足な点がみられたら、ご指摘頂けると幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラムを少しかじった私がバックエンドエンジニアとして働くためにECサイトを作り始めてみた その⑥

対象者

・バックエンドエンジニアを志す人
・web開発初学者
・ECサイトを作成しようと思っている人
・初学者の勉強仮定を見たい方

はじめに

こんにちは!
この投稿はその⑤の続きです。

今週は別プロダクトの発表が週末にあります!
前置きは短めに!目次です!

目次

1.今回の作業報告
2.反省点
3.次回のステップ

1.今回の作業報告

画像を使ってざっくり報告

◯商品の表示機能
商品一覧(全部)と男性向け商品と女性向け商品を一覧で表示させる仕様で実装しています。
スクリーンショット 2021-01-19 20.46.04.png

男性向け商品一覧
スクリーンショット 2021-01-19 20.46.20.png

女性向け商品一覧
スクリーンショット 2021-01-19 20.46.53.png

DBに男性向けと女性向けの識別するカラムをテーブルに入れて判定させました。

スクリーンショット 2021-01-19 22.41.10.png

◯注文確認機能
カートの商品を送る情報を入力
スクリーンショット 2021-01-19 20.48.13.png

ご注文確認画面へ。
カートの情報と送信先が表示されるようにしています。
スクリーンショット 2021-01-19 20.48.28.png

その他、ユーザー毎のログイン機能など他にも実装しましたが割愛します。

2.反省点
実装の仕様がちゃんと決まっていないために大幅に時間が取られてしまいました。
数量が増えたときどうするかなどの仕様はあらかじめ決める必要がありそうです。
テーブル結合などもうちょっと踏み込んで実装できれば色々表現できる幅が広がりそうです。

3.次のステップ
カート内の商品計算とかその他もろもろを引き続き実装していきます。

簡単ですが今回は以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript EC6【基本文法】~Part1~

初めに

最近、Reactを始めたのですが、そもそもJavaScriptのJaの字も分からなかったので
基本的すぎるかもしれませんが、アウトプットの練習をかねて、勉強した内容を分けて投稿しようと思います。

目次

・変数

・HTMLファイル内でJavaScriptファイルを読み込む

・データ型(プリミティブ型)

変数

const

再定義と再代入ができない変数

const x = 1;
console.log(x); //-> 1
x = 2;
console.log(x); //-> 1
const x = 1; //-> Error

let

再定義ができない変数

let x = 1;
console.log(x) //-> 1
x = 2;
console.log(x) //-> 2
let x = 1; //-> Error

letconstの厳密性

{}内でletconstを定義した場合、{}内でのみ参照できる。

const x = 1;
if (x === 1) {
    let y = 2;
    const z = 3;
    console.log(y); // -> 2
    console.log(z); // -> 3
}
console.log(y); // -> undefined
console.log(z); // -> undefined

var

再定義も再代入も出来るが、それ故に意図しない再定義や再代入を引き起こすため
基本的に使わない。

HTMLファイル内でJavaScriptファイルを読み込む

HTMLファイル内でJSファイルよ読み込みたい場合は以下の通りに書く。
今回は同じディレクトリにあるindex.jsというファイルを読み込む事にする。

<html>
<head>
    <meta charset="UTF-8">
    <title>Example</title>
    <script src="./index.js"></script>
</head>
<body></body>
</html>

データ型(プリミティブ型)

プリミティブ型(基本型)の値は一度作成すると値自体を変更する事ができないイミュータブル特性を持つ。

型名
number 数値
string 文字列
boolean 真偽値
underfined 値が定義されていない
null 値が存在しない
symbol 一意で不変な値のデータ型
console.log(typeof false);// => "boolean"
console.log(typeof 91110); // => "number"
console.log(typeof "JS"); // => "string"
console.log(typeof Symbol("シンボル"));// => "symbol"
console.log(typeof undefined); // => "undefined"
console.log(typeof null); // => "object"

nullの型名がobjectになるのは歴史的経緯のあるバグらしい。
(詳細はこちらの記事から->https://2ality.com/2013/10/typeof-null.html)

参考記事

https://qiita.com/Fendo181/items/cca476da99e8f09b6b97
https://jsprimer.net/basic/data-type/#fn_1
https://qiita.com/soarflat/items/b251caf9cb59b72beb9b

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CORSエラー無視したい

jqueryでincludeしようとしたら怒られた

開発中のアプリのモックを作っている時にjqueryつかってincludeしようとしたらこんなエラーを吐いてしまい、上手いことできない。

Access to XMLHttpRequest at 'file:///C:/"ファイルへのパス"/include.html' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.

このエラー、どうやらCORSというものに関係したエラーらしい。
ちなみにフロントの人たちは結構な頻度で遭遇するのだそう。

初めて知った。。

解決策

解決策としては、ローカルサーバーを立ち上げてそこで処理してもらうとか、ブラウザを変えるというのが常套手段らしいのだけど、どうにも面倒くさいなーと思いつつ解決策を探していたら、ChromeにCORSエラーを無視させる方法を見つけた。
結論、Chrome起動時のオプションに以下を入れてやると出来る。

--disable-web-security --user-data-dir="C:\Chrome dev session"

ショートカットを作ってプロパティを開く

ショートカット.png
Chromeへのショートカットを作り、アイコンを右クリックしてプロパティを開く。

リンク先の末尾にオプションを突っ込む

プロパティ.png
リンク先の入力ボックス内リンク末尾に上記の--disable-web-security --user-data-dir="C:\Chrome dev session"を追加してOK

あとはこのショートカットでChromeを起動して、見たいhtmlファイルをドラッグ&ドロップしてやればCORSエラーが沈黙しているのを確認できる。

決しておすすめしない

ここまで紹介してなんですが、つまりは敢えてセキュリティレベルを下げる方法なわけで決しておすすめはしない
今回、私は単なるモック作りのため一切のネットワークに繋がっていない状態で行ったが、例えば開発現場で多用して何か問題が起きても私は一切責任を負えない。

結局のところサーバー立てるのが一番無難だと思います。
そもそもjqueryだけでincludeするなんてことがほぼ無いだろうし。

ただ、前の開発で誰かが普通に作れてたんだよなぁ。今度聞いてみよう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ChromeでCORSエラーを無視したい

jqueryでincludeしようとしたら怒られた

開発中のアプリのモックを作っている時にjqueryのload()でincludeしようとしたらこんなエラーを吐いてしまい、上手いことできない。

Access to XMLHttpRequest at 'file:///C:/"ファイルへのパス"/include.html' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.

このエラー、どうやらCORSというものに関係したエラーらしい。
ちなみにフロントの人たちは結構な頻度で遭遇するのだそう。

初めて知った。。

解決策

解決策としては、ローカルサーバーを立ち上げてそこで処理してもらうとか、ブラウザを変えるというのが常套手段らしいのだけど、どうにも面倒くさいなーと思いつつ解決策を探していたら、ChromeにCORSエラーを無視させる方法を見つけた。
結論、Chrome起動時のオプションに以下を入れてやると出来る。

--disable-web-security --user-data-dir="C:\Chrome dev session"

ショートカットを作ってプロパティを開く

ショートカット.png
Chromeへのショートカットを作り、アイコンを右クリックしてプロパティを開く。

リンク先の末尾にオプションを突っ込む

プロパティ.png
リンク先の入力ボックス内リンク末尾に上記の--disable-web-security --user-data-dir="C:\Chrome dev session"を追加してOK

あとはこのショートカットでChromeを起動して、見たいhtmlファイルをドラッグ&ドロップしてやればCORSエラーが沈黙しているのを確認できる。

決しておすすめしない

ここまで紹介してなんですが、つまりは敢えてセキュリティレベルを下げる方法なわけで決しておすすめはしない
今回、私は単なるモック作りのため一切のネットワークに繋がっていない状態で行ったが、例えば開発現場で多用して何か問題が起きても私は一切責任を負えない。

結局のところサーバー立てるのが一番無難だと思います。
そもそもjqueryだけでincludeするなんてことがほぼ無いだろうし。

ただ、前の開発で誰かが普通に作れてたんだよなぁ。今度聞いてみよう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

要素間でフォーカスを移したときblurイベントとfocusイベントは同期的に実行される

ChromeとFirefoxの最新版で確認済。仕様通りの挙動なのだろうか。

<input name="input1" />
<input name="input2" />
document.querySelectorAll('input').forEach((input) => {
  input.addEventListener('focus', (e) => {
    console.log(`Focus: ${e.target.name}`);
    setTimeout(() => {
      console.log(`Focus async: ${e.target.name}`);
    }, 0);
  });
  input.addEventListener('blur', (e) => {
    console.log(`Blur: ${e.target.name}`);
    setTimeout(() => {
      console.log(`Blur async: ${e.target.name}`);
    }, 0);
  })
})

input1からinput2にフォーカスを移したときのコンソール出力は

Blur: input1
Focus: input2
Blur async: input1
Focus async: input2

となっていた。

サンプル

https://plnkr.co/edit/315T56FzA9MzQArg?open=lib%2Fscript.js

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】slotタグを使ってhtmlタグを親コンポーネントで定義し、子コンポーネントに渡す【slot】

参考

Udemy参考動画:https://www.udemy.com/course/vue-js-complete-guide/
講師 : よしぴー(Yoshipi)さん

Vue.jsslotタグを使ってhtmlタグを親コンポーネントで定義する方法をご紹介します。

通常

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <p>{{ title }}</p>
  </div>
</template>


<script>
export default {
  data() {
    return {
      title,
    };
  }
};
</script>

親コンポーネント App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent :title="タイトル"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from "./components/ChildComponent.vue";

export default {
  components: {
    ChildComponent,
  },  
};
</script>

結果

タイトル

プロパティを渡し、タグ子コンポーネントで定義する。

スロット

  • タグを親コンポーネント定義できる
  • 対応 : ver2.6.0~

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot></slot>
  </div>
</template>

親コンポーネント : App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent>
    <template>
          <p>タイトル</p>
      <template>
    </ChildComponent>
  </div>
</template>

結果

タイトル

コンポーネント内のtemplateタグと子コンポーネントのslotタグが対応

デフォルト

slotの数だけtemplateが生成されるため、slotタグを複数置くと同じ内容が連続して表示される

デフォルトの仕様ということでオールバックコンテンツと呼ばれる。

例えば、
子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot></slot>
    <slot></slot>
    <slot></slot>
    <slot></slot>
  </div>
</template>

結果

タイトル
タイトル
タイトル
タイトル

スコープ

  • インスタンス内(親コンポーネント内)
  • CSSは例外 : 親コンポーネントのスタイルが優先的に働く

名前付きslot

  • slot : name属性(子コンポーネント)
  • template : v-slot(親コンポーネント)

nameの値とv-slotの引数が対応
注意:nameは、v-slotは引数

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot name="title"></slot>
    <slot name="name"></slot>
  </div>
</template>

親コンポーネント : App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent>
    <template v-slot:title>
          <p>タイトル</p>
      <template>
      <template v-slot:name>
          <p>太郎</p>
      <template>
    </ChildComponent>
  </div>
</template>

結果

タイトル
太郎
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue.js】slotタグを使ってhtmlタグを親コンポーネントで定義【slot】

参考

Udemy参考動画:https://www.udemy.com/course/vue-js-complete-guide/
講師 : よしぴー(Yoshipi)さん

Vue.jsslotタグを使ってhtmlタグを親コンポーネントで定義する方法をご紹介します。

通常

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <p>{{ title }}</p>
  </div>
</template>


<script>
export default {
  data() {
    return {
      title,
    };
  }
};
</script>

親コンポーネント App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent :title="タイトル"></ChildComponent>
  </div>
</template>

<script>
import ChildComponent from "./components/ChildComponent.vue";

export default {
  components: {
    ChildComponent,
  },  
};
</script>

結果

タイトル

プロパティを渡し、タグ子コンポーネントで定義する。

スロット

  • タグを親コンポーネント定義できる
  • 対応 : ver2.6.0~

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot></slot>
  </div>
</template>

親コンポーネント : App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent>
    <template>
          <p>タイトル</p>
      <template>
    </ChildComponent>
  </div>
</template>

結果

タイトル

コンポーネント内のtemplateタグと子コンポーネントのslotタグが対応

デフォルト

slotの数だけtemplateが生成されるため、slotタグを複数置くと同じ内容が連続して表示される

デフォルトの仕様ということでオールバックコンテンツと呼ばれる。

例えば、
子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot></slot>
    <slot></slot>
    <slot></slot>
    <slot></slot>
  </div>
</template>

結果

タイトル
タイトル
タイトル
タイトル

スコープ

  • インスタンス内(親コンポーネント内)
  • CSSは例外 : 親コンポーネントのスタイルが優先的に働く

名前付きslot

  • slot : name属性(子コンポーネント)
  • template : v-slot(親コンポーネント)

nameの値とv-slotの引数が対応
注意:nameは、v-slotは引数

子コンポーネント : ChildComponent

//ChildComponent

<template>
  <div>
    <slot name="title"></slot>
    <slot name="name"></slot>
  </div>
</template>

親コンポーネント : App.Vue

//App.Vue

<template>
  <div>
    <ChildComponent>
    <template v-slot:title>
          <p>タイトル</p>
      <template>
      <template v-slot:name>
          <p>太郎</p>
      <template>
    </ChildComponent>
  </div>
</template>

結果

タイトル
太郎
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

サムネ付きで削除可能なファイルフォームの状態確認シート

いつも混乱するのでまとめておこうと思います。

前提

image.png

<input type=file name=logo_image /> <!-- (1) -->
<figure id=thumb_logo_image><img/></figure> <!-- (2) -->
<input type=hidden name=remove_logo_image value=on /> <!-- (3) -->
<button id=btn_remove_logo_img /> <!-- (4)-->
  • こんな要素があるとします
  • 保存済みのファイルがある場合は(2)にサムネが表示されるものとします
  • ファイルを選択した直後もJSで(2)にサムネをセットするものとします
    • ※サーバーにはまだ送っていない状態
  • remove_属性名 に値をセットして送れば保存済みのファイルが削除ができる実装だとします
    • 削除フィールドに値があったまま新しいファイルを送信してもきちんと新しいファイルに交換される実装になっているものとします
  • (4)の削除用のボタンが押されると、(2)サムネ、(3)削除用フィールド、(4)削除用ボタンがHTMLから消えると想定します

状態の洗い出し

  • 保存済みのファイルがあるかないか
  • 新しいファイルが選択されているかいないか
  • ファイル選択ダイアログを出したあとに「キャンセル」ボタンで戻ったかどうか
  • 削除用のボタンが押されたか押されていないか
  • 削除用のボタンが押された後にまたファイル選択をしたかどうか
  • 保存済みのファイルがある状態で新しいファイルを選択したが、新しいファイルはキャンセルした場合

状態変数の洗い出し

  • Object savedValue
    • 保存済みのファイル
  • String savedValueUrl
    • 保存済みファイルのサムネ用URL
  • Object inputValue
    • 新たに選択されたファイル
    • ※(1)ファイルフィールド のvalue値
    • ※ファイルフィールドの仕様により、JSからは再設定不可でリセット(nullの代入)のみ可能
  • String inputValueUrl
    • 新たに選択されたファイルのサムネ用URL
  • Bool thumbVisible
    • (2)サムネ を表示するかどうか
  • String thumbSrc
    • (2)サムネタグにセットする値
    • savedValueUrl or inputValueUrl
  • Bool readyToRemove
    • (3)保存済みファイルを削除するかどうか
  • Bool removeBtnVisible
    • (4)削除用ボタンを表示するかどうか

状態確認シート

  • この行数分リロードと操作を繰り返せば動作確認完了な想定
  • nullfalse のセルは省略。見にくくなったので
  • (1).. inputValue
  • (2).. thumbSrcthumbVisible
  • (3).. readyToRemove
  • (4).. removeBtnVisible

保存済みのファイルがない場合

操作\ (1)  (2) (3) (4)
初期状態
ファイルが選択された Object inputValueUrl true
ファイル選択後に
削除用ボタンが押された
ファイル選択後に
再度ファイル選択が開かれたが
キャンセルが押された

保存済みのファイルがある場合

操作\ (1) (2) (3) (4)
初期状態 savedValueUrl true
削除用ボタンが押された true
ファイルが選択された Object inputValueUrl true
ファイル選択が開かれたが
キャンセルが押された
savedValueUrl true
削除用ボタンが押されてから
ファイルが選択された
Object inputValueUrl true
ファイル選択されてから
削除用ボタンが押された
savedValueUrl true
ファイル選択されてから
削除ボタンが押されて
再度削除ボタンが押された
true
ファイル選択されてから
削除ボタンが押されて
再度ファイル選択が開かれたが
キャンセルが押された
savedValueUrl true

おわり

あーややこしい

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JSの基本構文と基礎の勉強(アウトプット用)(1)

はじめに

JavaScriptで利用される基本関数的な関数などを自分なりにまとめてみた。

目次

  1. JavaScriptとは
  2. いろんな関数
  3. 参考文献

JavaScript

JavaScriptでできること

・HTMLとCSSだけでできないことをすること。
・静止した画面をその場で書き換えたりすることができる。
・タグに囲まれたテキスト(コンテンツ)を書き換えることができる
・要素</>を追加・削除・変更することができる。
・CSSの値を変更することができる。
・ダイアログで別画面を表示することができる。

ECMAScript(ES6) 2015

2015年にJavaScriptの仕様が大きくなり改定され、エクマスクリプト2015と呼ばれるようになりました。
varは、非推奨でconstとletを利用するように言われました。
letは、再宣言ができない

sample.js
 let test = 1;
 let test = 2;//×
 test = 2;//〇

constは、再宣言ができない

sample.js
 const test = 1;
 const test = 2;//×
 const = 2;//×

詳細は、こちらES2015(ES6) 入門
上記に詳細な内容が書かれています。

JavaScriptの動作の仕組み

イベント発生(処理発生)→加工→アウトプット(出力)の順で処理が流れてアウトプットされます。

いろんな関数やその他

console.log();
・・・値の確認ができる。
※undefinedは未定義。
jsでの実行は、「〇〇は△△を××しなさい」で
〇〇→オブジェクト,△△→パラメータ,××→メソッド
console→オブジェクト
log()→メソッド

console.dir();
・・・配列や連想配列や関数の中身をより詳細に確認できる。

console.error();
・・・エラー表記する

スクリプトタブ

sample.html
<script>
'use strict';
let test = 1;
</script>

windowアラート
ダイアログボックスを表示させる。
windowオブジェクトで用意されているalertメソッドのことです。

sample.js
window.alert("test");

documentとgetElementByIdとtextContent
documentのIdを取得するメソッドにテキストを挿入する。

sample.js
'use strict';
document.getElementById('choice').textContent = new Date();

参考文献

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【React】いま一度、importとexportについて復習してみる

export

最初にexportから見ていきましょう。

名前付きexport

一つのファイル(モジュール)から複数の関数をexportできます。では、実際のコードを見ていきます。

export const Hoge = () => {
  return(
    <p>hoge</p>
  )
}
export const Aha = () => {
  return(
    <p>aha</p>
  )
}

こんな感じでexportできます。上記のように1ファイルから複数の関数コンポーネントを出力できます。

名前なしexport

一つのファイル(モジュール)から一つのコンポーネントしかexportできません。では、実際のコードを見ていきます。

const Hoge = () => {
  return(
    <p>hoge</p>
  )
}
export default Hoge

上記のように一つのコンポーネントしかexportできません。

Import

名前付きexportをImport

名前付きでexportされたモジュールをimportします。

import { Hoge, Aha } from './HogeAha'

1ファイル(モジュール)から複数のコンポーネントをimportするにはこの方法ですね。ライブラリからコンポーネント等を引っ張ってくる時によく使われますね。

名前なしexportをImport

  • 名前なしでexportされたコンポーネントをimportする。
  • モジュール全体をimportする。
import Hoge from './hoge'

以上!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript オブジェクト内の更新するキーを動的に変える

手順

[]を使えば引数の値をキーとして使える

const onChangeSelection = (e, key) => {
    dispatch(
      setConditionsActions({
        ...conditions,
        [key]: e.target.value,
      })
    );
  };
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Reactを触ってみる(その1)

動機: フロントエンド、ガッツリやってみたい!

  • 普段はサーバーサイドエンジニアとして、主にPHP/Javaで開発することが多いのですが、JavaScriptでゴリゴリにフロント動かしてみたい!という欲求が昔からありました。かつ、どうせだったら「altJS」(alternative JavaScript)× 「JSフレームワーク」を使ってみたい!という思いがあり、今回Javascriptをガッツリ触ってみることにしました。

フレームワーク何にしようか問題

  • さて、JavaScriptをガッツリやっていくのはいいとして、どういう組み合わせを選ぶか?日本のGoogleトレンドを見てみると、以下のような結果に。

<順位>
React > Vue > Angular

【参考】
React,Vue,Angularのトレンド比較(日本)

ふむふむ。結構ReactとVueが拮抗してますね。もっとよく調べてみると、世界の有名サービスは軒並みReactで作られている、かつグローバルではReactのシェアのほうが高い。(Vue.jsもコミュニティがかなり頑張っているので、結構いい勝負ではあるようです)悩んだんですが、Reactを以前から触ってみたかったので、今回の学習では「React」を学ぶことにしました。

何はともあれ触ってみる: 開発環境構築

  • 開発環境PC: Windows10 Home

Node.jsのインストール

まずPCに「Node.js」をインストール。そもそも、React使うのに何でNode.jsインストールする必要があるんだっけ?今一度整理。

  • Node.js
    • JavaScriptをRubyやPythonと同じようにPCのターミナル上で動かすことができるようにするためのソフトウェア。JavaScriptをサーバーサイド言語として使えるようになる。
    • npm: Node.jsの為に作られたパッケージ管理システム。Node Package Managerの略。パッケージのインストール・アップデート・アンインストールだけでなく、リポジトリ機能も完備。
    • フロントエンド用のパッケージを提供するのにも用いられるようになる。Javascriptのパッケージ管理はnpmを使う。

以下のリンクの記事を参考にWindowsマシンにNode.jsを入れていきます。

【参考】
Windows 10へNode.jsをインストールする

Visual Studio Codeのインストール
React開発元のデフォルト開発環境でもあるらしい「VS Code」をインストール。

プロジェクトの作成 ~ Hello World!まで

  • Create React App(CRA)でプロジェクト(スケルトン)を作成する。適当なディレクトリで以下のコマンドを実行。
npx create-react-app hello-world --template typescript

今回はaltJSに「TypeScript」を使います。

  • Create React App
    • react: React本体パッケージ
    • react-dom: DOMを抽象化してReactから操作できるようにするレンダラーのパッケージ
    • react-scripts: 50個以上のパッケージ群を隠蔽してくれる。

コマンド実行が終わると、最後にメッセージが表示されるので、言われた通りに実行する。

$cd hello-world
$npm start
  • コマンドを実行すると、ローカルにHTTPサーバーが3000番ポートで立ち上がってアプリが起動されてる!ブラウザにデフォルト画面が表示されました。

http://localhost:3000/

  • Hello World!と表示させる為、App.tsxを編集
import 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>
          Hello World!
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}
export default App;
  • Reactで作られるアプリケーションは全て「コンポーネント(Component)」の組み合わせで構成される
  • Reactではコンポーネントの実装は関数またはクラスで定義する

まとめ

  • 第一回はいったんこれにて満足w 今後、参考にしている本を読み進めて、さらに理解を深めていきます。

参考
『りあクト! TypeScript で始めるつらくない React 開発 第3.1版』
https://booth.pm/ja/items/2368045

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Collection Groupでサブコレクションをまとめてクエリ[Firestore]

Collection Groupを使うと、異なるドキュメント配下の同名のサブコレクションをまとめてクエリできます。

たとえば、

preference collection:県
 /document(京都、大阪、名古屋、岡山)
  /specialty collection:名物
   /document([name:八ツ橋, type:sweet] [name: たこ焼き, type: meal] [name:ひつまぶし, type: meal] [name:きびだんご, type: sweet])

という階層があったときに、

specialty collectionは別々のpreferenceドキュメントに属していますが、specialtyのくくりでまとめてクエリできます。

手順

1,セキュリティルールを追加

グループコレクションでクエリを行うには、途中までのパスがワイルドカードになったruleをFirestoreに追加します。

match /{path=**}/specialty/{document} {
  allow read: if true;
}

2,グループコレクションでクエリしてみる

Swiftの例は以下。他の言語は公式ドキュメント参照。

let db = Firestore.firestore()

db.collectionGroup("specialty").whereField("type", isEqualTo: "sweet").getDocuments { (snapshot, error) in
    // ...
}

このクエリは失敗します。
なぜなら、Collection Group queryをサポートする Index をFirestore に追加する必要があるからです。

3,Index を追加

上記クエリを実行すると、コンソールログにクエリに必要なインデックスを追加するためのリンクが表示されます。
ブラウザからそのリンクを開くと、必要なインデックスが自動で追加されます。

Firestoreコンソールから手動で追加することもできます。

3までの手順を実行して、改めて2,のクエリを実行すると、specialtyコレクションのスイーツタイプをもつドキュメントのスナップショットが得られます。

?


フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

Twitter
Medium

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

typescriptの型付け(関数)

戻り値のある関数

index.ts
function add(num1: number, num2: number): number{
    return num1 + num2;
}

戻り値のない関数

index.ts
function sayHell(): void{
    console.log('sayHello')
}

コールバック関数

index.ts
function doubleAndHandle(num: number, callback: (num: number) => number): void {
    const doubleNum = callback(num * 2)
    console.log(num * 2);
}

doubleAndHandle(21, doubleNum => {
    return doubleNum;
})

その他関数

index.ts
const anotherAdd: (n1: number, n2: number) => number = add;
const theOtherAdd: (n1: number, n2: number) => number = function (num1: number, num2: number): number{
    return num1 + num2;
};//無名関数

const doubleNumber = (number: number):number => number * 2;//アロー関数
const doubleNumber2: (num: number) => number = number => number * 2;//アロー関数

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む