vue封装组件进阶

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

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

初效果

原始代码

html 复制代码
<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>
html 复制代码
<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代码剪切到一个子组件中,通过父组件给子组件的传值来达到渲染的效果;但数据和效果上可以看出这是两个表格,数据也是两个。

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

html 复制代码
<template>
  <div class="test">
    <product :infor="productInfor" />
    <history :infor="historyInfor" />
  </div>
</template>

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

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

进阶

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

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

html 复制代码
<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>

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

html 复制代码
data() {
      return {
        obj: {
          productname: '产品名称',
          address: '生产地'
        }
      }
    }
html 复制代码
<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>

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

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

父组件

html 复制代码
<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>

子组件

html 复制代码
<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)是一种非常强大的组件内容分发机制,允许你在父组件中向子组件传递自定义内容。插槽的主要作用是提高组件的灵活性和复用性。

效果图

父组件修改的内容

html 复制代码
<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>

子组件修改的内容

html 复制代码
    <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>

以上就是所有内容

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

相关推荐
IT_陈寒3 小时前
Python开发者必知的5大性能陷阱:90%的人都踩过的坑!
前端·人工智能·后端
codingWhat3 小时前
介绍一个手势识别库——AlloyFinger
前端·javascript·vue.js
Lee川3 小时前
深度拆解:基于面向对象思维的“就地编辑”组件全模块解析
javascript·架构
代码老中医3 小时前
2026年CSS彻底疯了:这6个新特性让我删掉了三分之一JS代码
前端
进击的尘埃3 小时前
Web Worker 与 OffscreenCanvas:把主线程从重活里解放出来
javascript
不会敲代码13 小时前
Zustand:轻量级状态管理,从入门到实践
前端·typescript
踩着两条虫3 小时前
VTJ.PRO 双向代码转换原理揭秘
前端·vue.js·人工智能
扉川川3 小时前
OpenClaw 架构解析:一个生产级 AI Agent 是如何设计的
前端·人工智能
远山枫谷3 小时前
一文理清页面/组件通信与 Store 全局状态管理
前端·微信小程序
codingWhat3 小时前
手撸一个「能打」的 React Table 组件
前端·javascript·react.js