LoginSignup
22
14

More than 5 years have passed since last update.

Vueでの配列番号直指定での編集はダメ。ゼッタイ。

Last updated at Posted at 2017-03-03

概要

こういう配列番号を直指定で上書く書き方よくやるんだけど、Vueを使用してる時はしてはいけない。

js
var test_array = [1, 2, 3, 4]
test_array[1] = 5 // [1, 5, 3, 4]

なぜか。

それは算出プロパティが正しく動かなくなるからである。

何があった?

リストの編集機能とかよく作るじゃない。
で、編集用の子コンポーネントモーダル作って、編集したらプレビューさせる親コンポーネントに表示するとする。
親コンポーネントに表示する際、

  • プレビュー用の値
  • サーバ送信用のhiddenのname/value

を更新したいとすると、子コンポーネントから受け取った値を加工したい場合もあって、
算出プロパティ使って多少処理をいれたりするじゃない。

その際、編集時の処理で親コンポーネントで配列の値を直指定で更新してました。
コードはこんな感じ。

sample.coffee
Vue.component('child_component', {
    template: '#child_template'
    method:
        setOption: (value, index)-> # [1]編集時にこのメソッドを呼び出す
            hub.$emit 'set-option', value, index
})

Vue.component('parent_component', {
    template: '#parent_template'
    data: ->
        { return options: [] }
    computed:
        computed_options: -> # [3]ここで、optionsが変更された際に再評価してほしいが、されない・・!
            # ここでoptions使ってdisp_optionsを用意する
            return disp_options
    created: ->
        self = @
        hub.$on "set-option", (value, index) ->
            self.options[index] = value # [2]optionを子コンポーネントの値で更新
})

hub = new Vue()

なぜ?

Vueの公式サイトにこう書いてあった。

JavaScript の制限のため、Vue は配列で以下の変更を検出することはできません

1. インデックスでアイテムを直接設定するとき。例: vm.items[indexOfItem] = newValue

なんてこった。。。

どうしたら?

こうしたら良いのだって。

pattern1.js
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
pattern2.js
// Array.prototype.splice`
example1.items.splice(indexOfItem, 1, newValue)

予想外にハマって時間取られました。。。

どうやって解決した?

時間かかってどうしようもなかったのでここで質問しました。
https://vuejs-jp-slackin.herokuapp.com/

質問してから30分程度で解決しました。
ありがとうございました!!!!!

refs

22
14
2

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
22
14