element plus el-form双列布局及拓展任意布局

news2024/11/24 12:39:55

1 场景

一般表单我们直接默认布局,也就是单列布局,突然有个人员信息表单,需要双列布局的需求,简单实现并拓展下

2 思路

直接无脑div+flex布局实现

3 代码

<template>
  <el-form ref="formRef" :model="formData" label-width="80px">
    <div class="form-top">
      <div class="form-top--left">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="formData.name" placeholder="请输入姓名" />
        </el-form-item>
        <el-form-item label="年龄" prop="age">
          <el-input v-model="formData.age" placeholder="请输入年龄" />
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-radio-group v-model="formData.sex">
            <el-radio :label="1"></el-radio>
            <el-radio :label="2"></el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="formData.email" placeholder="请输入邮箱" />
        </el-form-item>

        <el-form-item label="排序" prop="sort" placeholder="请输入排序号">
          <el-input-number v-model="formData.sort" :min="1" />
        </el-form-item>
      </div>
      <div class="form-top--right">
        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="formData.remark"
            type="textarea"
            placeholder="请输入备注"
            maxlength="100"
            show-word-limit
            resize="none"
          />
        </el-form-item>
        <el-form-item label="说明" prop="config">
          <el-input
            v-model="formData.config"
            placeholder="请输入说明"
            type="textarea"
            show-word-limit
            maxlength="200"
            :autosize="{ minRows: 6, maxRows: 6 }"
          />
        </el-form-item>
      </div>
    </div>
    <div class="form-bottom">
      <el-form-item>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
        <el-button type="warning" @click="handleClose">取 消</el-button>
      </el-form-item>
    </div>
  </el-form>
</template>

<script setup lang="ts">
const formRef = ref();

const formData = reactive({
  remark: "",
  age: 10,
  config: "",
  email: "",
  sex: "",
  id: null,
  name: "",
  sort: 0,
});

const handleClose = () => {};
const handleSubmit = () => {};
</script>
<style lang="scss" scoped>
.container {
  width: 600px;
  margin-top: 100px;
  .form-top {
    display: flex;
    justify-content: space-between;
    .form-top--right {
      flex: 1;
    }
  }
  .form-bottom {
    display: flex;
    justify-content: flex-end;
  }
}
</style>

在这里插入图片描述

这样的无脑实现实在是对不起付出的时间,不嫩复用是最大问题

4 拓展

封装el-form,增加slot

// Form.vue

<template>
  <el-form>
    <slot></slot>
    <div class="form-top" v-if="!slot.default">
      <div class="form-top--left" v-if="slot.left">
        <slot name="left"></slot>
      </div>
      <div class="form-top--right" v-if="slot.right">
        <slot name="right"></slot>
      </div>
    </div>
    <div class="form-bottom" v-if="slot.bottom">
      <slot name="bottom"></slot>
    </div>
  </el-form>
</template>

<script setup lang="ts">
const slot = useSlots();
</script>
<style lang="scss" scoped>
.form-top {
  display: flex;
  justify-content: space-between;
  .form-top--left {
    flex: 1;
  }
  .form-top--right {
    flex: 1;
  }
}
.form-bottom {
  display: flex;
  justify-content: flex-end;
}
</style>

// index.vue

<template>
  <Form ref="formRef" :model="formData" label-width="80px">
    <template #left>
      <el-form-item label="姓名" prop="name">
        <el-input v-model="formData.name" placeholder="请输入姓名" />
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <el-input v-model="formData.age" placeholder="请输入年龄" />
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="formData.sex">
          <el-radio :label="1"></el-radio>
          <el-radio :label="2"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="formData.email" placeholder="请输入邮箱" />
      </el-form-item>

      <el-form-item label="排序" prop="sort" placeholder="请输入排序号">
        <el-input-number v-model="formData.sort" :min="1" />
      </el-form-item>
    </template>
    <template #right>
      <el-form-item label="备注" prop="remark">
        <el-input
          v-model="formData.remark"
          type="textarea"
          placeholder="请输入备注"
          maxlength="100"
          show-word-limit
          resize="none"
        />
      </el-form-item>
      <el-form-item label="说明" prop="config">
        <el-input
          v-model="formData.config"
          placeholder="请输入说明"
          type="textarea"
          show-word-limit
          maxlength="200"
          :autosize="{ minRows: 6, maxRows: 6 }"
        />
      </el-form-item>
    </template>
    <template #bottom>
      <el-form-item>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
        <el-button type="warning" @click="handleClose">取 消</el-button>
      </el-form-item>
    </template>
  </Form>
</template>

<script setup lang="ts">
import Form from "./Form.vue";
const formRef = ref();

//添加人员表单
const formData = reactive({
  remark: "",
  age: 10,
  config: "",
  email: "",
  sex: "",
  id: null,
  name: "",
  sort: 0,
});

const handleClose = () => {};
const handleSubmit = () => {};
</script>
<style lang="scss" scoped>
.form-top {
  display: flex;
  justify-content: space-between;
  .form-top--right {
    flex: 1;
  }
}
.form-bottom {
  display: flex;
  justify-content: flex-end;
}
</style>

依然不够通用,因为布局是固定的,如果想要其他布局,要么修改Form.vue,要么重新封装

5 继续拓展

抽出layout,形成Layout.vue组件,拿出祖传技艺slot传递
// Layout.vue

<template>
  <div>
    <slot></slot>
    <div class="form-top" v-if="!slot.default">
      <div class="form-top--left" v-if="slot.left">
        <slot name="left"></slot>
      </div>
      <div class="form-top--right" v-if="slot.right">
        <slot name="right"></slot>
      </div>
    </div>
    <div class="form-bottom" v-if="slot.bottom">
      <slot name="bottom"></slot>
    </div>
  </div>
</template>

<script setup lang="ts">
const slot = useSlots();
</script>
<style lang="scss" scoped>
.form-top {
  display: flex;
  justify-content: space-between;
  .form-top--left {
    flex: 1;
  }
  .form-top--right {
    flex: 1;
  }
}
.form-bottom {
  display: flex;
  justify-content: flex-end;
}
</style>

// Form.vue

<template>
  <el-form>
    <Layout>
      <template v-for="item in Object.keys(slot)" :key="item" #[item]>
        <slot :name="item"></slot>
      </template>
    </Layout>
  </el-form>
</template>

<script setup lang="ts">
import Layout from "./Layout.vue";
const slot = useSlots();
</script>
<style lang="scss" scoped></style>

// index.vue

<template>
  <Form ref="formRef" :model="formData" label-width="80px">
    <template #left>
      <el-form-item label="姓名" prop="name">
        <el-input v-model="formData.name" placeholder="请输入姓名" />
      </el-form-item>
      <el-form-item label="年龄" prop="age">
        <el-input v-model="formData.age" placeholder="请输入年龄" />
      </el-form-item>
      <el-form-item label="性别" prop="sex">
        <el-radio-group v-model="formData.sex">
          <el-radio :label="1"></el-radio>
          <el-radio :label="2"></el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="邮箱" prop="email">
        <el-input v-model="formData.email" placeholder="请输入邮箱" />
      </el-form-item>

      <el-form-item label="排序" prop="sort" placeholder="请输入排序号">
        <el-input-number v-model="formData.sort" :min="1" />
      </el-form-item>
    </template>
    <template #right>
      <el-form-item label="备注" prop="remark">
        <el-input
          v-model="formData.remark"
          type="textarea"
          placeholder="请输入备注"
          maxlength="100"
          show-word-limit
          resize="none"
        />
      </el-form-item>
      <el-form-item label="说明" prop="config">
        <el-input
          v-model="formData.config"
          placeholder="请输入说明"
          type="textarea"
          show-word-limit
          maxlength="200"
          :autosize="{ minRows: 6, maxRows: 6 }"
        />
      </el-form-item>
    </template>
    <template #bottom>
      <el-form-item>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
        <el-button type="warning" @click="handleClose">取 消</el-button>
      </el-form-item>
    </template>
  </Form>
</template>

<script setup lang="ts">
import Form from "./Form.vue";
const formRef = ref();

//添加人员表单
const formData = reactive({
  remark: "",
  age: 10,
  config: "",
  email: "",
  sex: "",
  id: null,
  name: "",
  sort: 0,
});

const handleClose = () => {};
const handleSubmit = () => {};
</script>
<style lang="scss" scoped>
.form-top {
  display: flex;
  justify-content: space-between;
  .form-top--right {
    flex: 1;
  }
}
.form-bottom {
  display: flex;
  justify-content: flex-end;
}
</style>

6 总结

  1. 布局和数据分离

  2. 灵活扩展layout

    2.1 可以建立多个layout文件,批量引入(或动态引入)Form.vue中 ,Form.vue中利用动态组件component加载各个layout文件

    2.2 可以建立多个layout文件,批量引入(或动态引入)LayoutIndex.vue文件中,LayoutIndex.vue文件利用动态组件component加载各个layout文件,然后Form.vue中只渲染LayoutIndex,同时通过传参决定渲染那个layout

  3. 新增layout时,只需要新增文件(所有layout文件已经被批量引入<或动态引入>),符合“开闭”原则

tip:

批量引入(vite):import.meta.glob(‘./layout/**/*.vue’);

动态引入:defineAsyncComponent(() => import(./components/${layoutName}.vue));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1372919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Mysql】InnoDB 引擎中的页目录

一、页目录和槽 现在知道记录在页中按照主键大小顺序串成了单链表。 那么我使用主键查询的时候&#xff0c;最顺其自然的办法肯定是从第一条记录&#xff0c;也就是 Infrimum 记录开始&#xff0c;一直向后找&#xff0c;只要存在总会找到。这种在数据量少的时候还好说&#x…

Federated Unlearning for On-Device Recommendation

WSDM 2023 CCF-B Federated Unlearning for On-Device Recommendation 本文工作的主要介绍 本文主要介绍了一种名为FRU&#xff08;Federated Recommendation Unlearning&#xff09;的联邦学习框架&#xff0c;用于在设备端的推荐系统中实现用户数据的有效擦除和模型重建。…

Web 缓存代理—— Nginx、CDN

代理的工作机制 代替客户机向网站请求数据&#xff0c;从而可以隐藏用户的真实IP地址。将获得的网页数据&#xff08;静态 Web 元素&#xff09;保存到缓存中并发送给客户机&#xff0c;以便下次请求相同的数据时快速响应。 代理服务器的概念 代理服务器是一个位于客户端和原始…

Kafka之集群搭建

1. 为什么要使用kafka集群 单机服务下&#xff0c;Kafka已经具备了非常高的性能。TPS能够达到百万级别。但是&#xff0c;在实际工作中使用时&#xff0c;单机搭建的Kafka会有很大的局限性。 ​ 消息太多&#xff0c;需要分开保存。Kafka是面向海量消息设计的&#xff0c;一个T…

徐怀钰巡演将开启,巡回22城上演全民金曲盛宴

1月10日下午&#xff0c;天后徐怀钰空降成都&#xff0c;现身“徐怀钰2024倒数3秒巡回演唱会”新闻发布会&#xff0c;在行业大咖、百余名歌迷的陪伴与在线数万直播观众的见证下&#xff0c;正式揭晓22座巡演城市&#xff0c;宣告巡演璀璨开启。主办方今夕何夕文化表示&#xf…

系列十、Java中的八种基本数据类型

一、Java中的八种基本数据类型 1.1、概览 1.2、备注 byte最大值&#xff1a;127 ,byte最小值&#xff1a;-128 short最大值&#xff1a;32767 ,short最小值&#xff1a;-32768 int最大值&#xff1a;2147483647 ,int最小值&#xff1a;-2147483648 long最大值&#xff1a;9…

云上攻防--云原生Docker逃逸--特权逃逸--危险挂载--漏洞逃逸

云上攻防–云原生&&Docker逃逸–特权逃逸–危险挂载–漏洞逃逸 目录标题 云上攻防--云原生&&Docker逃逸--特权逃逸--危险挂载--漏洞逃逸Docker介绍判断Docker环境容器逃逸-特权模式容器逃逸-危险挂载挂载DockerSocket逃逸挂载宿主机procfs逃逸 容器逃逸-Docker…

【前端素材】bootstrap4实现在线蛋糕甜品店网页Tehzeeb

一、需求分析 在线蛋糕甜品店的网站通常包含以下几个方面的内容和功能&#xff1a; 主页&#xff1a;网站的主页是用户进入网站的第一个页面&#xff0c;通常会展示一些精选蛋糕和甜品的图片和介绍&#xff0c;以吸引用户的注意力。主页还可能包含一些特别促销或最新的产品信息…

Matlab 分段函数(piecewise)

语法 pw piecewise(cond1,val1,cond2,val2,...) pw piecewise(cond1,val1,cond2,val2,...,otherwiseVal)描述 pw piecewise(cond1,val1,cond2,val2,...) 返回分段表达式或函数pw&#xff0c;当cond1为True时&#xff0c;其值为val1&#xff0c;当cond2为True时&#xff0…

超维空间M1无人机使用说明书——61、ROS无人机yolo识别与投放

引言&#xff1a;使用yolo进行物体识别&#xff0c;根据返回的目标位置信息&#xff0c;控制无人机全向移动&#xff0c;当无人机到达目标物的正上方&#xff0c;满足一定的误差阈值后&#xff0c;ROS发布控制控制将舵机挂载的物体抛下&#xff0c;紧接着无人机前往起飞点上方寻…

Java中异常处理-详解

异常&#xff08;Exception&#xff09; JVM 默认处理方案 把异常的名称&#xff0c;异常的原因&#xff0c;及异常出错的位置等信息输出在控制台程序停止执行 异常类型 编译时异常必须显示处理&#xff0c;否则程序会发生错误&#xff0c;无法通过编译运行时异常无需显示处理…

灵活实现主题切换 —— 白天、黑夜等主题

1、上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><style>/* 默认的CSS变量集合 */:root {--pr…

光伏方案设计有什么注意点?

光伏方案设计是实现光伏发电系统高效运行的关键环节。在进行光伏方案设计时&#xff0c;有几个重要的注意点需要特别关注。 首先&#xff0c;要充分考虑地理位置和气候条件。不同地区的日照时数、太阳辐射强度和日照角度都有所不同&#xff0c;这些因素直接影响光伏发电系统的发…

85.乐理基础-记号篇-力度记号

内容来源于&#xff1a;三分钟音乐社 上一个内容&#xff1a;78.乐理基础-非常见拍号如何打拍子-CSDN博客 85-78之间的内容观看索引&#xff1a; 腾讯课堂-三分钟音乐社-打拍子&#xff08;20&#xff09;-总结、重点、练习与检验方法开始看 力度记号&#xff1a;p、f、mp、…

网络协议攻击与模拟_02ARP协议

一、arp协议简介 一个工作在二层的三层协议&#xff0c;事一个2.5层协议 ARP协议地址解析协议&#xff0c;将一个已知的Ip地址解析为MAC地址&#xff0c;从而进行二层数据交互 二、工作流程 1、两个阶段 ARP请求ARP响应 两台主机IP地址主机A和主机B&#xff0c;IP地址和MAC…

2024年AI红利:抓住AI内容写作、绘画、数字人、等四大变现机遇

2023年见证了人工智能大模型的爆发&#xff0c;其影响力超出了科技界范畴&#xff0c;成为推动社会进步的重要力量。大模型的突破性进展引起了全球关注&#xff0c;被视为科技发展4.0时代的革命性创新。而每一次革命性创新都是一把双刃剑&#xff0c;随之而来的互联网大裁员事件…

RocketMQ 消费重试

消费者出现异常&#xff0c;消费某条消息失败时&#xff0c; Apache RocketMQ 会根据消费重试策略重新投递该消息进行故障恢复。本文介绍消费重试机制的原理、版本兼容性和使用建议。 一、应用场景​ Apache RocketMQ 的消费重试主要解决的是业务处理逻辑失败导致的消费完整性…

Web开发SpringBoot SpringMVC Spring的学习笔记(包含开发常用工具类)

开发框架学习笔记 一.Spring SpringMVC SpringBoot三者的联系SpringMVC工作原理 二.SpringBoot的学习2.1 注解2.1.1 SpringBoot的核心注解2.1.2 配置导入注解(简化Spring配置写XML的痛苦)Configuration和Bean(人为注册Spring 的 Bean)Import(补)ImportResource(补)AutowiredQua…

盖子的c++小课堂——第二十四讲:差分数组

前言 嗨嗨嗨&#xff0c;这里是盖子的小课堂哟&#xff0c;这次更新主要是因为快放假了&#xff0c;时间多了&#xff0c;好嘞&#xff0c;废话不多说&#xff0c;点赞评论拿来吧你~ 差分数组 一维差分数组 假设给你一个数组 nums &#xff0c;先对区间 [a,b] 中每个元素加…

深兰科技AI医疗健康产品获3000台采购订单

12月6日&#xff0c;武汉某企业与深兰科技签署协议&#xff0c;一次性采购3000台深兰科技AI生理健康检测仪——扁鹊。 深兰科技AI生理健康检测仪——扁鹊是深兰科技推出的人体生理指标检测产品。基于AI生物技术、融合互联网医疗及AIoT技术&#xff0c;深兰科技AI生理健康检测仪…