element-ui 開發備忘

本文針對本人這兩天進行界面開發的過程當中遇到的一些坑點和要點進行記錄,留待往後備忘。vue

本篇博客將用一個極簡的購物清單的例子講解,例子的完整代碼可見最後。java

購物清單的數據結構說明

shoppingList: {
    supermarket: '',        // 超市名稱,非空,字符串
    status: true,           // 狀態位,默認爲 true
    items: [                // 購物清單項,0 到多個
        {
            name: '',       // 商品名,非空,字符串
            quantity: 0     // 數量,非空,整數
        }
    ]
}

瞭解了購物清單的數據結構以後,就能夠開始講解了。web

1. <el-radio>label 屬性

根據官方文檔label 屬性能夠爲 StringNumberBoolean,但官方文檔中沒有說明的是,若是要給 label 屬性設置 NumberBoolean 值,則須要加上冒號變成 :label,否則像 "0""true" 這類的值會被看成 String 處理。element-ui

<!-- 
  感興趣的能夠試着去掉 label 前的冒號,
  你會發如今頁面中沒有一個 radio 處於選中狀態,
  提交表單的時候對應的 status 會變成 String 而非 Boolean
  -->
<el-form-item prop="status" label="狀態">
  <el-radio v-model="shoppingList.status" :label="true">啓用</el-radio>
  <el-radio v-model="shoppingList.status" :label="false">禁用</el-radio>
</el-form-item>

2. 在 <el-table> 中放入表單組件

從購物清單的數據結構能夠看出,清單項部分是可變的,在 element-ui 裏不難解決,官方文檔中提到過動態增減表單項。但出於項目的須要,咱們但願清單項可以像表格那樣編輯,因而天然就有了在表格中嵌入表單組件的作法。官方文檔中有一個自定義列模板能夠用來作這個。在本例中,代碼以下:數組

<el-table :data="shoppingList.items">
  <el-table-column type="index"></el-table-column>
  <el-table-column label="商品名">
    <template slot-scope="scope">
      <el-form-item :prop="'items.' + scope.$index + '.name'" 
                    :rules="[{ required: true, message: '請輸入商品名稱', trigger: 'blur' }]">
        <el-input v-model="scope.row.name"></el-input>
      </el-form-item>
    </template>
  </el-table-column>
  <el-table-column label="數量">
    <template slot-scope="scope">
      <el-form-item :prop="'items.' + scope.$index + '.quantity'" 
                    :rules="[{ required: true, message: '請輸入商品數量' }, { type: 'number', message: '只能輸入數字' }]">
        <el-input v-model="scope.row.quantity"></el-input>
      </el-form-item>
    </template>
  </el-table-column>
  <el-table-column>
    <template slot-scope="scope">
      <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeItem(scope.$index)"></el-button>
    </template>
  </el-table-column>
</el-table>

至於表單數據的綁定,在 <el-table-column><template> 元素中能夠定義一個 slot-scope 屬性(這裏,該屬性被定義爲 "scope")。通過這樣的設置以後,就能夠經過 scope.$index 獲得該行的索引,經過 scope.row 得到該行的元素,表單數據綁定就比較容易了。至於添加和刪除表單項,就經過對 shoppingList.items 進行 pushsplice 來實現(參見完整代碼)。數據結構

3. 表單驗證時填寫正確的 prop 屬性

官方文檔中,表單驗證既能夠在 Form 上傳遞全部的 rules,也能夠在單個表單域上傳遞驗證規則。但在動態增減的表單項中進行驗證,須要十分注意設置正確的 prop 屬性。既然時動態增減的表單項,那麼這個 prop 應該也是動態的,因而咱們使用 v-bind 指令(簡寫爲 :)進行綁定,如下是一個例子:app

<el-table-column label="商品名">
  <template slot-scope="scope">
    <el-form-item :prop="'items.' + scope.$index + '.name'" 
                  :rules="[{ required: true, message: '請輸入商品名稱', trigger: 'blur' }]">
      <el-input v-model="scope.row.name"></el-input>
    </el-form-item>
  </template>
</el-table-column>

上一節中咱們知道 scope.$index 能夠訪問到該行數據對應的索引,因而就能夠經過 :prop="'items.' + $index + '.name'" 進行綁定。注意這裏不能寫 :prop="scope.row.name",也不能省略冒號——前者會致使驗證規則不起做用,後者會在運行中給出警告,要求填寫正確的 prop 值。至於爲何必定要這種寫法,我的認爲能夠類比到 Java 中遍歷數組元素的兩種方式ide

// 方式一
for (int i = 0; i < items.length; i++) {
    // 遍歷操做
}
// 方式二
for (Item item : items) {
    // 遍歷操做
}

對於方式二來講,item 在遍歷過程當中是會變化的,沒法經過它惟一肯定一條記錄,而下標能夠。對於動態增減的表單項,確定要把一個驗證規則應用到全部表單項,同時又要區分哪一個項驗證經過,哪一個項驗證不經過,在這種要求下,天然用下標定位成爲了避免二之選。ui

總結

以上爲我在這兩天的頁面開發中遇到的一些坑點和要點,有任何問題或者其它須要商討的點能夠在評論區留言。

附:極簡購物清單的完整代碼

<template>
  <div id="app">
    <h2>A simple shopping list.</h2>
    <el-form :model="shoppingList" label-width="100px" size="mini">
      <el-form-item prop="supermarket" label="超市" 
                    :rules="[{ required: true, message: '請輸入超市名稱', trigger: 'blur' }]">
        <el-input v-model="shoppingList.supermarket"></el-input>
      </el-form-item>
      <el-form-item prop="status" label="狀態">
        <el-radio v-model="shoppingList.status" :label="true">啓用</el-radio>
        <el-radio v-model="shoppingList.status" :label="false">禁用</el-radio>
      </el-form-item>
      <el-divider></el-divider>
      <el-form-item prop="items" label="購物清單">
        <el-button type="text" icon="el-icon-plus" @click="addItem">添加</el-button>
        <el-table :data="shoppingList.items">
          <el-table-column type="index"></el-table-column>
          <el-table-column label="商品名">
            <template slot-scope="scope">
              <el-form-item :prop="'items.' + scope.$index + '.name'" 
                            :rules="[{ required: true, message: '請輸入商品名稱', trigger: 'blur' }]">
                <el-input v-model="scope.row.name"></el-input>
              </el-form-item>
            </template>
          </el-table-column>
          <el-table-column label="數量">
            <template slot-scope="scope">
              <el-form-item :prop="'items.' + scope.$index + '.quantity'" 
                            :rules="[{ required: true, message: '請輸入商品數量' }, { type: 'number', message: '只能輸入數字' }]">
                <el-input v-model="scope.row.quantity"></el-input>
              </el-form-item>
            </template>
          </el-table-column>
          <el-table-column>
            <template slot-scope="scope">
              <el-button type="danger" size="mini" icon="el-icon-delete" @click="removeItem(scope.$index)"></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-button type="primary" @click="saveList">Submit!</el-button>
    </el-form>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      shoppingList: {
        supermarket: '',
        status: true,
        items: [
          {
            name: '',
            quantity: 0
          }
        ]
      }
    }
  },
  methods: {
    addItem () {
      this.shoppingList.items.push({ name: '', quantity: 0 })
    },
    removeItem (index) {
      this.shoppingList.items.splice(index, 1)
    },
    saveList () {
      console.log('購物列表爲:' + JSON.stringify(this.shoppingList))
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
相關文章
相關標籤/搜索