Vue.js:Composition API うまく動かない

以下記事の2ページ目「Composition APIを利用したロジックの共通化」をやってみるがうまくいかない
新Vue.js「Vue 3」でコンポーネント実装法を大きく変える「Composition API」:CodeZine(コードジン)


現象

こうなって欲しいが
こうなってしまう

v-forでterminal配列を表示させている筈だが、その上の階層のstate変数全体が表示されている?
テキストボックス(input)のv-modelも"[object Object]"と表示されてしまう。
件数表示(compute)とボタンのイベントは正常

ソース

main.js
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
  
App.vue
<template>
  <div>
    <phones/>
  </div>
</template>

<script>
import Phones from './components/Phones.vue'

export default {
  name: 'App',
  components: {
    Phones
  },
}
</script>
  
components/PhonesLogic.js
import { reactive, computed, toRefs} from 'vue'

export default function PhonesLogic(initialList)
{
    const state = reactive(
        {
            terminals: initialList,
            newTerminal: '',
        },
    )
    function addNew() {
        state.terminals.push(state.newTerminal)
        state.newTerminal = ''
    }
    const count = computed(function() {
        return state.terminals.length
    })
    return {...toRefs(state), addNew, count}
}
  
components/Phones.vue
    <template>
    <div>
      <h4>iOS: {{ iOSLogic.count }} 機種</h4>
      <ul>
        <li v-for="(elem, index) in iOSLogic.terminals" v-bind:key="index">
          {{ elem }}
        </li>
      </ul>
      <h4>Android: {{ androidLogic.count }} 機種</h4>
      <ul>
        <li v-for="(elem, index) in androidLogic.terminals" v-bind:key="index">
          {{ elem }}
        </li>
      </ul>
      <h4>合計: {{ countTotal }} 機種</h4>
      <div>
        <input v-model="iOSLogic.newTerminal" placeholder="iOS機種">
        <button @click="iOSLogic.addNew">追加</button>
      </div>
      <div>
        <input v-model="androidLogic.newTerminal" placeholder="Android機種">
        <button @click="androidLogic.addNew">追加</button>
      </div>
    </div>
  </template>
  <script>
  import { computed } from 'vue'
  import PhonesLogic from './PhonesLogic'
  export default {
    setup() {
      // PhoneLogicでiOS/Androidの各処理ロジックを生成
      const iOSLogic = PhonesLogic(['iPhone 11'])
      const androidLogic = PhonesLogic(['Galaxy S20 5G'])
      // 総端末数を計算する算出プロパティ
      const countTotal = computed(function() {
        return iOSLogic.count.value + androidLogic.count.value
      })
      // ここまで定義してきた内容を返却
      return {
        iOSLogic, androidLogic, countTotal
      }
    }
  }
  </script>
  

調査

components/PhonesLogic.js PhonesLogicメソッドの戻り値 "...toRefs(state)" を "state" へ変更
li要素のterminals配列を参照している箇所を "xxxLogic.terminals" から "xxxLogic.state.terminals" へ変更
input要素のv-modelを "xxxLogic.newTerminal" から "xxxLogic.state.newTerminal" へ変更したら正常動作した。

オリジナルのサンプルソース(p005_refactor)から、
・components/Phones.vue
・components/PhonesLogic.js
・App.vue
・main.js
をコピーしてみたがダメ
ということはソースコードのパンチミスが原因ではない


Vue.js

0 件のコメント:

その他の記事