v-model繫結陣列的用法(以動態增減form表單中的input輸入框為例)

2021-03-31 03:02:38

問題描述

在我們的印象中,v-model的用法好像就是繫結一個data中的資料(比如輸入框)。比如下面的常見用法:

<el-input v-model="input" placeholder="請輸入內容"></el-input>

<script>
export default {
  data() {
    return {
      input: ''
    }
  }
}
</script>

這樣就會給我們造成一個錯覺,好像v-model就是繫結一個資料字串。其實v-model不僅可以繫結字串,還可以結合v-for繫結陣列。如下面的用法:

<template>
  <div id="app">
    <!-- 這裡v-model動態繫結inputArr下的value -->
    <el-input 
      v-model="item.value" 
      placeholder="請輸入內容" 
      v-for="(item,index) in inputArr" 
      :key="index"
    ></el-input>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputArr:[
        {
          value:"",
        },
        {
          value:"",
        },
        {
          value:"",
        },
      ]
    };
  },
};
</script>

結合vue的偵錯工具看一下資料雙向繫結的效果圖:
image.png

需求如下

下圖中的這個效果圖,就用到了v-model繫結陣列的用法。
image

需求分析

有一個表單,作品項中預設有兩個輸入框,當點選增加作品按鈕時,可以新增輸入框。新增輸入框的左邊有一個可以刪除的小圖示(也就是從第三個輸入框開始),點選刪除小圖示,就可以把對應的輸入框刪除掉。當然表單中的輸入框都是必填項。沒填寫就做一個提示吧。

思路分析

首先是要放一個el-form的結構。下面的作品項el-form-item中的el-input通過v-for迴圈bookArr同時v-model繫結陣列中的每一項的value。至於刪除小圖示,也一併寫好,只不過第一個和第二個輸入框不顯示,也就是v-show判斷一下,當index為0或者為1的時候隱藏。當點選增加作品時,往bookArr中輸增加一項,當點選刪除小圖示時,根據刪除的哪一項的索引,通過splice方法從第i個位置,刪除1項。當然點選確認的時候要看看輸入框內容是否為空,為空就提示一下,要是輸入框全部都填寫了,就可以使用輸入框的引數作為引數發請求發給後臺了了。

程式碼步驟

html部分

<template>
  <div id="app">
    <div class="content">
      <div class="contentHeader">
        <span>新增作家資訊</span>
        <i class="el-icon-close"></i>
      </div>
      <div class="contentBody">
        <el-form ref="form" :model="form" label-width="80px">
          <el-form-item label="名字:">
            <el-input 
              v-model.trim="form.name"
              placeholder="請輸入作家姓名"
            ></el-input>
          </el-form-item>
          <el-form-item label="作品:">
            <!-- 這個div裡面的是細節重點 -->
            <div class="itemitem" v-for="(item, index) in bookArr" :key="index">
              <!-- 刪除小圖示 -->
              <i 
                v-show="show(index)"
                @click="deleteItem(index)"
                class="el-icon-remove-outline dingwei"
              ></i>
              <!-- 輸入框v-model繫結陣列 -->
              <el-input 
                v-model.trim="item.value"
                placeholder="請輸入作家著作"
              ></el-input>
            </div>
            <el-button type="text" size="small" @click="addBook"
              >+增加作品</el-button
            >
          </el-form-item>
        </el-form>
      </div>
      <div class="contentFooter">
        <el-button size="small">取消</el-button>
        <el-button size="small" type="primary" @click="getFormValue">確認</el-button>
      </div>
    </div>
  </div>
</template>

js部分

<script>
export default {
  data() {
    return {
      form: {
        name: "",
      },
      bookArr: [
        {
          value: "",
        },
        {
          value: "",
        },
      ],
    };
  },
  methods: {
    // 新增一項
    addBook() {
      this.bookArr.push({ value: "" });
    },
    // 從第三項開始才展示
    show(i){
      if(i==0 | i==1){
        return false
      }else{
        return true
      }
    },
    // 根據索引刪除對應哪一項
    deleteItem(i){
      this.bookArr.splice(i,1)
    },
    // 點選確認按鈕
    getFormValue(){
      if(this.form.name == ""){
        this.$message.error('作家名字為必填項');
        return
      }
      // 這裡也可以用陣列的every方法做判斷
      let num = 0
      this.bookArr.forEach((item)=>{
        if(item.value == ""){
          num = num + 0
        }else{
          num = num + 1
        }
      })
      // 當num等於this.bookArr.length的時候,說明都填寫了
      if(num == this.bookArr.length){
        this.form.bookArr = this.bookArr
        console.log("發請求",this.form);
      }else{
        this.$message.error('作家作品需全部填寫');
      }
    }
  },
};
</script>

css部分

<style lang="less" scoped>
#app {
  width: 100%;
  height: 100vh;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
  .content {
    width: 480px;
    height: 360px;
    background-color: #fff;
    border-radius: 5px;
    .contentHeader {
      width: 100%;
      height: 50px;
      border-bottom: 1px solid #e9e9e9;
      box-sizing: border-box;
      padding: 0 25px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      span {
        font-size: 20px;
      }
      i {
        font-size: 25px;
        cursor: pointer;
      }
    }
    .contentBody {
      overflow-y: auto;
      width: 100%;
      height: calc(100% - 100px);
      display: flex;
      justify-content: center;
      padding-top: 20px;
      box-sizing: border-box;
      padding-right: 25px;
      // align-items: center;
      .el-form {
        .itemitem {
          display: flex;
          align-items: center;
          position: relative;
          .dingwei {
            position: absolute;
            left: -30px;
            top: 12px;
          }
          i {
            font-size: 20px;
            margin-right: 6px;
          }
          .el-input {
            margin-bottom: 8px;
            width: 206px;
          }
        }
      }
    }
    .contentFooter {
      width: 100%;
      height: 50px;
      line-height: 50px;
      border-top: 1px solid #e9e9e9;
      text-align: center;
    }
  }
}
</style>

總結

好記性不如爛筆頭,記錄一下吧。如果本篇文章的思路幫助到您了,歡迎各位看官大佬們賞賜個贊吧。手動比心