Vue中多个页面结构相同处理为共用一个入口页面组件,以及根据后台返回的页面的uniId处理不同页面的相关逻辑。

图一.png

图二.png
大致效果.gif

根据上面的图片可以看到,左侧的十三个页面大体上结构都是相同的,除了右侧的不同的按钮以及不同的按钮个数,这种情况下,就可以考虑使用动态路由传参以及slot具名插槽等技术去处理简化达到最优解。

1、使用到的技术方向
  • 动态路由传参
  • slot具名插槽
  • watch侦听器
  • 组件的封装
    ..等
2、开始对路由进行处理

体系建设是我这个项目的一个大的模块,下面13个页面结构类似,因此,直接写一个主入口targetManagement组件,这个模块所有的页面都跳转到这个页面,通过不同的页面的id实现获取不同的接口数据,由于我这个项目还有个打开文件夹的功能,因此,需要使用/targetManagement/:id/:fidid以及fid拼接到后面作为参数传入路由。

      // 体系建设
      {
        path: '/targetManagement/:id',
        name: 'targetManagement',
        component: () => import('@/views/pages/systemConstruction/targetManagement.vue'),
        meta: {
          title: [{
            name: '体系建设',
            url: ''
          }]
        }
      },
      // 文件夹查看
      {
        path: '/targetManagement/:id/:fid',
        name: 'targetManagement',
        component: () => import('@/views/pages/systemConstruction/components/foldersView.vue'),
        meta: {
          title: [{
            name: '体系建设',
            url: ''
          }, {
            name: '目标管理',
            url: ''
          }]
        }
      },
3、对页面进行唯一性处理

router-view是指的页面内容占位区域,也就是显示的部分,这里将路由路径进行唯一的key值绑定

<template>
  <div class="box">
    <navTop />
    <div class="content">
      <transition name="myfade" mode="out-in">
        <router-view :key="key" />
      </transition>
    </div>
  </div>
</template>
<script>
import navTop from "./navTop";

export default {
  name: "viewBox",
  components: {
    navTop,
  },
  computed: {
    key() {
      return this.$route.fullPath;
    },
  },
};
</script>
4、左侧导航栏菜单根据后台接口返回动态渲染

这部分获取接口返回过来的左侧菜单栏进行渲染操作

        <!-- 左侧菜单 -->
        <div class="menu-box">
          <div class="menu-wrap" :style="styleProps">
            <div class="logo-img">
              <!-- <img src="../assets/logo.png" alt /> -->
              <span>******平台</span>
            </div>
            <Menu
              :style="styleProps"
              :active-name="$route.menuUrl"
              :open-names="['home']"
              :theme="menuTheme"
              width="auto"
              :class="menuitemClasses"
              accordion
            >
              <template v-for="(item, componentIndex) in menu">
                <!-- 展开并且有子菜单 -->
                <Submenu
                  v-if="!isCollapsed && item.children && item.children.length"
                  v-bind:key="componentIndex"
                  :name="componentIndex"
                >
                  <template slot="title">
                    <Icon :type="item.menuIcon" />
                    <span>{{ item.menuName }}</span>
                  </template>
                  <MenuItem
                    v-for="children in item.children"
                    :key="children.menuUrl"
                    :name="children.menuUrl"
                    @click="handleRouter(children)"
                    :to="children.menuUrl"
                  >
                    {{ children.menuName }}
                  </MenuItem>
                </Submenu>

                <!-- 展开但没有子菜单 -->
                <MenuItem
                  v-else-if="!isCollapsed"
                  :name="item.menuUrl"
                  :to="item.menuUrl"
                  v-bind:key="componentIndex"
                >
                  <Icon :type="item.menuIcon" />
                  <span>{{ item.menuName }}</span>
                </MenuItem>

                <!-- 不展开有子菜单 -->
                <Dropdown
                  v-else-if="
                    isCollapsed && item.children && item.children.length
                  "
                  v-bind:key="componentIndex"
                  placement="right-start"
                  class="menu-dropdown"
                >
                  <MenuItem :name="item.menuUrl" :to="item.menuUrl">
                    <Icon :type="item.menuIcon" />
                    <span>{{ item.menuName }}</span>
                  </MenuItem>
                  <DropdownMenu slot="list">
                    <DropdownItem
                      v-for="(children, index) in item.children"
                      :key="index"
                      style="padding: 0 0; background-color: #515a6e"
                    >
                      <MenuItem :name="children.menuUrl" :to="children.menuUrl">
                        {{ children.menuName }}
                      </MenuItem>
                    </DropdownItem>
                  </DropdownMenu>
                </Dropdown>
                <!-- 不展开无子菜单 -->
                <Tooltip
                  v-else-if="isCollapsed"
                  :content="item.name"
                  placement="right"
                  v-bind:key="componentIndex"
                >
                  <MenuItem :name="item.menuUrl" :to="item.menuUrl">
                    <Icon :type="item.menuIcon" />
                    <span>{{ item.menuName }}</span>
                  </MenuItem>
                </Tooltip>
              </template>
            </Menu>
          </div>
        </div>
图三.png
5、模块处理过程
创建一个主入口页面.png
5.1、公共页面组件的搭建

创建一个BasicSystem组件为一个子组件,也就是去负责一些公共的部分,而右侧的不同内容的按钮需要根据item.btnId == key.split('/')[2]判断对应的内容去显示出来,uniId也就是监听到的拼接在路径末尾不同的id值。

    <transition-group name="fade" mode="out-in">
      <BasicSystem
        :key="uniId"
        :ps="ps"
        :pn="pn"
        :total="total"
        @handleSearch="handleSearch"
        @changePage="changePage"
        @handleSuccess="handleSuccess"
        @handleUpload="handleUpload"
        :dataList="dataList"
      >
        <template v-for="item in btns">
          <Button
            v-if="item.btnId == key.split('/')[2]"
            :key="item.id"
            type="primary"
            slot="fn-btn"
            @click="handleAll(item.handleName, item.row)"
            >{{ item.text }}
          </Button>
        </template>
      </BasicSystem>
    </transition-group>
5.2、主入口监听路由以及存储

监听路由获取uniId存储在会话中有一个好处,就是在这个页面下去频繁使用到uniId处理逻辑的时候可以去直接获取而不用频繁的使用params或者query去传参。
存储btnsLength是因为按钮的个数是不确定的,因此页面的 header布局也是动态的,无法固定死,需要去计算。

  computed: {
    key() {
      this.handleSession();
      this.handleTypeList();
      return this.$route.fullPath;
    },
  },
  watch: {
    $route: {
      handler(to, from) {
        this.btnsLength = 0;
        this.uniId = to.params.id;
        btns.forEach((item) => {
          if (item.btnId == this.uniId) {
            this.btnsLength++;
          }
        });
        sessionStorage.setItem("uniId", this.uniId);
        sessionStorage.setItem("btnsLength", this.btnsLength);
      },
      immediate: true,
    },
  },
5.3、子组件的头部动态布局处理

子组件中因为头部的按钮可以是一个也可以是三个,因此需要btnsLength=sessionStorage.getItem("btnsLength")?sessionStorage.getItem("btnsLength"): 0去处理头部的占位问题。

      <div class="basic-header">
        <Row class="row">
          <Col span="12">
            <Input
              v-model="keyWord"
              clearable
              placeholder="请输入文件名称查询"
              style="width: 300px"
            ></Input>
            <Button class="basic-btn" type="primary" @click="handleSearch"
              >查询</Button
            >

            <Button
              class="basic-btn secondary"
              type="success"
              @click="handleDown"
              >批量下载</Button
            >
          </Col>
          <Col :span="12 - 2 * btnsLength" class="basic-btn-upload right-btn">
            <Button type="success" @click="handleUpload">文档上传</Button>
          </Col>
          <Col :span="2 * btnsLength" class="basic-btn-operator">
            <slot name="fn-btn"></slot>
          </Col>
        </Row>
      </div>
5.4、右侧按钮的统一化处理

在处理右侧按钮时,也就是在targetManagement组件的过程中,使用:

        <template v-for="item in btns">
          <Button
            v-if="item.btnId == key.split('/')[2]"
            :key="item.id"
            type="primary"
            slot="fn-btn"
            @click="handleAll(item.handleName, item.row)"
            >{{ item.text }}
          </Button>
        </template>
图四.png

将所有的按钮放在一个js文件中,然后用上述的方法去遍历,获取的到方法的第一个参数就是按钮的事件名,第二个参数就是按钮的一些id等数据用于去判断。

5.5、右侧按钮的统一化处理(二)

将事件写出去,但是当点击主入口上的不同的按钮时,依旧是可以执行方法的。

 // 右侧的操作按钮
    handleAll(handleName, row) {
      switch (handleName) {
        // 目标管理签署列表
        case "handleSignListManage":
          this.handleSignListManage();
          break;
        // 组织结构文件签署
        case "handleSignListOrigin":
          this.handleSignListOrigin();
          break;
        // 安全生产费用
        case "handleSafetyCost":
          this.handleSafetyCost();
          break;
        // 年产总值
        case "handleTotalProduction":
          this.handleTotalProduction();
          break;
        // 培训列表
        case "handleTrainList":
          this.handleTrainList();
          break;
        // 演练列表
        case "handleDrillList":
          this.handleDrillList();
          break;
        // 设备清单
        case "handleEquipment":
          this.handleEquipment();
          break;
        default:
          break;
      }
    },

这样,大概总共几十甚至近百的页面,简单的优化处理,至少省去了几十个页面的重复绘制以及写一些重复的逻辑过程,在后期项目维护中,也是大大节省了成本,只需修改一个主入口即可。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容