欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue2 Element Schema Form 配置式生成表單的實現(xiàn)

 更新時間:2022年05月23日 10:25:14   作者:woodenF  
本文主要介紹了Vue2 Element Schema Form 配置式生成表單的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前置知識點

為了實現(xiàn)一個Schema Form配置式表單的生成,需要了解一部分前置知識點。

Component

vue 提供了一個內置組件 Component,用來動態(tài)渲染組件,舉個例子,本篇文章以Element UI 為例,假設我們全局注冊了Element UI的組件,那么下面一段代碼

<Component is="el-input"></Component>

將被渲染為el-input組件。

好了,最重要的實現(xiàn)知識點已經完了,只要了解了這一點,我這個Schema Form的實現(xiàn)思路,你就能完全看懂了,就這么簡單。

但是為了我們表單的易用性,我們再了解一點兒其他的。

比如Component組件并非只能接收一個字符串,渲染全局組件,同時可以接收一個Component組件,也就是說,當我們Element UI 組件沒有全局注冊的時候,我們可以通過import { ElInput } from 'element',傳遞給Component組件,同樣可以完成渲染一個el-input組件的功能。

$attrs

第二個知識點,vue屬性透傳,假如你有這么一個疑惑 —— 我對el-input進行了二次封裝,那el-input接收的props我是否需要在二次封裝的組件中進行props的定義,再逐一傳遞給el-input才能生效。

如果有這樣的疑惑那么$attrs可以幫你,對于二次封裝的組件,通過定義v-bind="$attrs",傳遞給父組件的屬性即可透傳給el-input,于是就有了這么一個疑問,$attrs可以綁定給v-bind,那么一個普通的對象可以嗎,答案是可以的。

這是我們 schema form 變得好用的第二個重要的知識點。

$listeners

$attrs 相同,做事件透傳的,通過v-on綁定。

以上就是我認為,實現(xiàn)Schema Form配置式生成表單所需要掌握的全部知識及擴展思考,接下來,我們簡單完成一個配置式表單.

表單的結構是什么樣的

1、我可能希望對表單進行一部分特殊的處理,所以,包一層div總是沒錯的,當然,這是我的習慣,你們可以自行選擇。

2、既然是表單,那一定被el-form包裹。

3、為了配置式布局的需要,我希望引入el-row el-col柵格系統(tǒng)

4、無論如何完善表單,必然不可能滿足所有要求,那最簡單的方式就是拋出slot

5、有些時候我希望渲染文本呢?有些時候我希望渲染字段的值而不涉及任何組件呢?

6、最后才是渲染對應的組件

那么,一個表單的結構化雛形就完成了。

<div class="schema-form">
    <el-form>
        <el-row>
            <el-col v-for="item in config" :key="item.key">
                <el-form-item>
                    <slot v-if="item.component === 'slot'" :name="item.slotName"></slot>
                    <div v-else-if="item.component === 'innerText'"></div>
                    <template v-else>
                        渲染對應組件,但需要對某些組件特殊處理
                    </template>
                </el-form-item>
            </el-col>
        </el-row>
    </el-form>
</div>

從上面的結構中,我們再來思考,我們的配置config數(shù)組的字段結構應該是什么樣的。

配置數(shù)組數(shù)據(jù)結構

1、el-form 可能需要一些字段注入,作為最外層的組件,將傳入schema form的字段都給它

2、el-form 需要傳入一個數(shù)據(jù)源,這個數(shù)據(jù)源可以內部定義再傳給外部,也可以傳入一個對象,利用對象的特性做雙向綁定,我選擇了后者

3、el-col項可能有時不顯示,所以config上擴展一個字段hidden,用于控制該項是否顯示。

4、el-form-item的屬性透傳

5、innerText的樣式定義

一些特殊的描述出來了,其余的再贅述,那么,config的數(shù)據(jù)結構就是這樣

{
    key: '', // 當前字段的 key 值,同時會傳到 el-form-item 的prop,不傳數(shù)據(jù)驗證和重置會失效
    label: '', // 當前 el-form-item 的label
    hidden: '', // 當前表單項是否展示
    labelWidth: '', // el-form-item 的label寬度
    component: '', // 支持 slot、innerText、Component,渲染成什么
    slotName: '', // compoment 為 slot 時,該值為對應slot的名字供外部使用
    innerClass: '', // component 為 innerText 時,給文本的樣式,通常為全局樣式
    innerStyle: '', // 同上
    innerText: '', // component 為 innerText 時,優(yōu)先顯示的文本,否則會顯示當前的字段值
    itemProps: '', // 注入到 el-form-item 的屬性
    props: '', // 當 component 為渲染組件時,注入到渲染組件當中的屬性
    listeners: '', // 當 component 為渲染組件時,注入到渲染組件當中的事件
}

當把這些實現(xiàn)之后,其余需要擴展的功能可以自行實現(xiàn),我這里也只是在業(yè)務中的擴展,并非完善的。

于是,我們的表單組件就變成了這樣

<template>
  <div class="nx-form">
    <el-form
      ref="form"
      v-bind="$attrs"
      :model="source"
      class="nx-form"
    >
      <el-row :gutter="20">
        <el-col
          v-for="item in config"
          :key="item.key"
          :span="item.hidden ? 0 : item.span || 8"
        >
          <el-form-item
            v-if="!item.hidden"
            :label="item.label"
            :prop="item.key"
            :label-width="item.labelWidth || labelWidth || '120px'"
            v-bind="item.itemProps"
          >
            <slot v-if="item.component === 'slot'" :name="item.slotName"></slot>
            <div
              v-else-if="item.component === 'innerText'"
              :class="item.innerClass"
              :style="item.style"
            >
              {{ item.innerText || source[item.key] }}
            </div>
            <template v-else>
              <div class="nx-flex-align-center">
                <component
                  :is="item.component"
                  v-model="source[item.key]"
                  style="width: 100%;flex: 1;"
                  v-bind="item.props"
                  v-on="item.listeners"
                >
                  <template v-if="item.component === 'el-radio-group'">
                    <el-radio
                      v-for="(radio, radioIndex) in item.data"
                      :key="radioIndex"
                      style="margin-top: 10px;"
                      :label="radio.value"
                      :disabled="radio.disabled"
                    >
                      {{ radio.label }}
                    </el-radio>
                  </template>

                  <template v-if="item.component === 'el-checkbox-group'">
                    <el-checkbox
                      v-for="(checkbox, checkboxIndex) in item.data"
                      :key="checkboxIndex"
                      :label="checkbox.value"
                    >
                      {{ checkbox.label }}
                    </el-checkbox>
                  </template>

                  <template v-if="item.component === 'el-select'">
                    <el-option
                      v-for="(option, optionIndex) in item.data"
                      :key="optionIndex"
                      :label="option.label"
                      :value="option.value"
                    ></el-option>
                  </template>
                </component>
                <div
                  v-if="item.after"
                  class="nx-form__after"
                >
                  {{ item.after }}
                </div>
              </div>
              <div
                v-if="item.tips"
                class="nx-form__tips"
                v-html="item.tips"
              ></div>
            </template>

          </el-form-item>
          <!-- <div
            v-if="item.tips"
            :style="{ marginLeft: item.labelWidth || '120px' }"
            class="nx-form__tips"
            v-html="item.tips"
          ></div> -->
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>
export default {
  name: 'NxForm',
  components: {},
  props: {
    config: {
      type: Array,
      default: () => []
    },
    source: {
      type: Object,
      default: () => ({})
    }
  },
  methods: {
    resetFields() {
      this.$refs.form.resetFields();
    },
    clearValidate() {
      this.$refs.form.clearValidate();
    },
    async validate() {
      const valid = await this.$refs.form.validate();
      return valid;
    }
  }
};

可以看到,我擴展了一個data字段,用來作為el-select el-checkbox-group el-radio-group的數(shù)據(jù)源,這些特殊的組件單獨列出就行了,基本上也之后有這么幾個。

methods里也只是為了方便添加了一些常用的form方法,基本不做邏輯處理。

現(xiàn)在看一下,這樣的配置可以生成怎樣的表單

注意:我這里定義了一部分全局樣式,比如在schema form下的組件,全部占滿整格,使其比較美觀。

生成這樣一個常用的篩選項表單

<template>
  <div>
    <nx-form
      ref="searchForm"
      :source="searchForm"
      :config="searchConfig"
    >
      <div slot="search">
        <el-button type="primary" @click="$refs.nxTable.search(1)">查詢</el-button>
        <el-button @click="reset()">重置</el-button>
      </div>
    </nx-form>
  </div>
</template>
<script>
export default {
  data() {
     searchForm: {
        keyWord: '', 
        newsType: '', 
        newsStatus: '', 
        publishTime: [],
        createTime: []
     },
  },
  computed: {
      searchConfig() {
      return [
        {
          key: 'keyWord',
          component: 'el-input',
          span: 8,
          label: '關鍵字',
          props: {
            placeholder: '標題/創(chuàng)建人',
            clearable: true
          }
        },
        {
          key: 'newsType',
          component: 'el-select',
          span: 8,
          label: '類型:',
          props: {
            placeholder: '請選擇',
            clearable: true
          },
          data: this.newsTypes
        },
        {
          key: 'newsStatus',
          component: 'el-select',
          span: 8,
          label: '狀態(tài):',
          props: {
            placeholder: '請選擇',
            clearable: true
          },
          data: statusTypes
        },
        {
          key: 'publishTime',
          component: 'el-date-picker',
          label: '發(fā)布時間:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '請選擇開始時間',
            endPlaceholder: '請選擇結束時間'
          }
        },
        {
          key: 'createTime',
          component: 'el-date-picker',
          label: '創(chuàng)建時間:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '請選擇開始時間',
            endPlaceholder: '請選擇結束時間'
          }
        },
        {
          component: 'slot',
          slotName: 'search',
          span: 8,
          labelWidth: '0'
        }
      ];
    }
  }
}
</script>

其余的找了一些,也沒啥特別的,就不貼了,簡單來說,這個百來行的組件,應用在多個大型項目當中,易用性,擴展性,沒有出現(xiàn)什么問題,配合我們自定義的其他table組件、dialog組件,十分鐘就可以實現(xiàn)一個完整的B端增刪改查。

值得一提的是,為了表單的易用性,我們基本上所有的自定義組件都支持了使用v-model做數(shù)據(jù)綁定,達到簡單易用的效果。

結語

代碼是找了一個很久的項目寫的一個思路,之后的項目中都有改進優(yōu)化,大致只是分享一個思路,如果有什么想法的,歡迎指正。

 到此這篇關于Vue2 Element Schema Form 配置式生成表單的實現(xiàn)的文章就介紹到這了,更多相關Vue2 Element Schema Form生成表單內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論