IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> webpack4使用require中加载异步组件 -> 正文阅读

[JavaScript知识库]webpack4使用require中加载异步组件

背景

我们开发的系统是提供给公司中其他项目组使用的,提供了一些管理信息系统中常用的功能,其他项目组在此基础上做二次开发,添加业务相关的其他功能模块。之前并没有完全采用前后端分离的形式开发,现在为了支持前后端分离,需要使用vue+elementui+webpack4再单独提供一套前端系统,后端接口继续使用原来的。有几个页面使用到页签组件tabs,但是页签中需要加载哪些页签是配置在数据库中的,需要从后台获取数据后再加载。试了几种方法,最后感觉有两种比较好。

方案一:使用component组件+require.context实现

在这里插入图片描述
系统中内置了组织管理功能,每个组织可以通过勾选下方的复选框关联组织类型,页签中加载相应的组织类型维护页面,由于组织类型是不固定的,由具体的项目组根据业务确定,所以需要具备扩展性。由于原先的系统是以jar包的形式提供给其他的项目组,不能修改源码,所以系统部署时需要将业务相关的组织类型信息,包括页面路径录入数据库中,该页面初始化时通过ajax读取配置信息进行加载。
由于现在使用vue重新开发一套前端系统,最终以源码的形式提供给其他项目组,所以简化了这方面的配置:
1.只需要在数据库中配置组织类型的id和text,不需要录入页面路径,页面出事化时从数据库中读取id和text,用来渲染下方的复选框和tab页签中的标签
2.系统将从指定路径下加载组织类型维护页面(使用webpack4的require.context()接口),并通过vue的components:{name:coponent,…}属性注册到上图页面的vue实例中,注册时的component名称取组织类型维护页面中的组件名称name,注意这里的name需要和数据库中的id保持一致,由于注册vue组件时,组件的name命名规则有限制(比如不能使用html标签名),所以注册时还会在name前添加一个前缀减少冲突的概率
代码大体是这样的:

<template>
<el-tabs v-model="activeTab" style="height:400px">
      <el-tab-pane label="基本信息" name="main" class="tab-panel-custom">
        <el-form ref="basicInfo" v-loading="billLoading" :model="form" :rules="rules" label-width="120px" :disabled="isBrowse">

          <el-row>
            <el-col :span="12">
              <el-form-item label="上级组织" prop="cparentname">
               //省略.....
              </el-form-item>
            </el-col>
          </el-row>

          //省略 编码、助记码。。。。

          <el-divider class="orgnTypeDivider" content-position="left">请选择组织类型</el-divider>
          <el-checkbox-group v-model="form.orgtype" :disabled="form.cparentid === '000000'">
            <el-checkbox v-for="(item) in orgnTypeData" :key="item.id" :label="item.id">{{ item.text }}</el-checkbox>
          </el-checkbox-group>
          <el-divider class="orgnTypeDivider"></el-divider>
        </el-form>
      </el-tab-pane>

      <!-- 根据数据库中的配置添加页签,使用v-if隐藏没有勾选的组织类型-->
      <template v-for="(item) in orgnTypeData">
        <el-tab-pane v-if="form.orgtype.indexOf(item.id) !== -1" :key="item.id" :label="item.text" :name="item.id" class="tab-panel-custom">
          <!-- 使用component动态加载组织类型维护页面 -->
          <component :is="getComponentName(item.id)" :ref="'custom-'+item.id" :params="{'cOrgnID':form.cGUID,'cOrgnType':item.id,'isBrowse':isBrowse}" />
          <!-- </keep-alive> -->
        </el-tab-pane>
      </template>

    </el-tabs>
</template>

<script>
//省略 import xxxx

// 直接从@/views/orgn/manage/orgnattrs目录读取各组织类型维护页面,各业务组织组件的name需与后台一致,不区分大小写
const files = require.context('@/views/aos/orgn/manage/orgnattrs', false, /\.vue$/)
const orgnComponents = {}
files.keys().forEach((value) => {
  const orgnComponent = files(value)// 注意require.context返回值是一个函数,不是map,这里是圆括号,不能用方括号files[value]取值
  orgnComponents[`aos-${orgnComponent.default.name.toLowerCase()}`] = orgnComponent.default
})

export default {
  name: 'OrgnBill',
  components: {
    ...orgnComponents//注册组织类型组件
  },
  //省略....
  method(){
  init(){
  	//省略....
  	//页面初始化化时通过axios请求获取配置的组织类型信息
  	this.orgnTypeData = xxx
	//省略....
  },
  // <component>标签is属性指定加载的组件名,若该组件对应的组织类型在数据库中存在,但未提供维护页面,则默认使用@/views/orgn/manange/orgnattrs/template.vue
  getComponentName(orgntypeid) {
      const componentName = 'aos-' + orgntypeid.toLowerCase()// template.vue
      if (this.$options.components[componentName]) {
        return componentName
      }
      return 'aos-businessorgntemplate'
    },
    //省略....
  }
  

方案二:使用component组件+require(‘modulePath’,callback)实现

另一个需要动态加载页签的页面是工作流审批中加载用户单据的页面,用户单据并不是只能在工作流的页签中加载,它可以是业务系统中的一个个可以独立使用的页面,所以我们并不能向组织类型那样指定一个固定的目录存放,具体的项目组会按模块功能划分目录,
然后将工作流中会用到的表单页面路径录入数据库,所以工作流中单据加载需要从后台读取页面的路径,这里使用webpack4的require(‘modulePath’,callback)接口实现
在这里插入图片描述

<template>
 	<el-tab-pane label="流程表单" name="businessForm">
      	<component :is="'Form'" ref="businessFormRef"></component>
 	</el-tab-pane>
</template> 
init(params) {
      //...
      Vue.component('Form', (resolve) => {
        require([`@/views/${this.params.formurl}`], (data) => {
          resolve(data)
          this.$nextTick(() => {
            //...
            this.$refs['businessFormRef'].initForm(params)
          })
        })
      })
 }

这里参照vue官网的例子,使用Vue.component接口将表单注册为全局组件,但是require接口的回调不能直接设置为resolve,因为使用require异步加载组件是通过网络请求异步加载的,返回表单组件后,首先使用resolve进行注册,再通过refs获取组件实例,调用初始化方法,resolve似乎包含异步操作,所以表单实例的初始化方法必须通过nextTick方法执行

其他

最后还剩一处疑惑,webpack4官方文档是推荐使用import(url)异步加载组件的,import支持注释的方式配置编译时的参数,可以按需求进行优化,一开始我也是使用的import(),但是f12提示找不到组件,百度了一下,都说webpack4的import()不支持路径里包含变量,必须是字面量,可是webpack4官方文档的例子中确实是可以包含变量的:
在这里插入图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-16 18:44:30  更:2021-11-16 18:44:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 16:37:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码