亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前置知識(shí)點(diǎn)

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

Component

vue 提供了一個(gè)內(nèi)置組件 Component,用來動(dòng)態(tài)渲染組件,舉個(gè)例子,本篇文章以Element UI 為例,假設(shè)我們?nèi)肿粤?code>Element UI的組件,那么下面一段代碼

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

將被渲染為el-input組件。

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

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

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

$attrs

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

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

這是我們 schema form 變得好用的第二個(gè)重要的知識(shí)點(diǎn)。

$listeners

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

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

表單的結(jié)構(gòu)是什么樣的

1、我可能希望對(duì)表單進(jìn)行一部分特殊的處理,所以,包一層div總是沒錯(cuò)的,當(dāng)然,這是我的習(xí)慣,你們可以自行選擇。

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

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

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

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

6、最后才是渲染對(duì)應(yīng)的組件

那么,一個(gè)表單的結(jié)構(gòu)化雛形就完成了。

<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>
                        渲染對(duì)應(yīng)組件,但需要對(duì)某些組件特殊處理
                    </template>
                </el-form-item>
            </el-col>
        </el-row>
    </el-form>
</div>

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

配置數(shù)組數(shù)據(jù)結(jié)構(gòu)

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

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

3、el-col項(xiàng)可能有時(shí)不顯示,所以config上擴(kuò)展一個(gè)字段hidden,用于控制該項(xiàng)是否顯示。

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

5、innerText的樣式定義

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

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

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

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

<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;
    }
  }
};

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

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

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

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

生成這樣一個(gè)常用的篩選項(xiàng)表單

<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: '關(guān)鍵字',
          props: {
            placeholder: '標(biāo)題/創(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ā)布時(shí)間:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '請選擇開始時(shí)間',
            endPlaceholder: '請選擇結(jié)束時(shí)間'
          }
        },
        {
          key: 'createTime',
          component: 'el-date-picker',
          label: '創(chuàng)建時(shí)間:',
          span: 8,
          props: {
            clearable: true,
            valueFormat: 'timestamp',
            type: 'datetimerange',
            defaultTime: ['00:00:00', '23:59:59'],
            rangeSeparator: '-',
            startPlaceholder: '請選擇開始時(shí)間',
            endPlaceholder: '請選擇結(jié)束時(shí)間'
          }
        },
        {
          component: 'slot',
          slotName: 'search',
          span: 8,
          labelWidth: '0'
        }
      ];
    }
  }
}
</script>

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

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

結(jié)語

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

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

相關(guān)文章

最新評(píng)論