vue 版本:3.3

背景:我项目里面希望给第三方提供一个页面。第三方通过网络接口的方式返回 html 代码,我程序里面把别人的 html 代码嵌入到我的页面中。

目前想到的方案:

1 、使用 v-html 标签嵌入。问题:这种方式嵌入,对方页面中如何调用我 vue 页面的方法属性呢?比如我这里有一个$http 变量是 axios 的实例,这个里面封装的验签相关处理,他必须用我这个$http 属性才能正常调用接口,不然他过不去验签。

2 、使用 vue 的异步组件。目前还没研究明白怎么用

下面是 demo 代码

```
<template>
    <div id="main">
        <el-tabs type="border-card">
        <el-tab-pane v-for="(html,name) in pluginList"  :label="name">
            // 方案 1
            <div v-html="html">

            </div>
            
            // 方案 2
            
            <AsyncComp /> // 这样写的话第二个 plugin 又叫啥名字呢?
            
        </el-tab-pane>
    </el-tabs>
    </div>
</template>

<script setup>
import { reactive, ref, getCurrentInstance } from 'vue'
const app = getCurrentInstance()
const $http = app.appContext.config.globalProperties.$http
import { defineAsyncComponent } from 'vue'


const pluginList = reactive({})

$http.get('/api/plugin/list').then(res => {
    if (res.data != null && res.data.length > 0  ) {
        pluginList[res.data] = ""
        getPlugHtml(res.data)
    }
})



const getPlugHtml = function(name){

         // 方案 1
         $http.post('/api/plugin/settings/'+name+"/index").then(res => {
                if (res.data != null && res.data!=""  ) {
                    pluginList[name] = res.data
                }else{
                    pluginList[name] = "Load Error!"
                }
            })



        // 方案 2. 但是 AsyncComp 这个名字怎么处理呢?这里换成变量以后,我模板里面的代码该怎么调用异步组件呢?
    const AsyncComp = defineAsyncComponent(() => {
        return new Promise((resolve, reject) => {
            $http.post('/api/plugin/settings/'+name+"/index").then(res => {
                if (res.data != null && res.data!=""  ) {
                    resolve(res.data)
                }else{
                    reject("Plugin Load Error!")
                }
            })
            
        })
    })



}


</script>

```
举报· 388 次点击
登录 注册 站外分享
21 条回复  
unco020511 小成 2024-7-24 18:00:46
你把所有需要桥接的对象和方法都挂载到 window 上不行吗
DesnLee 小成 2024-7-24 16:07:28
@Jinnrry #27 你这个为什么 template 包着 setup ?
linglingling 小成 2024-7-24 09:02:14
多年前端,全栈都会一些。你这个要求,既要简单,又要安全,还要通讯等等,实现不了。符合你需求的是后端模板,如 Thymeleaf 。
lisongeee 小成 2024-7-23 20:02:24
你这个是拿到的是 .vue 文件,不是编译后的 .js 代码,要不叫后端返回的时候给你编译为 js ,这样你直接用 import('/api/vue.js') 去引入

要不你就自己在前端使用 vue/compiler-sfc 将拿到的 .vue 字符串编译为组件对象
LuckyLauncher 小成 2024-7-23 19:36:07
用 webcomponent ,直接用 esm 加载这个定义了 webcomponent 的 js 文件,然后 v-html 渲染这个 webcomponent 标签,不过这种方案三方的权限很大,如果你需要管控还是需要微前端
asdjgfr 小成 2024-7-23 19:19:31
用 CustomEvent 不就好了: https://developer.mozilla.org/zh-CN/docs/Web/API/CustomEvent/CustomEvent
ipwx 小成 2024-7-23 18:31:50
你不如在这个组件里面

onMounted(() => window.pluginContext = {'$html': $html, ... 任何你想要传递的属性});

然后在你的插件里面通过 window.pluginContext 拿到上下文。
bladey 小成 2024-7-23 18:10:26
<el-tabs v-model="activeName">
      <el-tab-pane v-for="(html, name) in pluginList"  :label="name">
        <component :is="asyncCpt" :http="$http" />
      </el-tab-pane>
</el-tabs>

const activeName = ref('');
const asyncCpt = ref(null);
watch(activeName, async (newVal) => {
  asyncCpt.value = defineAsyncComponent(() => {
    return new Promise((resolve, reject) => {
      $http.post('/api/plugin/settings/' + newVal + '/index').then((res) => {
        if (res.data != null && res.data != '') {
          resolve(res.data);
        } else {
          reject('Plugin Load Error!');
        }
      });
    });
  });
});
ccSir 小成 2024-7-23 18:06:02
或者可以让第三方用 h() 创建组件,然后你封装一些方法供第三方调用就行。通过接口返回第三方写的 h() 在通过 defineComponent 创建组件,传入你自己定义的方法。
duanxianze 小成 2024-7-23 17:35:12
不想麻烦直接挂载全局就行了  稍微复杂一些就是提供一个 js 文件,里面封装你要提供的 API ,更复杂就是搞微前端,或者服务端渲染
123下一页
返回顶部