7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue の Boolean型のプロパティのdefaultを省略した場合の挙動について

Last updated at Posted at 2021-04-22

VueBoolean の プロパティのデフォルト値を省略した場合の挙動についてのメモです。

調べたVue のバージョンは 3.0.11です。

検証コード

ParentComponent.vue
<template>
  <ChildComponent />
</template>

<script lang="ts">
import { defineComponent } from "vue";
import ChildComponent from "./ChildComponent.vue";

export default defineComponent({
  name: "ParentComponent",
  components: {
    ChildComponent,
  },
  setup() {
    return {};
  },
});
</script>
ChildComponent.vue
<template>
  <div></div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "ChildComponent",
  props: {
    testValue: {
      type: Boolean,
    },
  },
  setup(props) {
    console.log(props.testValue); //false が出力される
    return {};
  },
});
</script>

testValue という Boolean 型のプロパティを定義してデフォルト値をなしにしています。

この時にtestValueconsole.log で出力してみました。

default がないので undefined になるかと思ったのですが false になるようです。

Vueのコードを追いかけてみる

componentProps.ts あたりでされているようです。

resolvePropValue という関数の この部分を見てみます。

// boolean casting
if (opt[BooleanFlags.shouldCast]) {
  if (!hasOwn(props, key) && !hasDefault) {
    value = false
  } else if (
    opt[BooleanFlags.shouldCastTrue] &&
    (value === '' || value === hyphenate(key))
  ) {
    value = true
  }
}

ここのコードにより value=false が行われているようです。

BooleanFlags.shouldCast, BooleanFlags.shouldCastTrue を参照しているようですがこれは

const enum BooleanFlags {
  shouldCast,
  shouldCastTrue
}

このように定義されています。
propsの各プロパティに追加する属性として定義されているような感じ(かな?)

hyphenateAbcDefabc-def という値に変換する関数です。

opt に対する設定は normalizePropsOptions という関数のこの部分で行われています。
(こっちの関数だとprop ですね)

const opt = raw[key]
const prop: NormalizedProp = (normalized[normalizedKey] =
  isArray(opt) || isFunction(opt) ? { type: opt } : opt)
if (prop) {
  const booleanIndex = getTypeIndex(Boolean, prop.type)
  const stringIndex = getTypeIndex(String, prop.type)
  prop[BooleanFlags.shouldCast] = booleanIndex > -1
  prop[BooleanFlags.shouldCastTrue] =
    stringIndex < 0 || booleanIndex < stringIndex
  // if the prop needs boolean casting or default value
  if (booleanIndex > -1 || hasOwn(prop, 'default')) {
    needCastKeys.push(normalizedKey)
  }
}

プロパティのtype の中にBoolean が含まれていたら BooleanFlags.shouldCast のところはtrue になるようです。

また プロパティがBooleanのみ もしくは 複数の型を許容しておりBoolean, String の順番で登録されていると BooleanFlags.shouldCastTruetrue になるようです。

上記の内容を踏まえたうえで、追加の検証をしてみる

上記のコードを確認したうえで 追加の検証をしてみます。

ParentComponent.vue
<template>
  <ChildComponent
    boolean02
    booleanOrString02
    booleanOrString04

    hyphenate01="hyphenate01"
    hyphenate02="hyphenate02"
   
   />
</template>

<script> 部分は省略

ChildComponent.vue
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "ChildComponent",
  props: {
    //Booleanのみ
    boolean01: {
      type: Boolean,
    },
    boolean02: {
      type: Boolean,
    },

    //Booleanが先
    booleanOrString01: {
      type: [Boolean, String],
    },
    booleanOrString02: {
      type: [Boolean, String],
    },

    //Stringが先
    booleanOrString03: {
      type: [String, Boolean],
    },
    booleanOrString04: {
      type: [String, Boolean],
    },

    //特殊
    hyphenate01: {
      type: [Boolean, String],
    },
    hyphenate02: {
      type: [String, Boolean],
    },
  },
  setup(props) {
    console.log(props.boolean01); //false
    console.log(props.boolean02); //true

    console.log(props.booleanOrString01); //false
    console.log(props.booleanOrString02); //true

    console.log(props.booleanOrString03); //false
    console.log(props.booleanOrString04); //(空文字列)

    console.log(props.hyphenate01); //true
    console.log(props.hyphenate02); //hyphenate02

    return {};
  },
});
</script>

<template> 部分は省略

上記のような結果になりました。

String, Boolean の順番を入れ替えると props名のみを与えた場合の挙動は異なるようです。

hyphenate01true になることは意外でした。

感想

ただのBoolean のプロパティについてでしたが コードを見てみると意外な発見があり面白かったです。

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?