[Vueitfy] データバインディング時に、v-text ディレクティブとMustache構文のどちらを使うか。


###環境
・Vue      3.12.0
・Vuetify  2.4.5

###概要
**リアクティブなテキストデータをVuetifyのUIコンポーネント（例.v-btn,v-chipなど） でバインディングする際は、v-textディレクティブとmustache構文の挙動に違いがあったので、原因を調べてみた。**

###発生したエラー
ボタンクリックで表示テキストをリアクティブに変更する際に、コンソールでエラーが出力された。

```console
uncaught domexception: failed to execute 'removechild' on 'node':
the node to be removed is not a child of this node error
```

**①エラーを出力したコード（テキストデータをv-textディレクティブでバインディングしている。）**

```vue
<template>
...
<v-btn 
  @click="checked === true ? uncheck() : check()"
  v-text="checked === true ? checkedText : uncheckedText"
/>
...
</template>

<script>
...
data(){
  return {
   checked: true
   checkedText: '確認済み',
   uncheckText: '未確認'
  }
}
...
</scirpt>
```

```html
<button type="button" class="v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default">
  確認済み
</button>
```

**②修正後のコード（テキストデータをMustache構文でバインディングしている。）**

```vue
<template>
...
<v-btn 
  @click="checked === true ? uncheck() : check()">
 {{ checked === true ? checkedText : uncheckedText }}
</v-btn>
...
</template>

<script>
...
data(){
  return {
   checked: true
   checkedText: '確認済み',
   uncheckText: '未確認'
  }
}
...
</scirpt>

```

```html
<button type="button" class="v-btn v-btn--is-elevated v-btn--has-bg theme--light v-size--default">
　  <span class="v-btn__content">確認済み</span>
</button>
```

エラー内容の確認
-
MDNでエラー内容を確認してみる。（https://developer.mozilla.org/ja/docs/Web/API/Node/removeChild）
DOM操作時にNodeから**childNode**を消そうとする時に出力されるエラーには2種類存在する模様。

**1.そもそもchildNodeが存在しない場合に出力される例外エラー。**

```html
<div id="parent"></div>
<script type="text/javascript">
 var parent = document.getElementById("parent");
 var child = document.getElementById("child");
 var removeFail = parent.removeChild(chid);
//Uncaught TypeError: Failed to execute 'removeChild' on 'Node':
//parameter 1 is not of type 'Node'.
// -> childNode自体がページに無い。
</script>
```
**2.DOM上に存在していたが、すでに削除されていた場合に出力される例外エラー。**

```html
<div id="parent">
　<div id="child">
 </div>
</div>
<script type="text/javascript">
 var parent = document.getElementById("parent");
 var child = document.getElementById("child");
 var removeSuccessful = parent.removeChild(chid);
 removeFail = parent.removeChild(chid);
//Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be //removed is not a child of this node.
</script>
```
今回のケースでは、DOMが再描画される際に、前提とされているchildNodeがないので**①v-textディレクティブ記法**ではエラーが出力されている。今回は、Vueコードからエラーが出ているので、内部でDOMを切り替えているVueかVuetifyの内部で、childNodeがあるかどうかを判定している部分があるのではないかと予想。

**Vuetifyで使用しているUIコンポーネントのソースを見てみる.**

```typescript:vuetify/src/components/VBtn/VBtn.ts
...
    genContent (): VNode {
      return this.$createElement('span', {
        staticClass: 'v-btn__content',
      }, this.$slots.default)
    },
...

```
VuetifyのUIコンポーネントにデータをバインディングする際
1.Mustache記法では、、**span**タグで**childNode**が生成される。
2.v-textディレクティブ記法では、**Node**が生成されず,シンプルテキストが描画される。

続いて、VuetifyでリアクティブにNodeを切り替えている部分を見てみる。

```typescript:vuetify/src/directives/ripple/index.ts
...
setTimeout(() => {
 animation.classList.remove('v-ripple__animation--in')
 animation.classList.add('v-ripple__animation--out')
 opacity(animation, 0)

 setTimeout(() => {
  const ripples = el.getElementsByClassName('v-ripple__animation')
  if (ripples.length === 1 && el.dataset.previousPosition) {
     el.style.position = el.dataset.previousPosition
     delete el.dataset.previousPosition
   }
　　　　　// エラー出力箇所。
   animation.parentNode && el.removeChild(animation.parentNode)
   }, 300)
 }, delay)
...
```
**el.removeChild**の箇所で、childNodeを削除しているが、v-text記法ではNodeが生成されないのでここでエラーが出力されている。

まとめ
-
Vuetifyの他のUIコンポーネントでも、v-text記法でデータをバインディングした際は、Nodeが生成されないので、真偽値で、ボタンを切り替える際にエラーが発生する模様。Vueitfyで、データバインディングする際はMustache記法で書く必要がある。

初めてQiitaに投稿してみました。全く間違っているよという部分等ありましたらご指摘いただけるとありがたいです。

(参考）
- https://stackoverflow.com/questions/44814346/in-what-situations-would-one-choose-v-text-over-the-mustache-syntax
- https://jp.vuejs.org/v2/guide/syntax.html
- https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild
- https://github.com/vuetifyjs/vuetify/issues/13457