Vue高阶知识:利用 defineModel 特性开发搜索组件组合

让我们一起走向未来

🎓作者简介:全栈领域优质创作者

🌐个人主页:百锦再@新空间代码工作室

📞工作室:新空间代码工作室(提供各种软件服务)

💌个人邮箱:[15045666310@163.com]

📱个人微信:15045666310

🌐网站:https://meihua150.cn/

💡座右铭:坚持自己的坚持,不要迷失自己!要快乐


目录

在 Vue.js 中,使用 defineModel 特性来创建一个高度可复用、灵活的搜索组件,能够简化复杂的搜索界面需求,同时增强代码的可维护性和可扩展性。本文将通过一个示例,展示如何基于 defineModelemit 机制,开发一个包含输入框、下拉列表和搜索按钮的搜索组件。该组件能够动态接收传参并且根据传入的数据,动态渲染不同类型的组件。

一、组件概述

我们将开发的搜索组件包含以下几个部分:

  1. 输入框 (Input):用户可以输入关键字进行搜索。
  2. 下拉框 (Select):用户可以选择一个选项进行过滤。
  3. 搜索按钮 (Search Button):触发搜索操作。

此外,我们将使用 Vue.js 的 defineModel 特性来定义一个可接收不同类型输入的表单,动态地渲染 inputselect 组件。

需求

输入框和下拉框的结构将根据传入的参数进行动态渲染,且每个组件都会有一个对应的 v-model 用来实现双向绑定。在用户操作输入框或下拉框时,组件通过 $emit 将搜索事件传递出去,供父组件使用。

传参数据的示例:

json 复制代码
[
  {
    "type": "select", // 组件类型,表示是下拉框
    "datalist": [{ "id": 1, "name": "Option 1" }, { "id": 2, "name": "Option 2" }], // 下拉框数据列表
    "value": "", // 当前选中的值
    "label": "选项", // 下拉框的标签
    "index": 0 // 排序索引
  },
  {
    "type": "input", // 组件类型,表示是输入框
    "datalist": "", // 输入框没有数据列表
    "value": "", // 输入框的初始值
    "label": "关键字", // 输入框的标签
    "index": 1 // 排序索引
  }
]

二、项目结构

为了实现这一需求,我们需要的主要文件包括:

  1. SearchComponent.vue:搜索组件
  2. ParentComponent.vue:父组件,负责传递参数和处理搜索事件

1. SearchComponent.vue (搜索组件)

该组件负责渲染输入框、下拉框以及搜索按钮。根据传入的数据,动态生成相应的表单元素,并通过 $emit 将搜索事件发送给父组件。

vue 复制代码
<template>
  <div class="search-component">
    <div v-for="(item, index) in searchData" :key="index" class="form-item">
      <!-- 根据 type 渲染不同的组件 -->
      <label :for="`search-item-${index}`">{{ item.label }}</label>
      
      <!-- 下拉框 -->
      <select v-if="item.type === 'select'" v-model="item.value" :id="`search-item-${index}`">
        <option v-for="(option, idx) in item.datalist" :key="idx" :value="option.id">{{ option.name }}</option>
      </select>
      
      <!-- 输入框 -->
      <input v-if="item.type === 'input'" v-model="item.value" :id="`search-item-${index}`" type="text" />
    </div>

    <!-- 搜索按钮 -->
    <button @click="onSearch">搜索</button>
  </div>
</template>

<script>
import { defineComponent, ref, toRefs } from "vue";

export default defineComponent({
  name: "SearchComponent",
  props: {
    // 接收搜索组件的数据配置
    searchData: {
      type: Array,
      required: true
    }
  },
  emits: ["search"], // 定义搜索事件,供父组件监听
  setup(props, { emit }) {
    const { searchData } = toRefs(props);

    // 搜索事件触发时,向父组件传递搜索结果
    const onSearch = () => {
      emit("search", searchData.value);
    };

    return {
      searchData,
      onSearch
    };
  }
});
</script>

<style scoped>
.search-component {
  display: flex;
  flex-direction: column;
}

.form-item {
  margin-bottom: 10px;
}

button {
  width: 100px;
  padding: 5px;
  margin-top: 10px;
}
</style>

2. ParentComponent.vue (父组件)

父组件负责接收搜索参数,并监听 search 事件,在事件触发时获取用户的选择值和输入框的值,并进行相应的处理(例如调用 API、过滤数据等)。

vue 复制代码
<template>
  <div>
    <h1>搜索组件示例</h1>
    <!-- 引入搜索组件 -->
    <SearchComponent :searchData="searchConfig" @search="handleSearch" />
  </div>
</template>

<script>
import { defineComponent, ref } from "vue";
import SearchComponent from "./SearchComponent.vue";

export default defineComponent({
  name: "ParentComponent",
  components: {
    SearchComponent
  },
  setup() {
    // 搜索组件的配置数据
    const searchConfig = ref([
      {
        type: "select",
        datalist: [
          { id: 1, name: "Option 1" },
          { id: 2, name: "Option 2" }
        ],
        value: "", // 默认值为空
        label: "选项",
        index: 0
      },
      {
        type: "input",
        datalist: "",
        value: "",
        label: "关键字",
        index: 1
      }
    ]);

    // 搜索事件处理
    const handleSearch = (searchData) => {
      // 在这里可以获取用户选择的值
      const filters = searchData.map(item => {
        return { label: item.label, value: item.value };
      });

      console.log("搜索条件:", filters);

      // 在此可以进行实际的搜索操作,如请求 API 或过滤本地数据
    };

    return {
      searchConfig,
      handleSearch
    };
  }
});
</script>

<style scoped>
h1 {
  margin-bottom: 20px;
}
</style>

三、代码说明

1. SearchComponent.vue 组件

该组件通过 v-for 遍历 searchData 数组,渲染每一个表单项。每一个表单项根据 type 字段决定渲染为输入框 (input) 还是下拉框 (select)。

  • 数据传递 :父组件通过 searchData 属性向子组件传递数据配置。每个配置项包含组件类型(type)、数据列表(datalist)、初始值(value)、标签(label)等。

  • 动态渲染 :使用 v-if 判断每个组件的类型,并根据 type 动态渲染相应的组件类型。

  • 双向绑定 :使用 v-model 双向绑定输入框和下拉框的值。这样用户在输入框或下拉框中输入或选择时,组件的 value 值会实时更新。

  • 搜索按钮 :点击搜索按钮时,onSearch 方法会触发,向父组件通过 emit 发送 search 事件,并将 searchData 数据传递出去。父组件可以通过监听该事件来处理搜索逻辑。

2. ParentComponent.vue 组件

父组件接收 searchData 配置,并通过 @search 监听搜索事件。在事件处理方法 handleSearch 中,可以获取用户选择的条件,并执行搜索操作。

  • 数据配置searchConfig 数组包含了两个搜索组件的配置项(一个 select,一个 input)。

  • 搜索事件处理handleSearch 方法接收到子组件通过 $emit 发出的 search 事件,在其中处理搜索逻辑。此处可以执行后端请求、过滤本地数据等。

3. 传递数据与 emit 机制

通过 emit 机制,子组件能够将事件(如搜索操作)传递给父组件,从而实现组件间的通信。在本示例中,SearchComponent 组件触发 search 事件,父组件通过监听该事件来处理搜索条件。

四、总结

通过结合 defineComponentv-forv-modelemit 机制,Vue.js 能够实现一个灵活且高效的动态搜索组件。这个搜索组件能够根据传入的数据配置,动态渲染不同类型的输入组件(如输入框、下拉框等),并且能够通过事件机制将用户选择的条件传递给父组件进行处理。这种设计使得该搜索组件具有较高的复用性,并且能够轻松应对不同的业务场景。

相关推荐
百思可瑞教育2 小时前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育
hdsoft_huge2 小时前
1panel面板中部署SpringBoot和Vue前后端分离系统 【图文教程】
vue.js·spring boot·后端
CappuccinoRose2 小时前
JavaScript 学习文档(二)
前端·javascript·学习·数据类型·运算符·箭头函数·变量声明
A9better2 小时前
C++——不一样的I/O工具与名称空间
开发语言·c++·学习
廖松洋(Alina)2 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙
这儿有一堆花2 小时前
Vue 是什么:一套为「真实业务」而生的前端框架
前端·vue.js·前端框架
AI职业加油站2 小时前
职业提升之路:我的大数据分析师学习与备考分享
大数据·人工智能·经验分享·学习·职场和发展·数据分析
全栈前端老曹2 小时前
【MongoDB】深入研究副本集与高可用性——Replica Set 架构、故障转移、读写分离
前端·javascript·数据库·mongodb·架构·nosql·副本集
四谎真好看3 小时前
JavaWeb学习笔记(Day13)
笔记·学习·学习笔记·javaweb