低代码平台加载远端组件解决方案(1)——defineAsyncComponent

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 低代码平台加载远端组件解决方案(1)——defineAsyncComponent

背景

最近在做低代码平台项目中遇到一个很容易遇到的问题,具体描述如下:

  • 问题描述:低代码平台依赖的组件库,如果将一个组件库进行融合打包到平台项目中的就会导致平台在渲染页面的时候需要加载完整的组件库,从而导致页面加载了一些大部分页面不需要的组件文件
  • 希望方案:页面使用到哪些组件就去动态加载组件
  • 解决方案:
  • Vue的异步加载组件,SuspensedefineAsyncComponent
  • React的异步加载组件, Suspenseimport()

由于低代码项目本身使用的 Vue3 框架,而且 Vue和 React的异步加载组件方案其实差异不多,所以下面以 Vue为主进行介绍。

基础知识

异步组件

在使用异步组件之前,我们需要先声明一个 Vue的异步组件,主要有以下几种方式:

第一种,采用<script setup>语法的,需要在 setup中 使用 await语法即可,例子如下:

<script setup>
const res = await fetch(...)
const posts = await res.json()
</script>

第二种,声明setup函数增加async,会被识别成异步组件,具体如下:

export default {
  async setup() {
    const res = await fetch(...)
    const posts = await res.json()
    return {
      posts
    }
  }
}

第三种,就是通过defineAsyncComponent函数定义异步获取的组件实例,具体如下:

import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() => {
  return new Promise((resolve, reject) => {
    // ...从服务器获取组件
    resolve(/* 获取到的组件 */)
  })
})
// ... 像使用其他一般组件一样使用 `AsyncComp`

注意:同时Vue组件有个配置属性suspensible,可以用来设置false忽略为异步组件。

Suspense

<Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。 —— Vue官方 Suspense定义

<Suspense>解决了我们什么问题:

  • 当我们有个全局 loading,就不再需要每个组件的针对自己的加载状态去写逻辑处理
  • 能够更好统一处理异步组件,减少逻辑代码
  • 结合路由切换 和 <Transition>,可以完美实现页面切换效果

目前只有异步组件才会触发<Suspense>状态变更。

使用Suspense

<script lang="ts" setup>
import Aysnc from "@/components/AsyncComponent.vue";
/**
 * Suspense 组件的 pending 进入挂起状态时触发
 */
 */
const pending = ()=>{
    console.log('pending')
}
/**
 * Suspense 组件的 resolve在 default 插槽完成获取新内容时触
 */
const resolve = ()=>{
    console.log('resolve')
}
/**
 * Suspense 组件的  fallback 插槽的内容显示时触发
 */
 */
const fallback = ()=>{
    console.log('fallback')
}
</script>
<template>
    <h3>测试 Supsense</h3>
    <Suspense @pending="pending" @resolve="resolve" @fallback="fallback">
        <!-- 具有深层异步依赖的组件 -->
        <aysnc />
        <!-- 在 #fallback 插槽中显示 “正在加载中” -->
        <template #fallback>
            <h1>正在加载中...</h1>
        </template>
    </Suspense>
</template>

其中,Suspense组件有三个事件分别是:

  • pending 进入挂起状态时触发
  • fallback 插槽的内容显示时触发
  • resolve default 插槽完成获取新内容时触

defineAsyncComponent

定义一个异步组件,它在运行时是懒加载的。参数可以是一个异步加载函数,或是对加载行为进行更具体定制的一个选项对象。 —— Vue异步组件

通过官方定义,从中可以得到两层意思,分别是:

  • 第一是这个函数是专门用来的定义异步组件的,其参数是一个async函数,结合ES Moduleimport()动态导入,可以快速实现懒加载组件
  • 第二是这个函数是可以从远端加载组件描述代码,而这个恰恰就是本文的重点

第一种用法就很简单了,通过 import()引入的组件会在打包的时候单独分割成一个文件,当使用的时候才会去加载。代码如下:

import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
  import('@/component/AsyncComponent.vue')
);

vite或者 Webpack 会把AsyncComponent.vue文件单独拆分打包成一个 js文件。

第二种用法是从远端服务器加载一个组件回来,然后加载成组件进行页面渲染,如下描述。

加载服务器上的组件

如果利用第二种方式去加载组件,我们最期待的代码效果如下:

<script setup>
import { defineAsyncComponent } from 'vue';
const AsyncComponent = defineAsyncComponent(() =>
    // 从服务器获取组件
    const async = await fetch('https://example.com/AsyncComponent.js')
    resolve(async)
    return async
);
// 后续可以直接在 template中使用 AsyncComponent
</script>
<template>
 <AsyncComponent />
</template>

那么AsyncComponent.js这种组件的代码应该如何生成呢?

但是,当数据还没返回来的时候,页面是不知道会渲染什么组件的。所以我们遇到第一个问题:

问题: 如何从远端加载 Vue组件,Vue通过defineAsyncComponent函数帮忙解决了加载问题,那么我们还需要知道这个函数支持加载什么格式的组件。

为了解决这个问题,我们先需要复习一下 Vue的组件基础知识

  1. 如何去定义一个组件,在 Vue 官方文档中是这么定义一个非单文件(.Vue)的组件, 如下所示:
// 选项式的组件
export default {
  data() {
    return {
      count: 0
    }
  },
  template: `
    <button @click="count++">
      You clicked me {{ count }} times.
    </button>`
}
  1. Vue组件注册知识,分为全局注册和局部注册,如下所示:

全局注册代码如下:

import { createApp } from 'vue'
import MyComponent from './App.vue'
const app = createApp({})
app.component('MyComponent', MyComponent)

局部注册如下:

<script>
import ComponentA from './ComponentA.vue'
export default {
  components: {
    ComponentA
  }
}
</script>
<template>
  <ComponentA />
</template>

复习完组件定义和注册,那么我们大概就知道如何解决【如何从远端加载Vue组件并进行注册使用?】,步骤如下:

  • 编写远端组件文件,需要符合组件的基本配置规范
  • 利用defineAsyncComponent函数异步加载组件机制去拉取远端组件
  • 解析远端组件文件内容,生成按照组件定义规范返回组件的对象resolve返回
  • 通过全局或局部注册,将defineAsyncComponent函数返回对象进行注册

示例代码如下:

  1. 制造符合组件规范的文件Async.js
// Async.js
export default {
  "template": `<h1>我是异步组件</h1><div></div><button @click="count++">\
        点击了 {{ count }} 次
      </button>`,
  "script": {
    "data": {
      "count": 0
    }
  }
}
  1. 解析组件和注册组件
<script lang="ts" setup>
...
</script>
<template>
    <h3>测试 Supsense</h3>
    <Suspense>
        <!-- 具有深层异步依赖的组件 -->
        <AsyncDD />
        <!-- 在 #fallback 插槽中显示 “正在加载中” -->
        <template #fallback>
            <h1>正在加载中...</h1>
        </template>
    </Suspense>
</template>
<script lang="ts">
import { defineAsyncComponent } from 'vue/dist/vue.esm-bundler.js';
/**
 * 加载远端+解析组件
 * @param url 
 */
const loadRemoteComponent = async (url: string) => {
    const response = await fetch(url);
    const scriptText = await response.text()
    let Component: any = '';
    try {
        const scriptStr = scriptText.replace('export default', '')
        Component = new Function('return ' + scriptStr)()
        console.log(Component)
    } catch (e) {
        console.error(e)
    }
    return Component
}
const AsyncDD = defineAsyncComponent(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            loadRemoteComponent('/async/demo.js').then((Component) => {
                resolve(Component)
            });
        }, 2000);
    });
})
export default {
    components: {
        AsyncDD
    }
}
</script>

项目实战

上述这种解决方案很明显存在问题,但是基础解决思路是没有问题,主要问题在于

  • 无法使用vue单文件
  • 无法通过import引用外部资源

如何解决呢,由于项目实战还在研究中,打算放到下一篇项目实战去解决掉,尽情期待。

参考资料

目录
相关文章
|
4月前
|
前端开发 JavaScript API
SPA与前端路由:构建无缝体验的现代前端应用
在前端开发领域,单页面应用(SPA)和前端路由成为了构建现代、高度交互性的应用程序的重要技术。本文将探讨SPA的优势以及前端路由的实践,帮助读者更好地理解如何利用这些技术来提升用户体验和开发效率。
|
监控 安全 前端开发
低代码PaaS平台源码:采用对象式和勾选式实现企业应用程序开发,内置10大功能引擎
管理后台低代码PaaS平台是一款基于 Salesforce Platform 的开源替代方案,旨在为企业提供高效、灵活、易于使用的低代码开发平台。低代码PaaS平台的10大核心引擎功能:1.建模引擎 2.移动引擎 3.流程引擎 4.页面引擎 5.报表引擎 6.安全引擎 7.API引擎 8.应用集成引擎 9.代码引擎 10.公式引擎。 采用与直接模块拖拽编程不一致的是,低代码PAAS采用的对象方式实现字段、API的字段类型,引入RPA实现表自动化建模;再使用选择方式对地段功能进行选择定义甚至可以插入代码进行自定义。采用前后端同一技术,可实现功能应用边使用边修改的功能。
低代码PaaS平台源码:采用对象式和勾选式实现企业应用程序开发,内置10大功能引擎
|
数据可视化 物联网 机器人
应用开发组件功能介绍(二)
应用开发组件功能介绍(二)
304 0
|
数据可视化 前端开发 安全
应用开发组件功能介绍(三)
应用开发组件功能介绍(三)
274 0
|
数据可视化 物联网 数据挖掘
应用开发组件功能介绍(一)
应用开发组件功能介绍(一)
262 0
|
监控 数据可视化 搜索推荐
只需简单编写配置文件即可构建企业级应用程序的低代码平台
一套可视化建模,描述式编程的企业应用程序开发平台。只需简单的点击鼠标,几乎任何人都可以创建功能强大的企业应用程序,实现业务流程自动化。企业创建的应用程序可以部署在移动,平板电脑和Web上,创建的应用程序可以很简单,也可以非常复杂,并且可以连接到几乎任何数据源。
只需简单编写配置文件即可构建企业级应用程序的低代码平台
|
数据可视化 安全 数据管理
低代码快开平台:Web可视化开发+强大流程+源码+多端支持
本套低代码PaaS平台是一款基于 Salesforce Platform 的开源替代方案,支持多种企业应用场景,包括但不限于CRM、ERP、OA、BI、IoT、大数据等。无论是传统企业还是新兴企业,都可以使用管理后台快速构建自己的应用程序和流程。
低代码快开平台:Web可视化开发+强大流程+源码+多端支持
|
Kubernetes 数据可视化 Cloud Native
【源码】低代码PaaS平台,用简单配置快速构建企业级应用程序
基于最先进的云原生技术搭建,整合了Kubernetes、微服务、Serverless、NoSQL 等最先进的技术架构,并提供了完善的自动化开发测试工具与运维管理工具。 基于moleculer 微服务架构开发,每个软件包、每个业务对象都是一个微服务,可以独立部署,独立运行。
|
缓存 安全 Linux
自建iOS构建流水线建设核心原理剖析
文章主要从iOS打包机远程构建的角度分析,整体链路脚本涉及的shell、ruby、security指令、xml以及iOS工程化相关知识,文章通过一个远程构建流程简单并重点的讲解了如何规避本地打包环境下的小的修改出包存在的大量人工操作,如何动态化配置证书、版本号等信息以及内测分发方式的避坑点。
自建iOS构建流水线建设核心原理剖析
|
敏捷开发 存储 数据可视化
低代码开发平台核心功能设计——组件自定义交互实现
笔者最近一直在研究Lowcode(低代码)平台, 也做了非常多的实践, 对于页面可视化搭建平台有了基本的研发方向和解决方案, 后期会陆续分享我对低代码平台的一些理解和解决方案, 并在企业应用层做一些探索.
1323 0