Vue2からVue3への移行時に気をつけたい!`v-model`と`input[type="number"]`の予期せぬ型変換
type="number"
を持つ場合はnumber
修飾子が自動で適用されます
Vue3では、inputが
ref: https://ja.vuejs.org/guide/essentials/forms.html#number
一方Vue2では、明示的に.number
を使用しない限りv-modelは文字列のまま扱われていました
そのため、Vue2からVue3への移行をする際に、実装によっては意図しない挙動になってしまうかもしれません
検証環境を用意し、何が起こっているかを確認する
今回はVue2, Vue3と環境を用意し、iframeを使って1つのHTMLで確認できるよう動かしてみました
どういったケースで困るか
例えば、0から始まる入力を扱うもの(電話番号など)は、丸められてしまうため、バリデーションによっては保存できないなどの不具合が発生してしまいそうですね
他にも、APIでstringを期待しているのにnumberで送られてしまい、リクエストが成功しないケースなどが考えられそうです
どう対応するか
今回はinput[type="number"]
を input[type="text"]
に変更するという方法で対応をしました
場所によっては pattern="[0-9]*"
, inputmode="numeric"
をつけます
eslintのルールを作成してこの組み合わせを非推奨にする
https://github.com/vuejs/eslint-plugin-vue の実装を参考に、カスタムルールを作成してみました
const utils = require("eslint-plugin-vue/lib/utils");
/** @type {import("eslint").Rule.RuleModule} */
module.exports = {
meta: {
type: "problem",
fixable: null,
schema: [],
docs: {
description: "disallow using v-model on <input type='number'>",
},
messages: {
noVModelOnNumberInput:
'v-model on <input type="number"> now implicitly applies the number modifier, which can lead to unexpected type conversions. Avoid using v-model and instead handle value changes explicitly.',
},
},
create(context) {
return utils.defineTemplateBodyVisitor(context, {
"VAttribute[directive=true][key.name.name='model']"(node) {
const element = node.parent.parent;
if (
element &&
element.name === "input" &&
utils.hasAttribute(element, "type", "number")
) {
context.report({
node,
loc: node.loc,
messageId: "noVModelOnNumberInput",
});
}
},
});
},
};
これは、破壊的変更?
Vue3へアップデートすることによって既存のコードが壊れる可能性があり、それを修正しなければならないという点で、破壊的変更と言えそうです。
ですが、 https://v3-migration.vuejs.org/ に今回の事象のことは記載されていなかったため、Zennにまとめてみることにしました
すでにIssueは上がっている
ですが、長い事動いていないように見えます😢
株式会社SODAの開発組織がお届けするZenn Publicationです。 是非Entrance Bookもご覧ください! → recruit.soda-inc.jp/engineer
Discussion