最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue2實(shí)現(xiàn)封裝動(dòng)態(tài)表單組件

 更新時(shí)間:2022年08月14日 08:23:23   作者:悟空和大王???????  
這篇文章主要介紹了vue2實(shí)現(xiàn)封裝動(dòng)態(tài)表單組件,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

封裝組件注意點(diǎn)

  • 不要為了封裝而封裝
  • 只封裝不變的部分,將變化的部分通過slot或其他方式,暴露出去,交給調(diào)用者實(shí)現(xiàn)
  • 為了提供封裝組件的復(fù)用率,優(yōu)先封裝為UI組件,而不是封裝為業(yè)務(wù)組件(即:封裝組件內(nèi)部使用到的數(shù)據(jù),都通過prop獲取,而不是直接通過ajax請(qǐng)求或vuex中獲?。?/li>

動(dòng)態(tài)表單動(dòng)態(tài)控制的是什么?

已知的需要?jiǎng)討B(tài)控制的場(chǎng)景:

  • 在A界面顯示:A, B, C三個(gè)表單項(xiàng),B界面顯示:A,B,E,F三個(gè)表單項(xiàng)
  • 在A界面默認(rèn)顯示:A,B兩個(gè)表單項(xiàng),當(dāng)A項(xiàng)的值為x時(shí),C表單項(xiàng)才顯示出來
  • 在A界面默認(rèn)顯示:A,B,C三個(gè)表單項(xiàng),A,B默認(rèn)可用,C默認(rèn)禁用,當(dāng)A項(xiàng)的值為x時(shí),C表單項(xiàng)才可用
  • 在A界面B表單項(xiàng)可選擇的值,依賴于A表單項(xiàng)的選擇/填寫結(jié)果
  • 根據(jù)不同的分辨率每行可顯示的表單項(xiàng)數(shù)量不同

動(dòng)態(tài)表單封裝

請(qǐng)優(yōu)先考慮風(fēng)格二的封裝方式

風(fēng)格一

特點(diǎn)簡(jiǎn)介

將el-form, el-form-item, el-input等等完全封裝到動(dòng)態(tài)表單組件內(nèi),通過for循環(huán)來刷表單項(xiàng),外部通過傳json配置對(duì)象的方式,完成字段的動(dòng)態(tài)顯示/隱藏控制。

優(yōu)點(diǎn):

  • 減少了<el-form-item><el-input></el-input></el-form-item> 這類代碼的重復(fù)編寫
  • 可以輕易的改變表單項(xiàng)的先后順序

缺點(diǎn):

  • 如果所有用到表單的地方,都用這一個(gè)表單組件實(shí)現(xiàn),那么這個(gè)組件后期一定會(huì)變得非常龐大,充斥大量的邏輯控制代碼,導(dǎo)致后期難以維護(hù)
  • 要想最大程度的保留原始表單的配置和事件,那就需要使用v-bind=attrsv-on=evts方式進(jìn)行配置,這相對(duì)于template語法來說,json對(duì)象的配置方式,就沒那么讓vue開發(fā)者習(xí)慣了。
  • 通過v-bind=attrs方式設(shè)置原組件的屬性,那么如果想設(shè)置一些默認(rèn)值就變得麻煩起來,因?yàn)関ue2中,設(shè)置了v-bind=attrs之后,沒法再在模板中設(shè)置默認(rèn)屬性,必須在這個(gè)封裝的組件中,在獲取到配置對(duì)象時(shí),進(jìn)行一些比較繁瑣的初始值設(shè)置。
  • 如果表單model對(duì)象是通過prop傳入,那么表單內(nèi)部修改這個(gè)表單對(duì)象需要做特殊處理,來規(guī)避eslint對(duì)單項(xiàng)數(shù)據(jù)流的檢查報(bào)錯(cuò)

代碼實(shí)現(xiàn)示例

動(dòng)態(tài)表單組件

<template>
  <el-form :model="formModel" v-bind="elFormAttrs">
    <el-form-item
      v-for="(formItemConfig, index) in formItemConfigArr"
      :key="`${formItemConfig.prop}-${index}`"
      :prop="formItemConfig.prop"
      :rules="formItemConfig.rules"
    >
      <template #label>
        <div class="o-custom-label">{{ formItemConfig.label }}</div>
      </template>
      <el-input
        v-if="formItemConfig.itemType === 'input'"
        v-model="formModel[formItemConfig.prop]"
      ></el-input>
      <el-select
        v-else-if="formItemConfig.itemType === 'select'"
        v-model="formModel[formItemConfig.prop]"
      >
        <template v-if="formItemConfig.optionArr">
          <el-option
            v-for="(option, pos) in formItemConfig.optionArr"
            :key="`${option.value}-${pos}`"
            :value="option.value"
            :label="option.label"
          ></el-option>
        </template>
      </el-select>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: "DynForm",
  model: {
    event: "change",
    prop: "formData",
  },
  props: {
    formData: {
      type: Object,
    },
    /**
     * prop: 唯一標(biāo)識(shí)
     * itemType: 表單項(xiàng)類型
     * rules: 表單驗(yàn)證規(guī)則
     * label: 顯示標(biāo)簽
     * optionArr: 下拉值
     */
    formItemConfigArr: {
      type: Array,
      default: () => [],
    },
    // el-form支持的所有屬性
    elFormAttrs: {
      type: Object,
    },
  },
  data() {
    return {
      formModel: this.formData ? this.formData : {},
    };
  },
  watch: {
    // 監(jiān)聽formData改變,將formData的值設(shè)置給組件內(nèi)部的formModel,規(guī)避eslint對(duì)單項(xiàng)數(shù)據(jù)流的規(guī)則檢測(cè)報(bào)錯(cuò)
    formData: {
      handler(newVal) {
        this.formModel = newVal;
      },
    },
  },
  methods: {},
};
</script>
<style scoped></style>

調(diào)用動(dòng)態(tài)表單組件

<template>
  <div class="demo-form">
    <DynForm
      v-model="formData"
      :form-item-config-arr="formItemConfigArr"
      :el-form-attrs="elFormAttrs"
    ></DynForm>
  </div>
</template>

<script>
import DynForm from "@/components/form/dyn/DynForm";
export default {
  name: "FormTemplate3",
  components: {
    DynForm,
  },
  props: {
    // input文本框數(shù)量
    count: {
      type: Number,
      default: 50,
    },
  },
  data() {
    // 表單項(xiàng)配置
    const formItemConfigArr = [
      {
        prop: "sex",
        label: "成語故",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "name",
        label: "姓名",
        itemType: "input",
      },
      {
        prop: "three",
        label: "成語故事",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "four",
        label: "一二三四五",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "five",
        label: "一二三四五六",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "six",
        label: "一二三四五六七",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "seven",
        label: "一二三四五六七八",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "eight",
        label: "一二三四五六七八九",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "ten",
        label: "ten",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "zero",
        label: "zero",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "a",
        label: "hello",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "b",
        label: "hello world",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "c",
        label: "good idea thank",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "d",
        label: "good configuration",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "d",
        label: "good idea thank configuration",
        itemType: "select",
        optionArr: [],
      },
    ];
    return {
      elFormAttrs: {
        inline: true,
        labelWidth: "81px",
      },
      formData: null,
      formItemConfigArr,
    };
  },
  created() {
    this.loadFormData();
    this.loadSexOptions();
  },
  methods: {
    loadFormData() {
      setTimeout(() => {
        this.formData = {
          name: "張三",
          sex: 1,
        };
      }, 1000);
    },
    loadSexOptions() {
      setTimeout(() => {
        const item = this.formItemConfigArr.find((item) => item.prop === "sex");
        if (item) {
          const sexOptionArr = [
            { value: 1, label: "選項(xiàng)1" },
            { value: 2, label: "選項(xiàng)2" },
            { value: 3, label: "選項(xiàng)3" },
          ];
          item.optionArr = sexOptionArr;
        }
      }, 1500);
    },
  },
};
</script>

<style scoped lang="scss">
.js-validate-form ::v-deep(.is-error .o-show-data) {
  color: red;
}
.demo-form ::v-deep(.el-form-item__label) {
  line-height: 1.6;
  display: inline-flex;
  height: 40px;
  justify-items: right;
  justify-content: flex-end;
  align-items: center;
}
.demo-form ::v-deep(.el-form-item__label .o-custom-label) {
  word-break: break-word;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; /* 這里是超出幾行省略 */
  overflow: hidden;
}
</style>

風(fēng)格二 (推薦優(yōu)先采用此風(fēng)格)

特點(diǎn)介紹

通過函數(shù)組件,以jsx語法對(duì)el-form-item進(jìn)行封裝,僅封裝模板代碼部分,動(dòng)態(tài)部分全部由調(diào)用者自行實(shí)現(xiàn)

優(yōu)點(diǎn):

  • 能夠針對(duì)界面特點(diǎn),僅封裝不變的模板代碼部分,能夠最大程度保留template編程風(fēng)格
  • 因?yàn)楸韱雾?xiàng)都是通過slot實(shí)現(xiàn),不會(huì)導(dǎo)致這個(gè)表單組件隨著應(yīng)用的場(chǎng)景增多和變得越來越復(fù)雜,復(fù)雜度會(huì)基本保持不變

缺點(diǎn):

  • 需要掌握jsx語法(jsx僅用于封裝組件,調(diào)用這個(gè)組件使用template語法即可)

代碼實(shí)現(xiàn)示例

表單項(xiàng)組件封裝

<script>
export default {
  functional: true,
  name: "DynFormItemsFunction",
  props: {
    formItemConfigArr: {
      type: Array,
      required: true,
    },
  },
  render(h, context) {
    // console.log(context);
    const { props, scopedSlots } = context;
    const { formItemConfigArr } = props;
    // 獲得插槽里的 vNodes
    const vNodes = scopedSlots.default();
    return vNodes.map((node, idx) => {
      const formItemConfig = formItemConfigArr[idx];
      return (
        <el-form-item prop={formItemConfig.prop} rules={formItemConfig.rules}>
          <span slot="label" className="o-custom-label">
            {formItemConfig.label}
          </span>
          {node}
        </el-form-item>
      );
    });
  },
};
</script>

<style scoped>
.o-custom-label {
  color: blue;
}
</style>

代碼調(diào)用示例

<template>
  <div>
    <el-form :model="formData" inline :validate-on-rule-change="false">
      <!-- DynFormItemsFunction 這個(gè)組件,僅封裝了el-form-item的邏輯 -->
      <DynFormItemsFunction :form-item-config-arr="formItemConfigArrComp">
        <!-- 
        注意組件的循環(huán)是在slot中進(jìn)行的,el-form-item的包裝邏輯,
        交給了DynFormItemsFunction組件實(shí)現(xiàn)
        -->
        <template v-for="(formItemConfig, idx) in formItemConfigArrComp">
          <el-input
            v-if="formItemConfig.itemType === 'input'"
            v-model="formData[formItemConfig.prop]"
            :key="idx"
          ></el-input>
          <el-select
            v-else-if="formItemConfig.itemType === 'select'"
            v-model="formData.sex"
            :key="idx"
          >
            <template v-if="formItemConfig.optionArr">
              <el-option
                v-for="option in formItemConfig.optionArr"
                :key="option.value"
                :value="option.value"
                :label="option.label"
              ></el-option>
            </template>
          </el-select>
        </template>
      </DynFormItemsFunction>
    </el-form>
  </div>
</template>

<script>
import DynFormItemsFunction from "@/components/form/dyn/DynFormItemsFunction";
export default {
  name: "FormTemplate",
  components: {
    DynFormItemsFunction,
  },
  props: {
    count: {
      type: Number,
      default: 50,
    },
  },
  data() {
    /*
    完整的表單配置放在data中,數(shù)據(jù)中的元素個(gè)數(shù)不會(huì)變,
    動(dòng)態(tài)值也填充到formItemConfigArr對(duì)應(yīng)元素中(如性別的下拉選項(xiàng)值),
    formItemConfigArr只需要關(guān)注完整表單需要哪些表單項(xiàng)字段,
    以及下拉選項(xiàng)數(shù)據(jù)的填充,無需考慮表單項(xiàng)字段的顯示/隱藏邏輯控制
    */
    const formItemConfigArr = [
      {
        prop: "sex",
        label: "性別",
        itemType: "select",
        optionArr: [],
      },
      {
        prop: "name",
        label: "姓名",
        itemType: "input",
        rules: [{ required: true, message: "該項(xiàng)必填", trigger: "change" }],
      },
      {
        prop: "school",
        label: "學(xué)校",
        itemType: "input",
        rules: [],
      },
    ];
    // for (let i = 0; i < this.count; i++) {
    //   formItemConfigArr.push({
    //     prop: "name" + i,
    //     label: "姓名" + i,
    //     itemType: "input",
    //   });
    // }
    return {
      formData: {
        name: null,
        sex: null,
        school: null,
      },
      formItemConfigArr,
    };
  },
  computed: {
    /*
    表單項(xiàng)的顯示/隱藏通過計(jì)算屬性實(shí)現(xiàn),可以認(rèn)為計(jì)算屬性就只關(guān)注控制哪些表單項(xiàng)需要顯示,
    哪些需要隱藏,就可以了。算是一種職責(zé)分離
    */
    formItemConfigArrComp() {
      return this.formItemConfigArr.filter((item) => {
        if (this.formData.sex === 3 && item.prop === "name") {
          return null;
        }
        return item;
      });
    },
  },
  created() {
    this.loadOptions(1500);
  },
  methods: {
    loadOptions(timeout) {
      setTimeout(() => {
        const item = this.formItemConfigArr.find((item) => item.prop === "sex");
        if (item) {
          const sexOptionArr = new Array(10)
            .fill(true)
            .map((item, idx) => ({ value: idx, label: "選項(xiàng):" + idx }));
          item.optionArr = sexOptionArr;
        }
      }, timeout);
    },
  },
};
</script>

<style scoped lang="scss">
.js-validate-form ::v-deep(.is-error .o-show-data) {
  color: red;
}
</style>

到此這篇關(guān)于vue2實(shí)現(xiàn)封裝動(dòng)態(tài)表單組件的文章就介紹到這了,更多相關(guān)vue封裝表單組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue 里面使用axios 和封裝的示例代碼

    vue 里面使用axios 和封裝的示例代碼

    本篇文章主要介紹了vue 里面使用axios 和封裝的示例代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-09-09
  • 基于VuePress 輕量級(jí)靜態(tài)網(wǎng)站生成器的實(shí)現(xiàn)方法

    基于VuePress 輕量級(jí)靜態(tài)網(wǎng)站生成器的實(shí)現(xiàn)方法

    VuePress是一個(gè)基于Vue的輕量級(jí)靜態(tài)網(wǎng)站生成器以及為編寫技術(shù)文檔而優(yōu)化的默認(rèn)主題。這么文章給大家詳細(xì)介紹了vuepress 靜態(tài)網(wǎng)站生成器的方法,需要的朋友參考下吧
    2018-04-04
  • vue登錄頁實(shí)現(xiàn)使用cookie記住7天密碼功能的方法

    vue登錄頁實(shí)現(xiàn)使用cookie記住7天密碼功能的方法

    這篇文章主要介紹了vue登錄頁實(shí)現(xiàn)使用cookie記住7天密碼功能的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • 前端實(shí)現(xiàn)不同角色登入展示不同頁面效果實(shí)例

    前端實(shí)現(xiàn)不同角色登入展示不同頁面效果實(shí)例

    要實(shí)現(xiàn)不同角色登錄跳轉(zhuǎn)不同的前端頁面,可以在登錄成功后,根據(jù)用戶的角色信息,使用路由跳轉(zhuǎn)到不同的頁面,這篇文章主要給大家介紹了關(guān)于前端實(shí)現(xiàn)不同角色登入展示不同頁面效果的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • vue封裝axios與api接口管理的完整步驟

    vue封裝axios與api接口管理的完整步驟

    在實(shí)際的項(xiàng)目中,和后臺(tái)的數(shù)據(jù)交互是少不了的,我通常使用的是 axios 庫(kù),所以下面這篇文章主要給大家介紹了關(guān)于vue封裝axios與api接口管理的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • Vue3基礎(chǔ)篇之常用的循環(huán)示例詳解

    Vue3基礎(chǔ)篇之常用的循環(huán)示例詳解

    filter?方法會(huì)創(chuàng)建一個(gè)新的數(shù)組,其中包含滿足指定條件的所有元素,這個(gè)方法非常適合循環(huán)遍歷數(shù)組并根據(jù)特定條件過濾元素的情況,這篇文章主要介紹了Vue3基礎(chǔ)[常用的循環(huán)],需要的朋友可以參考下
    2024-01-01
  • element-ui在table中如何禁用其中幾行

    element-ui在table中如何禁用其中幾行

    這篇文章主要介紹了element-ui在table中如何禁用其中幾行問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • vue實(shí)現(xiàn)彈窗引用另一個(gè)頁面窗口

    vue實(shí)現(xiàn)彈窗引用另一個(gè)頁面窗口

    這篇文章主要介紹了vue實(shí)現(xiàn)彈窗引用另一個(gè)頁面窗口,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue和Flask通信的實(shí)現(xiàn)

    Vue和Flask通信的實(shí)現(xiàn)

    最近新做了個(gè)項(xiàng)目,前端使用的是目前很流行的前端框架,對(duì)于后端,本項(xiàng)目選擇的是比較好上手、輕量級(jí)的python后臺(tái)框架:Flask。感興趣的可以了解一下
    2021-05-05
  • 解決vue axios的封裝 請(qǐng)求狀態(tài)的錯(cuò)誤提示問題

    解決vue axios的封裝 請(qǐng)求狀態(tài)的錯(cuò)誤提示問題

    今天小編就為大家分享一篇解決vue axios的封裝 請(qǐng)求狀態(tài)的錯(cuò)誤提示問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09

最新評(píng)論

鄂托克前旗| 驻马店市| 宣威市| 神农架林区| 许昌市| 治多县| 荃湾区| 含山县| 拉萨市| 梁平县| 扶风县| 军事| 双鸭山市| 漳平市| 星子县| 和林格尔县| 九龙坡区| 湖南省| 抚顺县| 武乡县| 大足县| 黔江区| 桐庐县| 临沧市| 聂拉木县| 广水市| 峡江县| 隆化县| 彭泽县| 焦作市| 巩留县| 民权县| 康保县| 朔州市| 泉州市| 探索| 永川市| 行唐县| 孙吴县| 宣城市| 台中市|