vue的组件化的理解之单独拆分的组件&组件的封装(以el-table组件的二次封装举例)

简介: vue的组件化的理解之单独拆分的组件&组件的封装(以el-table组件的二次封装举例)

highlight: a11y-dark

什么是组件化

组件化是一种思想,就是拆分的意思,通俗而言,就是大而化小(没有小而化了)、方便管理。比如咱们中国地大物博,人口众多不好管理,所以就拆分成许多省、直辖市、自治区,方便管理。写代码也是一样,如果一个文件写了几万行代码,就会耦合太严重,拆分开来,方便管理。

但是组件化不能过渡使用,不能为了组件化而组件化。合理使用,才为上策

组件化和模块化的区别

组件化-ui视图层面的拆分

组件化-ui视图层面的拆分,以vue为例,一个页面有头部、内容区、底部。可以拆分开来,这里的拆分一般都会带着样式css,所以称之为UI视图层面的拆分(当然也会包含js的相关逻辑)

模块化-js层面的拆分

模块化的拆分主要是js逻辑层面的拆分,二者类似,但不同

组件的分类

独立拆分的组件

比如我们把一个页面的头部、内容区、底部分别拆分成三个独立的组件

公共复用的组件

比如在很多的路由页面里,都需要使用到一个弹框、或者使用到一个表格。我们可以封装一个弹框或者封装一个表格,哪里需要引哪里,不同页面的弹框或表格数据不一样,我们可以通过给封装的公共组件传递不同的数据,使其展现不同。

其实一个.vue文件就是一个组件,只不过是页面级别的组件罢了

独立拆分的组件之拆分步骤

第一步 组件拆分

本来都写在一个文件中的内容,比如一个.vue文件的结构中包括头部、底部、内容区。我们把头部的html、css、js的内容,单独拎出来成为一个新的.vue文件。当然底部、和内容区的也同样单独拎出来。单独拎出来的就放在components文件夹下吧

第二步 组件引入

import dialogMask from "./components/dialog";

第三步 组件注册

// 是components不是component,要加个s,因为组件可能要注册多个
export default {
    // ...
    components: {
        dialogMask,
    },
}

第四步 组件使用

<div class="dialog">
      <dialog-mask></dialog-mask>
</div>

公共复用的组件之拆分步骤

复用组件的拆分步骤,最后el-table组件的二次封装会讲解,诸位看官且继续往下看。这里先按下不表。
说道组件的封装,就要与数据传递打交道,所以这里简单说一下vue组件间的数据传递,又因为封装组件大多数的数据传递是以父子组件的传递为主,所以这里提一下vue父子组件间的数据传递。

父子组件间的数据传递之两种方式

方式一(v-bind加v-on)

父传子

  • 父组件v-bind绑定自己data中数据传递给子组件
  • 子组件通过props接收到在页面中使用

步骤图如下:

image.png

子传父

  • 子组件通过this.$emit('eventName','参数')触发父组件中的方法
  • 父组件要提前在组件上通过v-on暴露给子组件以便调用

步骤图如下:

image.png

方式二(使用ref取值赋值)

父传子或子传父

  • 第一步,给子组件打一个ref,就可以看到子组件所有的东西,感兴趣的朋友可以打印一下this.$refs.dialogRef结果一目了然。 <dialogMask ref="dialogRef"></dialogMask>
  • 第二步,在父组件中把父组件的数据赋给子组件(父传子)this.$refs.dialogRef.子组件的数据 = this.父组件的数据
  • 第三步,在子组件中直接取到拿到子组件的数据赋给父组件 this.父组件的数据 = this.$refs.dialogRef.子组件的数据

父子组件的方法的相互调用

就记住常用的方式吧

  • 父组件调用子组件的方法,使用ref
    this.$refs.xxx.childMethods()
  • 子组件调用父组件的方法,使用this.$emit('eventName','参数')

饿了么UI中的el-table组件的二次封装

饿了么UI的组件是饿了么团队基于vue封装的,里面有很多常用的组件,方便我们快速开发项目。不过假设我们的项目中的很多页面都有表格呈现,表格的结构差不多,就是数据不一样,如果我么每个页面都去写el-table一大堆的话,就会比较麻烦,倒不如自己封装一个公共的table组件,那个页面用table的话,那个页面就引进来,传参即可。

第一步,新建组件,注册并在main.js引入

流程图如下:

image.png
至此,我们自定义的封装的myTable组件已经注册好了,那个页面需要用,就在那个页面去引入,传对应的参数即可

第二步,根据需求考虑传参

我们先看一下效果图:

image.png

需求如下:

  • 复选框列和序号列可控制是否展示
  • 表头数据动态展示
  • 表内容数据也动态展示
实际项目中我们要发请求获取表的数据和表内容数据,这里的话,我们就模拟一下数据即可

封装的myTable组件代码

<template>
  <div class="box">
    <el-table
      :data="tableData"
      border
      style="width: 100%"
      @selection-change="handleSelectionChange"
    >
      <!-- 复选框列
              复选框列和索引列因为有的显示有的不显示,所以我们使用一个v-if去控制它,
              v-if的标识取决于父组件(引用这个组件的组件)传递过来的标识。子组件也就是
              我们封装的这个myTable组件用props接收一下又因为复选框要有勾选时间所以
              @select-change事件不能落下
       -->
      <el-table-column
        v-if="isShowCheckbox == true"
        type="selection"
        width="48"
        fixed
      ></el-table-column>
      <!-- 索引列 -->
      <el-table-column
        v-if="isShowIndex == true"
        label="序号"
        type="index"
        width="50"
        fixed
      >
      </el-table-column>
      <!-- 主内容列 
              主内容列的表头就是label,表头列对应的数据就是prop,所以父组件可以传递过来
              一个数组,里面的每一项就是label的名字和prop对应的值。通过v-for就动态了
      -->
      <el-table-column
        :prop="item.propName"
        :label="item.labelName"
        v-for="(item, index) in tableHeaderTitle"
        :key="index"
      >
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "myTable",
  props: {
    // 父组件传递过来的表头的数组数据
    tableHeaderTitle: {
      type: Array,
      default: [],
    },
    // 父组件传递过来的表内容的数组数据
    //  注意:表头内容数据和表内容数据有关联的
    tableData: {
      type: Array,
      default: [],
    },
    // 父组件传递过来的是否展示复选框列的标识
    isShowCheckbox: {
      type: Boolean,
      default: false,
    },
    // 父组件传递过来的是否展示序号索引列的标识
    isShowIndex: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    // 勾选以后,要把勾选的这一行的数据传递给父组件,以供使用
    handleSelectionChange(checked) {
      this.$emit("receiveCheckedData", checked);
    },
  },
};
</script>

引用myTable组件的父组件代码

<template>
  <div id="app">
    <!-- 因为之前已经vue全局注册了自己封装的组件,所以这里不需要在引入这个组件了
         可以直接用即可 -->
    <my-table
      :tableHeaderTitle="tableHeaderTitle"
      :tableData="tableData"
      :isShowCheckbox="isShowCheckbox"
      :isShowIndex="isShowIndex"
      @receiveCheckedData="receiveCheckedData"
    ></my-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 模拟表头数据,实际要发请求获取的
      tableHeaderTitle: [
        {
          propName: "name",
          labelName: "姓名",
        },
        {
          propName: "age",
          labelName: "年龄",
        },
        {
          propName: "gender",
          labelName: "性别",
        },
        {
          propName: "height",
          labelName: "身高",
        },
        {
          propName: "weight",
          labelName: "体重",
        },
        {
          propName: "like",
          labelName: "爱好",
        },
        {
          propName: "address",
          labelName: "住址",
        },
      ],
      // 模拟表内容数据
      tableData: [
        {
          id:"11111",
          name: "孙悟空",
          age: 500,
          gender: "男",
          height: "七尺男儿",
          weight: "三百吨",
          like: "桃子",
          address: "花果山水帘洞",
        },
        {
          id:"22222",
          name: "猪八戒",
          age: 88,
          gender: "男",
          height: "七尺男儿",
          weight: "八百吨",
          like: "肉包子",
          address: "高老庄",
        },
        {
          id:"33333",
          name: "沙和尚",
          age: 1000,
          gender: "男",
          height: "七尺男儿",
          weight: "三百吨",
          like: "鱼",
          address: "通天河",
        },
      ],
      // 是否展示复选框列
      isShowCheckbox:true,
      // 是否展示序号索引列
      isShowIndex:true,
    };
  },
  methods: {
    // 接收子组件勾选的行的数据
    receiveCheckedData(checked){
      console.log('checked',checked);
    }
  },
};
</script>

<style lang="less" scoped>
#app {
  width: 100%;
  min-height: 100vh;
  box-sizing: border-box;
  padding: 50px;
}
</style>

在实际情况中,需要根据产品的需求,去做出对应的封装。组件封装一定要灵活

补充(看饿了么组件的收获)

我们打开node_modules文件夹下,里面有很多的依赖包(库),我们找到element-ui的这个文件夹,里面的packages文件夹存放的就是饿了么团队封装好的组件。如下图:

image.png

没事看看也挺好,也能学到不少的东西

image.png
小伙伴们如果觉得文章写的还勉强凑合能看,给鼓励一下点个赞呗。感谢哦

相关文章
|
7天前
|
移动开发 JavaScript API
Vue Router 核心原理
Vue Router 是 Vue.js 的官方路由管理器,用于实现单页面应用(SPA)的路由功能。其核心原理包括路由配置、监听浏览器事件和组件渲染等。通过定义路径与组件的映射关系,Vue Router 将用户访问的路径与对应的组件关联,支持哈希和历史模式监听 URL 变化,确保页面导航时正确渲染组件。
|
7天前
|
JavaScript 前端开发 开发者
Vue中的class和style绑定
在 Vue 中,class 和 style 绑定是基于数据驱动视图的强大功能。通过 class 绑定,可以动态更新元素的 class 属性,支持对象和数组语法,适用于普通元素和组件。style 绑定则允许以对象或数组形式动态设置内联样式,Vue 会根据数据变化自动更新 DOM。
|
7天前
|
JavaScript 前端开发 数据安全/隐私保护
Vue Router 简介
Vue Router 是 Vue.js 官方的路由管理库,用于构建单页面应用(SPA)。它将不同页面映射到对应组件,支持嵌套路由、路由参数和导航守卫等功能,简化复杂前端应用的开发。主要特性包括路由映射、嵌套路由、路由参数、导航守卫和路由懒加载,提升性能和开发效率。安装命令:`npm install vue-router`。
|
JavaScript 容器
Vue组件化定义
组件化     组件化的概念         Web 中的组件其实就是页面组成的一部分,好比是电脑中的每一个元件(如硬盘、键盘、鼠标),它是一个具有独立的逻辑和功能或界面,同时又能根据规定的接口规则进行相互融合,变成一个完整的应用,页面就是有一个个类似这样的部分组成,比如导航、列表、弹窗、下拉菜单等。
1484 0
|
2月前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
148 1
|
11天前
|
监控 JavaScript 前端开发
ry-vue-flowable-xg:震撼来袭!这款基于 Vue 和 Flowable 的企业级工程项目管理项目,你绝不能错过
基于 Vue 和 Flowable 的企业级工程项目管理平台,免费开源且高度定制化。它覆盖投标管理、进度控制、财务核算等全流程需求,提供流程设计、部署、监控和任务管理等功能,适用于企业办公、生产制造、金融服务等多个场景,助力企业提升效率与竞争力。
65 12
|
28天前
|
JavaScript 安全 API
iframe嵌入页面实现免登录思路(以vue为例)
通过上述步骤,可以在Vue.js项目中通过 `iframe`实现不同应用间的免登录功能。利用Token传递和消息传递机制,可以确保安全、高效地在主应用和子应用间共享登录状态。这种方法在实际项目中具有广泛的应用前景,能够显著提升用户体验。
54 8
|
29天前
|
存储 设计模式 JavaScript
Vue 组件化开发:构建高质量应用的核心
本文深入探讨了 Vue.js 组件化开发的核心概念与最佳实践。
75 1
|
3月前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
111 58
|
2月前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。

热门文章

最新文章