iT邦幫忙

1

(已解決)Vue.js 在 v-for 中的 v-model 請教

大家好,我是 Vue.js 的新手還請多多指教,以下是我遇到的問題,以及部分程式碼,供參考:

  1. 我遇到當我點選第一個 Table 的雞的 checkbox 時,所有 Table 的雞的 checkbox 都會勾選起來;當我點選第三個 Table 的豬的 checkbox 時,所有 Table 的豬的 checkbox 都會勾選起來...(以此類推)。希望點選第一個 Table 的雞的 checkbox 時,只有點選的第一個 Table 的雞的 checkbox 會勾選起來就好;點選第三個 Table 的豬的 checkbox 時,只有點選的第三個 Table 的豬的 checkbox 會勾選起來就好...(以此類推)。
  2. 另外,希望在按下第一個 clickBtn() 按鈕時能夠 console.log 第一個 Table 所勾選的結果就好;按下第三個 clickBtn() 時能夠 console.log 第三個 Table 所勾選的結果就好...(以此類推)。

謝謝

HTML:

<template>
    <div id="app">
        <div v-for="(item, key) in list" :key="key">
            <h5>{{ item.id }}<Button label="Click" class="p-button-label p-button-sm" style="float:right" @click="clickBtn()" /></h5>
            <DataTable :value="animals" showGridlines responsiveLayout="scroll" :loading="loading">
            <Column field="0" header="雞">
                <template #body>
                <input type="checkbox" class="form-check-input" id="check0" v-model="checkboxArray" value="雞" style="cursor:pointer">
                </template>
            </Column>
            <Column field="1" header="豬">
                <template #body>
                <input type="checkbox" class="form-check-input" id="check1" v-model="checkboxArray" value="豬" style="cursor:pointer">
                </template>
            </Column>
            <Column field="2" header="牛">
                <template #body>
                <input type="checkbox" class="form-check-input" id="check2" v-model="checkboxArray" value="牛" style="cursor:pointer">
                </template>
            </Column>
            </DataTable>
        </div>
    </div>
</template>

JS:

<script>
    export default {
      name: 'app',
      data() {
        return {
            list: [{"id": "1","title": "animals1"},{"id": "2","title": "animals2"},{"id": "3","title": "animals3"},{"id": "4","title": "animals4"},{"id": "5","title": "animals5"}],
            animals: [{"0":"","1":"","2":""}],
            checkboxArray: [],
        }
      }
    }
</script>
Mao iT邦新手 1 級 ‧ 2021-10-23 00:28:32 檢舉
這樣問有點難幫你,不知道 `list` 這個資料在哪裡,
不過既然會一起勾選,我猜是因為你 `checkbox` 的 value 值都一樣,
而 `@click` 綁定的函式要把 `()` 去掉。
小斑 iT邦新手 3 級 ‧ 2021-10-23 00:33:21 檢舉
不好意思,剛剛有想到,已修正補上 list 資料。
小斑 iT邦新手 3 級 ‧ 2021-10-23 10:05:51 檢舉
@毛毛 不好意思,剛剛有想到,已修正補上 list 資料,再麻煩幫忙看看,感謝。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

3
listennn08
iT邦高手 5 級 ‧ 2021-10-23 14:34:42
最佳解答
  1. checkbox 使用 v-model 綁定同一個變數,只要變數有其中一個 value 被勾選,你使用 v-for 迭代出來的 checkbox 都會被勾選,因為是參照同一個陣列,所以要使用二維陣列隔開每個 table 的勾選選項,二維陣列要跟你的 list 一樣長所以可以這樣產生至 checkboxArray
created() {
  this.checkboxArray.push(...Array.from({ length: this.list.length }).map(() => []))
}

然後 v-model 改成

v-model="checkboxArray[key]"
  1. 希望按下 clickBtn 只秀當前 table 的選取狀態,一樣可以使用 key 當參數去代出來
<template>
    <!-- ... -->
    <Button label="Click" class="p-button-label p-button-sm" style="float:right" @click="clickBtn(key)" />
    <!-- ... -->
</template>
<script>
export default {
  // ...
  methods: {
    clickBtn(idx) {
      console.log(this.checkboxArray[idx])
    }
  }
}
</script>
Mao iT邦新手 1 級 ‧ 2021-10-23 15:20:06 檢舉

挖~原來可以這樣把值分別傳進 checkboxArray,我還苦苦的為每個 value 值定義= =
/images/emoticon/emoticon33.gif

小斑 iT邦新手 3 級 ‧ 2021-10-23 23:20:45 檢舉

真的非常感謝!幫助了我很多!另外,不知道方便再多請教一下,使用二維陣列後我暫時有點不太知道怎麼在 script 中控制每一個 checkbox,我有測試過 this.checkboxArray[idx][x] 這樣格式的寫法但好像不太行,所以再請教。

我想將 HTML 中每一個 checkboxvalue 改成 false
然後在 methods: {//...} 中控制某幾個 checkboxtrue (因為是透過串接 API 後才會知道哪些為 true,所以才另外寫在 methods)。

然後希望能夠在 clickBtn
console.log 印出那一個 Table 的每一個動物的 ture/false,例如:console.log(this.checkboxArray[idx][x])顯示ture/false

謝謝/images/emoticon/emoticon41.gif

1
Mao
iT邦新手 1 級 ‧ 2021-10-23 14:53:03

我遇到當我點選第一個 Table 的雞的 checkbox 時,所有 Table 的雞的 checkbox 都會勾選起來;當我點選第三個 Table 的豬的 checkbox 時,所有 Table 的豬的 checkbox 都會勾選起來...(以此類推)。希望點選第一個 Table 的雞的 checkbox 時,只有點選的第一個 Table 的雞的 checkbox 會勾選起來就好;點選第三個 Table 的豬的 checkbox 時,只有點選的第三個 Table 的豬的 checkbox 會勾選起來就好...(以此類推)。

會出現勾選一個,同一種品項都一起勾選起來的這個原因,是因為你使用 v-model 雙向綁定後,checkbox 的 value 並沒有分別給值,所以雙向綁定的結果就是,你勾選一個,那個 value 值傳到 checkboxArray 後,Vue 幫你把雙向綁定相同value 值,也都一起勾選起來了。

另外,希望在按下第一個 clickBtn() 按鈕時能夠 console.log 第一個 Table 所勾選的結果就好;按下第三個 clickBtn() 時能夠 console.log 第三個 Table 所勾選的結果就好...(以此類推)。

而你想要按鈕的這個功能算是比較複雜的程式邏輯,會建議你先自己思考該怎麼做,如果覺得太難,試著拆分邏輯細節,對你會比較有幫助,我這裡先給你解答,但還是希望你能靠自己的想法再做一次!


因為我本身是自學 React,Vue 只有在六角學院體驗營稍微體驗,所以對於 Vue Cli 其實沒有到很了解,所以我有稍微調整你的標籤,因為我不清楚 <DataTable><Column> 是使用哪個套件的,所以我把他替換成原生的 HTML 標籤,希望你看得懂,整體改的重點方向在,v-for 把每個 input 的 value 都設置各自的值,如: :value="item.animal.chicken"

<template>
    <div id="app">
        <div v-for="(item, key) in list" :key="key">
            <h5>{{ item.title }}<button style="float:right" :id="item.id" @click="clickBtn">按鈕</button></h5>
            <table>
              <tr>
                <td>
                  <label :for="item.animal.chicken">雞</label>
                  <input type="checkbox" :id="item.animal.chicken" v-model="checkboxArray" :value="item.animal.chicken" style="cursor:pointer">
                </td>
                <td>
                  <label :for="item.animal.pork">豬</label>
                  <input type="checkbox" :id="item.animal.pork" v-model="checkboxArray" :value="item.animal.pork" style="cursor:pointer">
                </td>
                <td>
                  <label :for="item.animal.beef">牛</label>
                  <input type="checkbox" :id="item.animal.beef" v-model="checkboxArray" :value="item.animal.beef" style="cursor:pointer">
                </td>
              </tr>
            </table>
        </div>
    </div>
</template>

而邏輯的部分,資料結構有為 list 添加 animal 來為每個 input 綁定值,這部分我知道 React 怎麼優化,但 Vue 我就不知道要怎麼在 value 串接字串與變數。

而按鈕邏輯的部分,我使用的是 reduce 這個方法,算是初學者比較不懂的方法,會建議你先嘗試想一個自己的邏輯後,在認識進階的邏輯,學起來會比較快。

邏輯思考方向,我們有所有勾選品項的陣列,透過現有知識,把我們想要歸類在一起的放一起,有基礎 JS 邏輯也能實作出來,只是會打比較長

<script>
    export default {
      name: 'app',
      data() {
        return {
            list: [
              {
                "id": "1",
                "title": "animals1",
                animal: {chicken: "chicken_1", pork: "pork_1", beef: "beef_1"}
              },{
                "id": "2",
                "title": "animals2",
                animal: {chicken: "chicken_2", pork: "pork_2", beef: "beef_2"}
              },{
                "id": "3",
                "title": "animals3",
                animal: {chicken: "chicken_3", pork: "pork_3", beef: "beef_3"}
              },{
                "id": "4",
                "title": "animals4",
                animal: {chicken: "chicken_4", pork: "pork_4", beef: "beef_4"}
              },{
                "id": "5",
                "title": "animals5",
                animal: {chicken: "chicken_5", pork: "pork_5", beef: "beef_5"}
              }
            ],
            animals: [],
            checkboxArray: [],
        }
      },
      methods: {
        clickBtn(e){
          this.animals = [];
          this.checkboxArray.reduce((animals, animal)=>{
            animal.indexOf(e.target.id) !== -1 ? animals.push(animal) : null;
            return animals
          }, this.animals)
          console.log("你當前按鈕選擇的品項:" + this.animals)
          console.log("你所有勾選的品項:" + this.checkboxArray)
        }
      }
    }
</script>

Codepen 示範

小斑 iT邦新手 3 級 ‧ 2021-10-23 23:26:27 檢舉

真的非常感謝!很細心的詳解和示範!@listennn08 大大的寫法好像比較方便,所以我選擇採用他的方式往下進行,但您們都一樣幫助我許多,真的很感謝您!

另外,不知道方便再多請教一下,使用二維陣列後我暫時有點不太知道怎麼在 script 中控制每一個 checkbox,我有測試過 this.checkboxArray[idx][x] 這樣格式的寫法但好像不太行,所以再請教。

我想將 HTML 中每一個 checkboxvalue 改成 false
然後在 methods: {//...} 中控制某幾個 checkboxtrue (因為是透過串接 API 後才會知道哪些為 true,所以才另外寫在 methods)。

然後希望能夠在 clickBtn
console.log 印出那一個 Table 的每一個動物的 ture/false,例如:console.log(this.checkboxArray[idx][x])顯示ture/false

謝謝/images/emoticon/emoticon41.gif

我要發表回答

立即登入回答