通用vue组件化搜索组件页面

news2025/1/11 6:54:18

一、组件化封装

1.首先创建一个form文件夹,将搜索框组件的内容全部写在这个里面,然后再在需要的页面直接引入相应的组件即可

2.首先先在goods.vue文件里面写对应的文本数组formItems,将所定义的类型IFormItem引用进去,这个里面写的字段都是对应goods.vue文件里面的文本数组formItems里面所拥有的字段

 const formItems: IFormItem[] = [
      {
        field: "id",
        type: "input",
        label: "id",
        placeholder: "请输入账号"
      },
      {
        field: "realname",
        type: "input",
        label: "姓名",
        placeholder: "请输入姓名"
      },
      {
        field: "cellphone",
        type: "input",
        label: "电话号码",
        placeholder: "请输入电话号码"
      }
    ]

 3.然后在form.vue文件里面去判断获取到的prop的数据,也就是父组件goods.vue传给子组件form.vue的formItems,根据里面写的type的类型去进行组件的匹配

form.vue

form.vue

  <el-form label-width="100px">
      <el-row>
        <!--  :key="item.label"动态匹配-->
        <template v-for="item in formItems" :key="item.label">
          <el-col :span="8">
            <!-- 动态匹配label值 -->
            <el-form-item :label="item.label">
               <!-- 动态判断文本框类型,从而去使用对应的element组件 -->
              <template
                v-if="item.type === 'input' || item.type === 'password'"
              >
              <!-- type是文本框 -->
                <el-input
                  :placeholder="item.placeholder"
                  :show-password="item.type === 'password'"
                />
              </template>
              <template v-else-if="item.type === 'select'">
                <!-- type是下拉框 -->
                <el-select :placeholder="item.placeholder" style="width: 100%">
                  <el-option
                    v-for="option in item.options"
                    :key="option.value"
                    :value="option.value"
                    >{{ option.title }}</el-option
                  >
                </el-select>
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
    </el-form>

 4.可以选择在form.vue里面接收相应的样式itemStyle和labelWidth,或者直接在form.vue里面给他们默认值,然后绑定到上面对应的组件上,就能进行响应

 5.一开始可以将所有的itemLayout、formItems、lableWidth和colLayout全部由父组件传给子组件,但是这样的话hy-form组件里面要传的东西就太多了,所以可以考虑把上面这些数据全部放在一个新变量里面,然后给这个新变量定义一个类型,这个类型里面就包括了这些变量值

6.虽然这样一定程度上简化了代码,但是goods.vue文件里面的代码还是太多了,为了更加简便,我们可以把formConfig单独抽离到一个文件里面,然后再在goods.vue里面去引用

search.config.ts

import { IForm } from '@/base-ui/form'
export const searchformConfig: IForm = {
  labelWidth: '120px',
  itemStyle: {
    padding: '10px 40px'
  },
  colLayout: {
    span: 8
  },
  formItems: [
    {
      field: "id",
      type: "input",
      label: "id",
      placeholder: "请输入商品id"
    },
    {
      field: "realname",
      type: "input",
      label: "商品名称",
      placeholder: "请输入商品名称"
    },
    {
      field: "cellphone",
      type: "input",
      label: "商品编号",
      placeholder: "请输入商品编号"
    }
  ]
}

 goods.vue

<template>
  <div class="main">
    <div class="search">
      <!-- <hy-form
        :formItems="formItems"
        :collayout="collayout"
        :lableWidth="lableWith"
        :itemLayout="itemLayout"
      ></hy-form> -->

      <!-- <hy-form v-bind="formConfig"></hy-form> -->
      <hy-form v-bind="searchformConfig"></hy-form>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent } from "vue"
// import HyForm, { IFormItem, IForm } from "@/base-ui/form"
import HyForm from "@/base-ui/form"
import { searchformConfig } from "./config/search.config"

export default defineComponent({
  name: "goods",
  components: {
    HyForm
  },
  setup() {
    // const formItems: IFormItem[] = [
    //   {
    //     field: "id",
    //     type: "input",
    //     label: "id",
    //     placeholder: "请输入账号"
    //   },
    //   {
    //     field: "realname",
    //     type: "input",
    //     label: "姓名",
    //     placeholder: "请输入姓名"
    //   },
    //   {
    //     field: "cellphone",
    //     type: "input",
    //     label: "电话号码",
    //     placeholder: "请输入电话号码"
    //   }
    // ]
    // const labelWidth = "120px"
    // const itemStyle = { padding: "10px 40px" }
    // const collayout = { span: 8 }
    // 简化后的变量
    // const formConfig: IForm = {
    //   formItems: [
    //     {
    //       field: "id",
    //       type: "input",
    //       label: "id",
    //       placeholder: "请输入商品id"
    //     },
    //     {
    //       field: "realname",
    //       type: "input",
    //       label: "商品名称",
    //       placeholder: "请输入商品名称"
    //     },
    //     {
    //       field: "cellphone",
    //       type: "input",
    //       label: "商品编号",
    //       placeholder: "请输入商品编号"
    //     }
    //   ],
    //   labelWidth: "120px",
    //   itemStyle: { padding: "10px 40px" },
    //   collayout: { span: 8 }
    // }
    return {
      // formItems,
      // labelWidth,
      // itemStyle,
      // collayout
      // formConfig
      searchformConfig
    }
  }
})
</script>

二、解决文本框的双向绑定问题

1.可以使用父组件向子组件传参数的办法,首先在一开始封装的formItem里面定义一个字段field,然后再在goods组件上去双向绑定

2.然后在form.vue文件里面,给文本框或下拉框这些动态匹配绑定V-model

goods.vue

search.config.ts

form.vue

 

3.但是这样做的话会有一个弊端,就是直接修改从父组件传过来的数据,一定程度上不是很严谨,所以可以选择将从父组件获取到的数据变量赋值拷贝给另一个变量,然后在form.vue里面去动态监听这个变量是否发生变化,从而去发送监听事件

goods.vue

 

form.vue

 

 三、给搜索框动态绑定一个title标题

1.可以先给form.vue组件一个自定义的插槽

2.然后在之前的formItem数组中再多定义一个字段title

3.最后在引用form.vue组件对应的地方加入一个插槽template,然后动态匹配对应的title字段

 

 四、增加搜索和重置按钮

1、跟前面增加title标题一样的道理,先给form.vue增加一个底部插槽

2.在goods.vue组件对应的位置加一个template,里面对应相应的按钮

 五、组件的封装简化

1.为了使搜索组件能够多次使用,不用重复写代码,可以创建一个page-search文件夹,专门编写搜索组件的代码,这样方便之后直接引用这个组件到相应的页面即可

 简化后的goods.vue

<template>
  <div class="goods">
    <page-search :searchformConfig="searchformConfig"></page-search>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue"
import { searchformConfig } from "./config/search.config"
import PageSearch from "@/components/page-search"

export default defineComponent({
  name: "goods",
  components: {
    PageSearch
  },
  setup() {
    return {
      searchformConfig
    }
  }
})
</script>
<style scoped></style>

 简化后的page-search.vue

<template>
  <div class="page-search">
    <div class="search">
      <!-- <hy-form v-bind="formConfig"></hy-form> -->
      <!-- <hy-form v-bind="searchformConfig" :formData="formData"></hy-form> -->
      <hy-form v-bind="searchformConfig" v-model="formData">
        <!-- 插槽对应form.vue组件里面定义的一个插槽slot,这里的title可以自定义,从serch.config.ts传过来 -->
        <!-- 头部标题插槽 -->
        <template #header>
          <h1>{{ searchformConfig.title }}</h1>
        </template>
        <!-- 底部按钮插槽 -->
        <template #footer>
          <div class="handle-btns">
            <el-button @click="handleResetClick">
              <el-icon> <Refresh /> </el-icon>重置
            </el-button>
            <el-button type="primary" @click="handleQueryClick">
              <el-icon> <Search /> </el-icon>搜索
            </el-button>
            <slot></slot>
          </div>
        </template>
      </hy-form>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue"
import HyForm from "@/base-ui/form"
// import { searchformConfig } from './config/search.config'
import { Search, Refresh } from "@element-plus/icons"

export default defineComponent({
  props: {
    searchformConfig: {
      type: Object,
      required: true
    }
  },
  components: {
    HyForm,
    Search,
    Refresh
  },

  setup(props, { emit }) {
    const formData = ref({
      id: "",
      realname: "",
      cellphone: ""
    })
    return {
      formData
    }
  }
})
</script>
<style scoped>
.handle-btns {
  text-align: right;
  padding: 0 50px 20px 0;
}
</style>

 form.vue文件跟之前的一样

<template>
  <div class="hy-form">
    <div class="header">
      <slot name="header"></slot>
    </div>
    <el-form :label-width="labelWidth">
      <el-row>
        <!--  :key="item.label"动态匹配-->
        <template v-for="item in formItems" :key="item.label">
          <el-col v-bind="collayout">
            <!-- 动态匹配label值 -->
            <el-form-item :label="item.label" :style="itemStyle">
              <!-- 动态判断文本框类型,从而去使用对应的element组件 -->
              <template
                v-if="item.type === 'input' || item.type === 'password'"
              >
                <!-- type是文本框 -->
                <el-input
                  :placeholder="item.placeholder"
                  :show-password="item.type === 'password'"
                  v-model="formData[`${item.field}`]"
                />
              </template>
              <template v-else-if="item.type === 'select'">
                <!-- type是下拉框 -->
                <el-select
                  :placeholder="item.placeholder"
                  style="width: 100%"
                  v-model="formData[`${item.field}`]"
                >
                  <el-option
                    v-for="option in item.options"
                    :key="option.value"
                    :value="option.value"
                    >{{ option.title }}</el-option
                  >
                </el-select>
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
    </el-form>
    <div class="footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, PropType, ref, watch } from "vue"
import { IFormItem } from "../types"

export default defineComponent({
  props: {
    // 改进之后的formData
    modelValue: {
      type: Object,
      required: true
    },
    // 这是子组件接收父组件传过来的数组数据
    formItems: {
      // 默认传过来的数据是IFormItem类型
      type: Array as PropType<IFormItem[]>,
      // 如果默认数据是数组或者对象时需要用箭头函数表示
      default: () => []
    },
    labelWidth: {
      type: String,
      default: "100px"
    },
    title: {
      type: String,
      default: ""
    },
    itemStyle: {
      type: Object,
      default: () => ({ padding: "10px 40px" })
    },
    collayout: {
      type: Object,
      default: () => ({
        xl: 6, //>1920 显示4个
        lg: 8,
        md: 12,
        sm: 24,
        xs: 24
      })
    }
  },
  emits: ["update:modelValue"],
  setup(props, { emit }) {
    // 这里是将获取到的props.modelValue重新拷贝一份放在formData
    const formData = ref({ ...props.modelValue })
    // 深度监听,当formData发生变化,就发送事件给父组件
    watch(
      formData,
      (newValue: any) => {
        console.log(newValue)
        emit("update:modelValue", newValue)
      },
      {
        deep: true
      }
    )
    return {
      formData
    }
  }
})
</script>

<style scoped lang="less">
.hy-form {
  padding-top: 22px;
}
</style>

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

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

相关文章

coresight(五) rom table

五、 rom table 在一个soc中&#xff0c;有多个coresight组件&#xff0c;但是软件怎么去识别这些coresight组件&#xff0c;去获取这些coresight组件的信息了&#xff1f;这个时候&#xff0c;就需要靠coresight组件中&#xff0c;一个重要的组件&#xff0c;这个组件就是rom …

CMD有哪些有趣的命令?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store 用惯Linux和macOS的同学都会对各种各样强大的命令印象深刻&#xff0c;然而再转向Windows时就开始不屑一顾&#xff0c;认为Windows上没有Linux上那些超级便捷好用的命令。 其实&#xff0c;Windows下…

ROS安装及rosdep update问题解决

ROS安装&#xff1a; 参考链接&#xff1a;详细介绍如何在ubuntu20.04中安装ROS系统&#xff0c;以及安装过程中出现的常见错误的解决方法&#xff0c;填坑&#xff01;&#xff01;&#xff01;_慕羽★的博客-CSDN博客_ubuntu20.04安装ros rosdep update问题解决&#xff1a…

Linux Shell 脚本编程基础

Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应…

Selenium用法详解【窗口表单切换】【JAVA爬虫】

简介本文主要讲解java 代码利用Selenium如何实现控制浏览器进行窗口切换和页面内的不同表单之间的切换操作。切换操作窗口切换在 selenium 操作页面的时候&#xff0c;可能会因为点击某个链接而跳转到一个新的页面&#xff08;打开了一个新标签页&#xff09;&#xff0c;这时候…

电子词典流程图

简易流程&#xff1a; 详细介绍 服务端&#xff08;TCP并发&#xff09; 一.分支线程负责处理客户端发送的信息 1.登陆与注册信息 登陆&#xff08;l&#xff09;;注册&#xff08;e&#xff09; (1)登陆根据接收的用户名&#xff0c;密码在用户注册表中遍历是否符合&#xff…

ORB-SLAM2 --- ORBmatcher::SearchBySim3函数

目录 1.函数作用 2.函数流程 3.函数解析 3.1 准备工作&#xff1a;内参&#xff0c;计算Sim3的逆 3.2 记录已经匹配的特征点 3.3 通过Sim变换&#xff0c;寻找 pKF1 中特征点和 pKF2 中的新的匹配 3.4 通过Sim变换&#xff0c;寻找 pKF2 中特征点和 pKF1 中的新的匹…

Jenkins远程SSH部署SpringBoot项目

1.前置环境 前置环境配置&#xff1a;jdk、maven、git 2.在Jenkins配置git凭据 请查看往期文章&#xff1a; https://blog.csdn.net/RookiexiaoMu_a/article/details/122655272?spm1001.2014.3001.5501 3.安装Publish over SSH插件 4.配置SSH Servers 安装完Publish over…

C++蓝桥杯贪心算法

目录 &#x1f33c;一&#xff0c;1812: [NewOJ Week 5] 排列变换 &#x1f33c;二&#xff0c;1827: [NewOJ Week 8] 升降数字 &#x1f33c;三&#xff0c;剑指offer 10-II 青蛙跳台阶问题 &#x1f33c;四&#xff0c;P1223 排队接水 &#x1f33c;五&#xff0c;P5650…

npm常用命令

目录1. 构建项目2. 安装包3. 查看安装目录4. 卸载包5. 更新包6. 查看已安装的包7. 使用国内npm镜像源8. 使用yarn1. 构建项目 npm init # 全部使用默认配置 npm init --yes2. 安装包 # 全局安装 npm install 包名 -g # 本地安装 npm install 包名 # 一次安装多个 npm install…

ROS移动机器人开发——硬件引脚

我们使用的32开发板为冰达机器人官方的开发板&#xff0c;类型为STM32RCT6。32章节的目的为&#xff0c;将官方所给源码转化为 官方标准库函数来进行使用 —————————————— 需求提出&#xff1a; 电源 1. 3.3V-200ma供电 2. 输入 9-12.6V 5A 控制&#xff1a…

(十三)JAVA基础语法

目录 前言: 一、包 二、权限修饰符 三、final关键字 四、常量 五、枚举 六、抽象类 七、抽象类:模板方法模式 八、接口 前言: ①包: 在编写Java程序时&#xff0c;随着程序架构越来越大&#xff0c;类的个数也越来越多&#xff0c;这时就会发现管理程序中维护类名称也…

利用OpenCV的函数calcHist()计算出图像的直方图数据后绘制图像的直方图

利用OpenCV的函数calcHist()计算出图像的直方图数据后绘制图像的直方图 在上一篇博文 https://www.hhai.cc/thread-200-1-1.html 中已经对OpenCV的直方图计算函数calcHist()进行了详细介绍。 这篇博文介绍如何用直方图数据绘制直方图。 OpenCV是没有统计图绘制的相关函数的&a…

Verilog语法笔记(夏宇闻第三版)-循环语句

目录 forever语句: repeat语句: while语句: for语句: 在Verilog HDL中存在着四种类型的循环语句&#xff0c;用来控制执行语句的执行次数。 1) forever 连续的执行语句。 2) repeat 连续执行一条语句 n 次。 3) while 执行一条语句直到某个条件不满足。如果一开始条件即…

数据异动分析方法论

注&#xff1a;本文首发于公众号&#xff1a;书剑双修&#xff0c;欢迎关注。 数据异动分析是一类典型的数据分析问题&#xff0c;也是分析师日常工作中会频繁遇到的问题。很多的数据分析面试过程中&#xff0c;都会对这个方面进行考察&#xff0c;以此来判断分析师思考问题的全…

使用IIS服务器搭建一个网站

1、什么是IISIIS全称为Internet Information Services&#xff0c;是一种Web服务组件。通过在自己电脑上安装好IIS服务&#xff0c;就可以把你自己的电脑当作一个网站的服务器。2、搭建一个IIS2.1、开启windows的IIS服务Step1、控制面板——程序——程序和功能——启用或关闭wi…

微软的COM、DOM和COM+

纯粹的为了记录一下 COM 组件对象模型&#xff08;COM&#xff09;&#xff0c;是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术。在COM构架下&#xff0c;人们可以开发出各种各样的功能专一的组件&#xff0c;然后将它们按照需要组合起…

大数据NiFi(九):NiFi集群页面的添加、配置处理器操作

文章目录 NiFi集群页面的添加、配置处理器操作

jdb2/kworker

测试代码出自&#xff1a;块设备IO优化的典型案例分析_papaofdoudou的博客-CSDN博客_kworker/u2:2-2- #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <unistd.h&g…

基础算法 - 常见算法模板题(最简洁写法)【下】

目录 双指针 最长连续不重复子序列​编辑 二进制中1的个数 离散化 区间和 区间合并 双指针 最长连续不重复子序列 思路&#xff1a; 设左右指针 j&#xff0c;i&#xff1b;用 i 遍历数组&#xff0c;对【j&#xff0c;i】范围路径数值出现次数记录若次数大于1&#xff0c;则…