Vuejs và Vue.set (), cập nhật mảng


92

Tôi mới đến Vuejs. Đã làm một cái gì đó, nhưng tôi không biết đó là cách đơn giản / đúng.

những gì tôi muốn

Tôi muốn một số ngày trong một mảng và cập nhật chúng vào một sự kiện. Đầu tiên, tôi đã thử Vue.set, nhưng nó không hoạt động. Bây giờ sau khi thay đổi mục mảng của tôi:

this.items[index] = val;
this.items.push();

Tôi đẩy () không có gì vào mảng và nó sẽ cập nhật .. Nhưng đôi khi mục cuối cùng sẽ bị ẩn, không hiểu sao ... Tôi nghĩ giải pháp này là một chút hacky, làm thế nào tôi có thể làm cho nó ổn định?

Mã đơn giản ở đây:

new Vue({
  el: '#app',
  data: {
  	f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {
    
    cha: function(index, item, what, count) {
    	console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);
  		this.items[index] = val;
      this.items.push();
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
    <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button>
      {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
    <br><br>
    </li>
  </ul>
</div>

Câu trả lời:


57

VueJS không thể nhận các thay đổi của bạn về trạng thái nếu bạn thao tác các mảng như thế này.

Như đã giải thích trong Common Beginner Gotchas , bạn nên sử dụng các phương thức mảng như push, splice hoặc bất cứ thứ gì và không bao giờ sửa đổi các chỉ mục như thế này a[2] = 2cũng như thuộc tính .length của một mảng.

new Vue({
  el: '#app',
  data: {
    f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {

    cha: function(index, item, what, count) {
      console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);

      this.items.$set(index, val)
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
      <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button> {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
      <br><br>
    </li>
  </ul>
</div>


1
Như đã nói trong tài liệu, $ set chỉ là một .splice () đẹp. Điều này có ý nghĩa vì giống như họ nói trong tài liệu, bạn nên sửa đổi mảng bằng cách sử dụng các phương thức của nó.
Borjante

1
Xin vui lòng không kết hợp indents tab với indents không gian, kích thước của một tab là rõ ràng khác nhau trên ứng dụng SE, làm cho nó khó đọc mã của bạn
Ferrybig

Trong trường hợp của tôi ES6 lây lan-nhà điều hành cho các hoạt động đẩy không hoạt động proberly với vue
Mathias S

116

CHỈNH SỬA 2

  • Đối với tất cả các thay đổi đối tượng cần sử dụng tính năng phản ứngVue.set(object, prop, value)
  • Đối với đột biến mảng, bạn có thể xem danh sách hiện được hỗ trợ tại đây

CHỈNH SỬA 1

Đối với vuex, bạn sẽ muốn làm Vue.set(state.object, key, value)


Nguyên

Vì vậy, chỉ dành cho những người khác đến câu hỏi này. Nó xuất hiện tại một số điểm trong Vue 2. * họ đã loại bỏ this.items.$set(index, val)để ủng hộ this.$set(this.items, index, val).

Splice vẫn có sẵn và đây là một liên kết đến các phương pháp đột biến mảng có sẵn trong liên kết vue .


Tôi cần cung cấp chuỗi nào làm 'chỉ mục'?
Kokodoko

@Kokodoko bạn có thể nói rõ bạn đang cố gắng làm gì không? Nếu nó là một mảng, nó phải là một số cho chỉ mục. Một chuỗi sẽ là nếu bạn đang thiết lập một trường trên một đối tượng.
Martin Calvert

Ah ok, IDE của tôi khẳng định nó phải là một chuỗi, phải là một trục trặc.
Kokodoko 13/02/18

Vue.set không dành cho vuex. Và cái này. $ Set không được dùng nữa.
localhoost

2
@MartinCalvert Nó nói "khi thêm thuộc tính vào đối tượng". Đó là mục đích chính của Vue.set, không chỉ liên quan đến vuex. Không dùng nữa, tôi đã đọc nó trên liên kết nhưng bây giờ đọc lại, tôi không hiểu hết. stackoverflow.com/questions/36671106/…
localhoost

10

Như đã nêu trước đây - VueJS đơn giản là không thể theo dõi các hoạt động đó (gán các phần tử mảng). Tất cả các hoạt động được VueJS theo dõi với mảng đều có ở đây . Nhưng tôi sẽ sao chép chúng một lần nữa:

  • đẩy()
  • pop ()
  • shift ()
  • unshift ()
  • mối nối ()
  • sắp xếp ()
  • đảo ngược()

Trong quá trình phát triển, bạn phải đối mặt với một vấn đề - làm thế nào để sống với điều đó :).

push (), pop (), shift (), unshift (), sort () và reverse () khá đơn giản và giúp bạn trong một số trường hợp nhưng trọng tâm chính nằm trong splice () , cho phép bạn sửa đổi mảng một cách hiệu quả sẽ được theo dõi bởi VueJs. Vì vậy, tôi có thể chia sẻ một số cách tiếp cận được sử dụng nhiều nhất khi làm việc với mảng.

Bạn cần thay thế Mục trong Mảng:

// note - findIndex might be replaced with some(), filter(), forEach() 
// or any other function/approach if you need 
// additional browser support, or you might use a polyfill
const index = this.values.findIndex(item => {
          return (replacementItem.id === item.id)
        })
this.values.splice(index, 1, replacementItem)

Lưu ý: nếu bạn chỉ cần sửa đổi một trường mục - bạn có thể làm điều đó chỉ bằng cách:

this.values[index].itemField = newItemFieldValue

Và điều này sẽ được VueJS theo dõi vì các trường mục (Đối tượng) sẽ được theo dõi.

Bạn cần làm trống mảng:

this.values.splice(0, this.values.length)

Trên thực tế, bạn có thể làm được nhiều hơn thế với hàm splice () - liên kết w3schools Bạn có thể thêm nhiều bản ghi, xóa nhiều bản ghi, v.v.

Vue.set () và Vue.delete ()

Vue.set () và Vue.delete () có thể được sử dụng để thêm trường vào phiên bản dữ liệu giao diện người dùng của bạn. Ví dụ: bạn cần một số dữ liệu hoặc cờ được tính toán bổ sung trong các đối tượng của mình. Bạn có thể làm điều này cho các đối tượng của mình hoặc danh sách các đối tượng (trong vòng lặp):

 Vue.set(plan, 'editEnabled', true) //(or this.$set)

Và gửi dữ liệu đã chỉnh sửa trở lại back-end theo cùng một định dạng để thực hiện việc này trước khi gọi Axios:

 Vue.delete(plan, 'editEnabled') //(or this.$delete)

0

Một phương pháp thay thế - và cách tiếp cận nhẹ nhàng hơn cho vấn đề của bạn - có thể là, chỉ cần chỉnh sửa mảng tạm thời và sau đó gán lại toàn bộ mảng cho biến của bạn. Vì Vue không xem từng mục riêng lẻ nên Vue sẽ xem toàn bộ biến đang được cập nhật.

Vì vậy, bạn điều này cũng sẽ hoạt động:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Điều này sau đó cũng sẽ cập nhật DOM của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.