Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
33
Help us understand the problem. What is going on with this article?
@ysKuga

Vue.js でのツリー構造など循環参照の具体的コピペ

More than 1 year has passed since last update.

Vue.js での「この単純なアプリケーション」にて入れ子を実現する

子から親を参照可能に

コンポーネント間の循環参照の記述の通り、
子側から親を配下のコンポーネントとするための記述を行うためには
beforeCreate のタイミングで require を実施するか、
components への指定にて import を行わせる

  • Nuxt.js においては require ではうまくいかなかったので
    両方うまくいった components での import のほうがよさそうです
/components/TodoListItem.vue(子)
<script>
  export default {
    // Nuxt.js ではこちらのほうがうまくいった
    components: {
      TodoList: () => import("./TodoList.vue")
    },
    ・・・
    beforeCreate() {
      // 親となっている TodoList を template にて使用可能とする
      // - ただしこの記述は Nuxt.js ではうまくいかなかった
      //this.$options.components.TodoList = require('./TodoList.vue')
    }
    ・・・
  };
</script>

data から props への変更による循環参照の回避

子側から呼び出し可能となったところで変更を行わず template に記載すると
循環参照によりエラーが発生するのでプロパティの種類を変更する

/components/TodoList.vue(親)
  export default {
    ・・・
    props: {
      // あくまで親要素より受け取るという状態にすることで無限ループを回避
      todos: {
        type: Array,
        // 「一番上」の TodoList 用にデフォルト値を指定する
        default() {
          return [
            {
              id: nextTodoId++,
              text: 'Learn Vue'
            },
            {
              id: nextTodoId++,
              text: 'Learn about single-file components'
            },
            {
              id: nextTodoId++,
              text: 'Fall in love'
            }
          ];
        }
      }
    },
    data () {
      return {
        newTodoText: '',
        // TodoListItem より受け取れるよう独自のプロパティとしては持たせない
        //todos: [
        //    {
        //      id: nextTodoId++,
        //      text: 'Learn Vue'
        //    },
        //    ・・・
        //]
      }
    },
    ・・・
  };

入れ子を実装

子であった TodoListItem にて TodoList を呼び出し
その子となる TodoList は呼び出しもとよりデータを受ける

/components/TodoListItem.vue(入れ子)
<template>
  <li draggable="true">
    {{ todo.text }}
    <button @click="$emit('remove', todo.id)">
      X
    </button>
    <!-- 入れ子を実装しつつ「子要素」への props down -->
    <TodoList
      :todos="todos"
      />
  </li>
</template>

<script>
  export default {
    ・・・
    data() {
      // もとは親であった TodoList のプロパティを TodoListItem 自身に持たせる
      return {
        todos: []
      };
    }
    ・・・
  };
</script>

実例 (Warning 有)

・・・これだと削除時に「props」をいじるなと注意されてしまう

[Vue warn]:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders.
Instead, use a data or computed property based on the prop's value. Prop being mutated: "todos"

「prop の値を基に data を使いなさい」(おおまかに)

props down を行いつつ data も使用

props として配列を受け取り、そのまま使用していたことが問題を発生させていたので
props でいったん受けたものを data にて流用する形にする

/components/TodoList.vue
  ・・・
  props: {
    // ここでは todos を受け取らないように変更
    prop_todos: {
      type: Array,
      default() {
        return [
          {
            id: nextTodoId++,
            text: 'Learn Vue'
          },
          ・・・
        ];
      }
    }
  },
  data () {
    return {
      newTodoText: '',
      // props の値を data として使用
      todos: this.prop_todos
    }
  },
  ・・・
/components/TodoListItem.vue(todosからprop_todosへ)
<template>
  <li draggable="true">
    ・・・
    <!-- 渡す対象を prop_todos に変更 -->
    <TodoList
      :prop_todos="todos"
      />
    ・・・
  </li>
</template>

実例 (props を data にして Warning 対応)

props への操作で Warning が発生して前述の事例を対応したもの
https://codesandbox.io/s/5vkv67yw4

33
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ysKuga
いつもの vagrant のおっさん

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
33
Help us understand the problem. What is going on with this article?