JavaScript framework

提供:senooken JP Wiki
2024年10月29日 (火) 11:54時点におけるSenooken (トーク | 投稿記録)による版 (JavaScriptからFrameworkを分離。)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)

jQuery

jQuery API Documentation

レガシー

jQueryがもういらなくなってきたという意見がある。

  • Webブラウザー間の違いがなくなってきた。
  • 標準のJavaScriptでできることが増えた。

上記2点が大きい。jQueryじゃないとできないことが大幅に減った。標準APIでこなしたほうがいいだろう。

ajaxのasync/awaitでの書換

$.ajax(jQuery.ajax)の非同期処理をasync awaitの入れ子なし同期処理で記述する #JavaScript - Qiita

ajaxを使っている関数の定義にasync。ajax関数の使用箇所にawait。これでうまくいく。

**
 * フルーツ名を取得する
 *
 * @param {string} fruitId
 */
async function getFruitName(fruitId) {
  const fruitRequest = {id: fruitId}
  const fruitResult = await ajaxGetFruit(fruitRequest);
  return fruitResult.name;
}

/**
 * フルーツのajax[GET]を実施する
 * 
 * @param {object} request
 * @returns
 */
function ajaxGetFruit(request) {
  return $.ajax({
      url: '/fruit/name',
      type: "GET",
      async: true,
      contentType: "application/json",
      data: JSON.stringify(request),
      dataType: "json",
    }).then(
      function (result) {
        // 正常終了
        resolve(result);
      },
      function () {
        // エラー
        reject();
      }
    )
}

jQuery.ajax() | jQuery API Documentation」にあるように、jquery 1.5から$.ajaxの返却値はPromiseの派生クラス。そのまま返却させて良い。


Nuxt.js

終端スラッシュありへのリダイレクト

Nuxt.jsにおける末尾スラッシュを統一する方法 #amplify - Qiita

// middleware/trailingSlash.js
/**
 * 終端スラッシュありのURLにリダイレクトする。
 * @param {Object} Nuxt.jsのContextオブジェクト。
 */
export default ({ route, redirect }) => {
  if (route.path.endsWith('/')) {
    return
  }
  let to = route.path + '/'
  if (route.query) {
    to +=
      '?' +
      Object.entries(route.query)
        .map((e) => e.join('='))
        .join('&')
  }
  to += route.hash
  redirect(301, to)
}

//へのアクセスエラー

  • https://github.com/vuejs/vue-router/issues/2593
  • https://github.com/nuxt/nuxt.js/issues/2020

けっきょく、serverMiddlewareは結合環境で機能せず、middlewareもルートの変化後に発動するため対応できなかった。

そのため、プラグインにして、router.beforeEachで変化前に書き換え処理を入れた。

// plugins/redirect.js
export default ({ app }) => {
  app.router.beforeEach((to, from, next) => {
    // 二重スラッシュを一重スラッシュに変換する。
    // 素直にnextでリダイレクトすると、一度もともとのtoのURLでDOMの更新に進んでエラーが出る。
    // そのためnext(false)でtoは使わずにpushで履歴を差し替える。
    if (/\/\/+/.test(to.path)) {
      next(false)
      app.router.push(to.path.replace(/\/\/+/g, '/'))
    } else {
      next()
    }
  })
}

Vue.js

Naming

【Vue】単一ファイルコンポーネントの命名規則まとめ【ファイル名から記法まで】 #Vue.js - Qiita

radioのbool

vuejs2 - Vue: Binding radio to boolean - Stack Overflow

v-bind:か:で型を合わせて代入する。stringにするとうまく認識されない。

IMEの入力制限

IME以外はformatterで処理して、IMEだけcompositionendで処理すればいい。

<template>
  <div role="group" class="bv-no-focus-ring">
          <div
            class="form-group-text"
            :class="{ active: '' + value, 'is-invalid': error }"
          >
            <b-form-input
              :id="'input-text-' + _uid"
              type="text"
              :formatter="formatter"
              :value="value"
              @input="$emit('input', $event)"
              @compositionend="$emit('input', normalize($event.target.value))"
              @paste="$emit('input', paste($event))"
            />
            <label :for="'input-text-' + _uid">{{
              /[._]/.test(label) ? $t(label) : label
            }}</label>
    </div>
    <div :id="'input-live-feedback-' + _uid" class="invalid-feedback">
            {{ $t(error) }}
    </div>
  </div>
</template>
<script>
      export default {
        props: {
          value: { type: String, default: '', required: true },
    label: { type: String, default: '', required: true },
    // ファームウェアとスケジュールにエラーのないフォームがある。
    error: { type: String, default: '' },
  },
  methods: {
    /**
     * 入力内容の正規化を行う。
     * @param {string} input - 入力文字列。
     * @return {string} 正規化後文字列。
     */
    normalize(input) {
      // ASCII文字列以外は削除する。
      return input.replace(/[^ -~]/g, '')
    },
    /**
     * 入力フォームを整形する。
     * @param {string} value - 入力文字列。
     * @param {Object} event - イベントオブジェクト。
     * @return {string} IME変換時は正規化後の文字列。それ以外は、compositionendで行うため、未変換文字列。
     * IME変換時はcompositionendで入力を正規化し、それ以外はformatterで正規化する。
     */
    formatter(value, event) {
      return event.isComposing ? value : this.normalize(value)
    },
    /**
     * クリップボードからの貼付時の文字列を処理する。
     * @param {Object} event - イベントオブジェクト。
     * @return {string} 処理後の文字列。
     * @todo 入力の途中にカーソルを移動させて貼り付けた場合、貼り付け後、カーソルが末尾に移動してしまう。
     * event.preventDefault()が原因と思われる。しかし、これの解決が難しい。
     * event.target.selectionStartにカーソル位置を指定できるのだが、preventDefaultすると一瞬カーソルが末尾に飛ぶ。
     */
    paste(event) {
      event.preventDefault()
      const cb = (event.clipboardData || window.clipboardData).getData('text')
      const start = event.target.selectionStart
      return this.normalize(
        this.value.slice(0, start) + cb + this.value.slice(start)
      )
    },
  },
}
</script>
<template>
  <div role="group" class="bv-no-focus-ring mb-3">
          <div
            class="form-group-text"
            :class="{ active: '' + value, 'is-invalid': error }"
          >
            <b-form-input
              :id="'input-number-' + _uid"
              class="form-control"
              type="tel"
              autocomplete="off"
              maxlength="10"
              :formatter="formatter"
              :value="value"
              @input="$emit('input', $event)"
              @compositionend="$emit('input', normalize($event.target.value))"
            />
            <label :for="'input-number-' + _uid">{{ $t(label) }}</label>
    </div>
    <div :id="'input-live-feedback-' + _uid" class="invalid-feedback">
            {{ $t(error) }}
    </div>
  </div>
</template>
<script>
      export default {
        props: {
          value: { type: [String, Number], default: '', required: true },
    error: { type: String, default: '', required: true },
    label: { type: String, default: '', required: true },
  },
  methods: {
    /**
     * 入力内容の正規化を行う。
     * @param {string} value - 入力文字列。
     * @return {string} result - 正規化後文字列。
     * @warn v-model.numberの修飾子を指定するとcompositionendでの変更が反映されない。
     * そのため、.numberを使わず、この関数で型変換する。
     */
    normalize(value) {
      const result = parseFloat(value.replace(/[^0-9]/g, ''))
      return isNaN(result) ? '' : result
    },
    /**
     * 入力フォームを整形する。
     * @param {string} value - 入力文字列。
     * @param {Object} event - イベントオブジェクト。
     * @return {string} IME変換時は正規化後の文字列。それ以外は、compositionendで行うため、未変換文字列。
     * IME変換時はcompositionendで入力を正規化し、それ以外はformatterで正規化する。
     */
    formatter(value, event) {
      return event.isComposing ? value : this.normalize(value)
    },
  },
}
</script>