当前位置: 首页 > article >正文

vue封装组件进阶

创作代码时,经常会遇到需求出现相似的界面效果,但是里面循环的列表参数不一致,重新写的话会导致代码冗余。复用代码,灵活操控会大大提高开发效率。

场景:vue循环列表,两个列表展示的参数不一致;封装一个公用组件,达到可定制会展示内容

初效果

原始代码

<div class="test_item">
      <div class="test_item_top">
        产品信息
      </div>
      <div class="product">
        <div v-for="(item,index) in product" :key="index" class="product_item">
          <div class="product_item_top">
            产品名称
          </div>
          <div class="product_item_bottom">
            {
  
  { item.productname }}
          </div>
          <div class="product_item_top">
            生产地
          </div>
          <div class="product_item_bottom">
            {
  
  { item.address }}
          </div>
        </div>
      </div>
    </div>
<div class="test_item">
      <div class="test_item_top">
        审核信息
      </div>
      <div class="product">
        <div v-for="(item,index) in history" :key="index" class="product_item">
          <div class="product_item_top">
            提交时间
          </div>
          <div class="product_item_bottom">
            {
  
  { item.one }}
          </div>
          <div class="product_item_top">
            审核时间
          </div>
          <div class="product_item_bottom">
            {
  
  { item.two }}
          </div>
        </div>
      </div>
    </div>

可见,两个列表有相似的样式,可以公用一个组件。

初次封装可能就会把共同使用的html及css代码剪切到一个子组件中,通过父组件给子组件的传值来达到渲染的效果;但数据和效果上可以看出这是两个表格,数据也是两个。

如果是这样的话,首先想到的是在父组件挂载两个子组件不就行了,传递不同的数据用以渲染;

<template>
  <div class="test">
    <product :infor="productInfor" />
    <history :infor="historyInfor" />
  </div>
</template>

这样写违背了我们的初衷,果断舍弃

再者要不把数据全部给子组件,子组件根据渲染条件判断?这样写不就是相当于把冗余的代码剪切到另外的文件吗!!

进阶

首先,我们需要解决一个问题就是效果图上的诸如产品名称、生产地、提交时间等固定的文字能否也是动态的,根据我们传入的数据来一一展示呢?!固定文字与渲染数组的对象的键一一对应,那就是对象了。

我们平常都是循环数组对象已达到在页面上渲染诸多相同结构的数据

<div v-for="(item, index) in history" :key="index" class="product_item">
    <div class="product_item_top">
        提交时间
    </div>
    <div class="product_item_bottom">
        {
  
  { item.one }}
     </div>
     <div class="product_item_top">
         审核时间
     </div>
     <div class="product_item_bottom">
         {
  
  { item.two }}
      </div>
</div>

其实对象也可以用作循环遍历的,在上面的循环里在写入循环对象。用对象的键值来展示固定字段,用对象的键来固定展示外层数组数据

data() {
      return {
        obj: {
          productname: '产品名称',
          address: '生产地'
        }
      }
    }
<div class="product">
      <div
        v-for="(item, index) in product.data"
        :key="index"
        class="product_item"
      >
        <div v-for="(it, objIndex) in obj" :key="objIndex">
          <div class="product_item_top">
            {
  
  { it }}
          </div>
          <div class="product_item_bottom">
            {
  
  { item[objIndex] }}
          </div>
        </div>
      </div>
    </div>

注释:上方代码中循环对象,第一个参数为对象的键值,第二的参数为对象的键,根据循环对象的键来获取循环数组对象的规定值

结合以上的规则,我们可以对代码进行再升级

父组件

<template>
  <div class="test">
    <list :product="product" :obj="proObj" />
    <list :product="history" :obj="hisObj" />
  </div>
</template>
<script>
  import list from './components/list.vue'
  export default {
    components: {
      list
    },
    data() {
      return {
        product: {
          category: '产品信息',
          data: [
            {
              productname: '肯德基',
              address: '洛杉矶'
            },
            {
              productname: '蜜雪冰城',
              address: '中国'
            }
          ]
        },
        proObj: {
          productname: '产品名称',
          address: '地址'
        },
        history: {
          category: '历史记录',
          data: [
            {
              one: '2025-05-05 12:00:00',
              two: '2025-06-05 12:00:00'
            },
            {
              one: '2025-06-05 12:00:00',
              two: '2025-07-05 12:00:00'
            }
          ]
        },
        hisObj: {
          one: '提交时间',
          two: '审核时间'
        }
      }
    }
  }
</script>

子组件

<template>
  <div class="test_item">
    <div class="test_item_top">
      {
  
  { product.category }}
    </div>
    <div class="product">
      <div
        v-for="(item, index) in product.data"
        :key="index"
        class="product_item"
      >
        <div v-for="(it, objIndex) in obj" :key="objIndex">
          <div class="product_item_top">
            {
  
  { it }}
          </div>
          <div class="product_item_bottom">
            {
  
  { item[objIndex] }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  export default {
    props: {
      product: {
        type: Object,
        default: () => {}
      },
      obj: {
        type: Object,
        default: () => {}
      }

    },
    data() {
      return {

      }
    }
  }
</script>

由此可以看出,子组件完全根据父组件的要求展示内容,完全灵活。

实际使用中,样式完全一致的情况很少,有些地方会有些不同,那就需要我们对组件进行再升级。

vue中插槽的作用完全可以满足我们的需求,在不影响我们的总体效果。在 Vue.js 中,插槽(Slots)是一种非常强大的组件内容分发机制,允许你在父组件中向子组件传递自定义内容。插槽的主要作用是提高组件的灵活性和复用性。

效果图

父组件修改的内容

<list :product="product" :obj="proObj">
      <template v-slot:category="slotProps">
        <div class="btn_cate">
          <div class="btn_inner">
            {
  
  { slotProps.item.address }}
          </div>
        </div>
      </template>
</list>

子组件修改的内容

    <div class="product">
      <div
        v-for="(item, index) in product.data"
        :key="index"
        class="product_item"
      >
        <div v-for="(it, objIndex) in obj" :key="objIndex">
          <div class="product_item_top">
            {
  
  { it }}
          </div>
          <div class="product_item_bottom">
            {
  
  { item[objIndex] }}
          </div>
        </div>
        <template>
          <slot name="category" :item="item"></slot>
        </template>
      </div>
    </div>

以上就是所有内容

本博客仅仅是提供了一种优化组件封装的思路,欢迎留言交流


http://www.kler.cn/a/538510.html

相关文章:

  • StochSync:可在任意空间中生成360°全景图和3D网格纹理
  • 深入探究 Go 语言中的 Fx 框架:依赖注入的强大工具
  • Android性能优化
  • Docker 部署 RabbitMQ | 自带延时队列
  • Flink (十七) :Table API SQL (五) 时区
  • Sentinel——Spring Boot 应用接入 Sentinel 后内存开销增长计算方式
  • Visual Basic语言的区块链
  • Unity做2D小游戏2------创建地形和背景
  • Spring Boot的常用注解
  • 光伏-报告显示,假期内,硅料端签单顺序发货相对稳定。若3月份下游存提产,则不排除硅料价格有上调预期。
  • Java怎么记录网络安全情报 java转网络安全
  • 微服务日志查询难解决方案-EFK
  • 增加工作台菜单页面,AI问答应用支持上下文设置,数据库表索引优化,zyplayer-doc 2.4.8 发布啦!
  • deepseek+kimi自动生成ppt
  • 【信奥赛CSP-J 需要掌握的STL知识有哪些?】
  • 【HarmonyOS NEXT】systemDateTime 时间戳转换为时间格式 Date,DateTimeFormat
  • C# ASP.NET程序与 Web services 编程介绍
  • Python实现机器学习小项目教程案例
  • Ollama 部署 DeepSeek-R1 及Open-WebUI
  • 响应式编程库Reactor(一)
  • USB枚举过程及Linux下U盘识别流程
  • DeepSeek-V3 论文解读:大语言模型领域的创新先锋与性能强者
  • ubuntu 22.04 cuda12.x 上 cutensor 1.6.2 版本环境搭建
  • 机器人调度系统交通管制算法
  • DeepSeek在FPGA/IC开发中的创新应用与未来潜力
  • 如何查看Ubuntu24.04系统,显卡是什么型号,适配的驱动是什么?