windows部署腾讯tmagic-editor02-Runtime

创建editor项目

将上一教程中的hello-world复制过来,改名hello-editor

创建runtime项目

和hello-editor同级

pnpm create vite

在这里插入图片描述
在这里插入图片描述
删除src/components/HelloWorld.vue

按钮需要用的ts types依赖

pnpm add @tmagic/schema @tmagic/stage

在这里插入图片描述

实现runtime

将hello-editor中的render函数实现移植到runtime项目中

<script setup lang="ts">
import {createApp,ref, computed} from 'vue';
import type StageCore from '@tmagic/stage';const value = ref({type: 'app',// 必须加上ID,这个id可能是数据库生成的key,也可以是生成的uuidid: 1,items: [],
});const render = async ({renderer}:StageCore) => {const root = window.document.createElement('div');const page = value.value.items[0];if (!page.value) return root;const {width = 375, height = 1700} = page.value.style || {};root.id = `${page.value.id}`;root.style.cssText = `width: ${width}px;height: ${height}px;`;createApp({template: '<div v-for="node in config.items" :key="node.id" :id="node.id">hello world</div>',props: ['config'],},{config: page.value,},).mount(root);renderer.on('onload', () => {const style = window.document.createElement('style');// 隐藏滚动条,重置默认样式style.innerHTML = `body {overflow: auto;}html,body {height: 100%; margin: 0;padding: 0;}html::-webkit-scrollbar {width: 0 !important;display: none;}`;renderer.iframe?.contentDocument?.head.appendChild(style);renderer.contentWindow?.magic?.onPageElUpdate(root);renderer.contentWindow?.magic?.onRuntimeReady({});});return root;
};
</script><template><div></div>
</template><style scoped>
</style>

新建ui-page.vue文件

<template><div v-if="config" :id="config.id" :style="style"><div v-for="node in config.items" :key="node.id" :id="node.id">hello world</div></div>
</template><script lang="ts" setup>
import { computed } from 'vue';const props = defineProps<{config: any;
}>();const style = computed(() => {const { width = 375, height = 1700 } = props.config.style || {};return {width: `${width}px`,height: `${height}px`,};
});
</script>

将以下代码覆盖到src/App.vue中

<template><uiPage :config="page"></uiPage>
</template><script lang="ts" setup>
import { ref } from 'vue';import uiPage from './ui-page.vue';const page = ref<any>();
</script>

修改vite.config.js
在这里插入图片描述

启动项目
在这里插入图片描述

修改hello-editor

删除render props,添加runtimeUrl,修改样式app.vue

<template><m-editorv-model="value":runtime-url="runtimeUrl":component-group-list="componentGroupList"></m-editor>
</template><script lang="ts" setup>
import {ref, createApp, computed} from 'vue';
import {editorService} from '@tmagic/editor';const page = computed(() => editorService.get('page'));const value = ref({type: 'app',// 必须加上ID,这个id可能是数据库生成的key,也可以是生成的uuidid: 1,items: [],
});const componentGroupList = ref([{title: '组件列表',items: [{icon: 'https://vfiles.gtimg.cn/vupload/20220614/9cc3091655207317835.png',text: 'HelloWorld',type: 'hello-world',},],},
]);const runtimeUrl = 'http://localhost:8078/';
</script><style>
#app {overflow: auto;
}html,body,#app {height: 100%; margin: 0;padding: 0;
}#app::-webkit-scrollbar {width: 0 !important;display: none;
}
</style>

在这里插入图片描述
启动hello-editor
在这里插入图片描述

跨域问题

修改editor-runtime下的vite.config.js

 server: {port: 8078, //指定端口号headers:{'Access-Control-Allow-Origin': '*',}},

runtime与editor通信

到这里项目就可以正常访问了,但是会发现添加组件没有反应。

这是因为在runtime中无法直接获取到editor中的dsl,所以需要通过editor注入到window的magic api来交互

如出现在runtime中出现magic为undefined, 可以尝试在App.vue中通过监听message,来准备获取magic注入时机,然后调用magic.onRuntimeReady,示例代码如下

window.addEventListener('message', ({ data }) => {if (!data.tmagicRuntimeReady) {return;}window.magic?.onRuntimeReady({// ...});
});

注意:这里可能会出现editor抛出message的时候,runtime还没有执行到监听message的情况 编辑器只在iframe onload事件中抛出message 如果出现runtime中接收不到message的情况,可以尝试在onMounted的时候调用magic.onRuntimeReady

修改main.js为main.ts

import { createApp } from 'vue'
import type { Magic } from '@tmagic/stage';
import './style.css';
import App from './App.vue';declare global {interface Window {magic?: Magic;}
}
createApp(App).mount('#app')

新增tsconfig.json

{"compilerOptions": {"target": "esnext","module": "esnext","strict": true,"jsx": "preserve","moduleResolution": "node","skipLibCheck": true,"esModuleInterop": true,"allowSyntheticDefaultImports": true,"forceConsistentCasingInFileNames": true,"useDefineForClassFields": true,"sourceMap": true,"baseUrl": ".","types": ["webpack-env"],"paths": {"@/*": ["src/*"]},"lib": ["esnext","dom","dom.iterable","scripthost"]},"include": ["src/**/*.ts","src/**/*.tsx","src/**/*.vue","tests/**/*.ts","tests/**/*.tsx"],"exclude": ["node_modules"]
}

src下新增shims-vue.d.ts

/* eslint-disable */
declare module '*.vue' {import type { DefineComponent } from 'vue'const component: DefineComponent<{}, {}, any>export default component
}

修改runtime下的app.vue

<template><uiPage :config="page"></uiPage>
</template><script lang="ts" setup>
import type { RemoveData, UpdateData } from '@tmagic/stage';
import type { Id, MApp, MNode } from '@tmagic/schema';
import { ref,reactive } from 'vue';
import uiPage from './ui-page.vue';
const root = ref<MApp>();const page = ref<any>();window.magic?.onRuntimeReady({/** 当编辑器的dsl对象变化时会调用 */updateRootConfig(config: MApp) {root.value = config;},/** 当编辑器的切换页面时会调用 */updatePageId(id: Id) {page.value = root.value?.items?.find((item) => item.id === id);},/** 新增组件时调用 */add({ config }: UpdateData) {const parent = config.type === 'page' ? root.value : page.value;parent.items?.push(config);},/** 更新组件时调用 */update({ config }: UpdateData) {const index = page.value.items?.findIndex((child: MNode) => child.id === config.id);page.value.items.splice(index, 1, reactive(config));},/** 删除组件时调用 */remove({ id }: RemoveData) {const index = page.value.items?.findIndex((child: MNode) => child.id === id);page.value.items.splice(index, 1);},
});
</script>

同步页面dom给编辑器

由于组件渲染在runtime中,对于编辑器来说是个黑盒,并不知道哪个dom节点才是页面(对于dsl的解析渲染可能是千奇百怪的),所以需要将页面的dom节点同步给编辑器
修改runtime下的app.vue

const pageComp = ref<InstanceType<typeof uiPage>>();watch(page, async () => {// page配置变化后,需要等dom更新await nextTick();window?.magic?.onPageElUpdate(pageComp.value?.$el);
});

以上就是一个简单runtime实现,以及与编辑的交互,这是一个不完善的实现(会发现组件再画布中无法自由拖动,是因为没有完整的解析style),但是其中已经几乎覆盖所有需要关心的内容

当前教程中实现了一个简单的page,tmagic提供了一个比较完善的实现,将在下一节介绍

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/13082.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】5.C语言函数(2)

文章目录 7.嵌套调⽤和链式访问7.1 嵌套调⽤7.2 链式访问 8.函数的声明和定义8.1 单个⽂件8.2 多个⽂件8.3 static 和 extern8.3.1 static 修饰局部变量8.3.2 static 修饰全局变量8.3.3 static 修饰函数 7.嵌套调⽤和链式访问 7.1 嵌套调⽤ 嵌套调用就是函数之间的互相调用。…

Docker安装Mosquitto

在物联网项目中&#xff0c;我们经常用到MQTT协议&#xff0c;用MQTT协议做交互就需要部署一个MQTT服务&#xff0c;而mosquitto是一个常用的MQTT应用服务&#xff0c; Mosquitto是一个实现了消息推送协议MQTT v3.1的开源消息代理软件。MQTT&#xff08;Message Queuing Teleme…

python的几个关于文本文件的demo脚本

部分来自WeTab AI PRO 1.在文末添加一行文字 def add_endline(filename, texts): # 文本末尾增加一行with open(filename, a) as file:file.write(f\n{texts})file.close() 当使用 open() 函数打开文件时&#xff0c;第二个参数指定了文件的打开模式。常见的文件打开模式包…

【LeetCode】每日一题 2024_5_14 完成所有任务需要的最少轮数(哈希)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;完成所有任务需要的最少轮数题目描述代码与解题思路 每天进步一点点 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;完成所有任务需要的最少轮数 题…

拿到测试点如何跑

首先你要知道你测试点文件的位置,然后你要创建一个接收结果的文件,将你代码中的std::cin替换成infile,std::cout替换成outfile即可 #include <fstream> int main() {// 打开输入文件std::ifstream infile("C:\\Users\\Downloads\\P4779_1.in");// 打开输出文件…

OpenCV 图像退化与增强

退化 滤波 img_averagingcv2.blur(img2,(3,3)) #均值滤波 img_median cv2.medianBlur(img2,3) #中值滤波高斯模糊 result cv2.GaussianBlur(source, (11,11), 0)高斯噪声 def add_noise_Guass(img, mean0, var0.01): # 添加高斯噪声img np.array(img / 255, dtypefloat…

麒麟 V10 安装docker2

1. 查看系统版本 2.安装docker-ce 添加源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 安装docker yum install docker-ce --allowerasing 重启docker systemctl start docker 3.安装nvidia-container-runtime 添…

el-tooltip 提示框样式修改?

【element-plus el-tooltip官网地址&#xff1a; Tooltip 文字提示 | Element Plus】 <el-tooltippopper-class"Tooltip":content"content"placement"top"effect"light" ><span class"content">{{ content }}&l…

【TypeScript的JSX简介以及使用方法】

TypeScript 是 JavaScript 的一个超集&#xff0c;它添加了静态类型检查和面向对象编程的特性。JSX 是一种 JavaScript 的语法扩展&#xff0c;主要用于 React 组件的声明性渲染。TypeScript 完美地支持 JSX&#xff0c;并允许你为 React 组件和它们的 props 添加类型注解。 T…

C中Mysql的基本api接口

一、初始化参数返回值 二、链接服务器三、执行SQL语句注意事项 四、获取结果集4.1mysql_affected_rows和mysql_num_rows4.2mysql_store_result与mysql_free_result注意事项注意事项整体的工作流程 4.3mysql_use_result&#xff08;&#xff09;4.4mysql_field_count&#xff08…

001 侧边栏 地址增删改查 默认地址代码没完善

文章目录 user_index.htmlmyaccount_style.cssmyaccount_scripts.jsaddress_edit.htmlReceiverAddressReceiverAddressControllerReceiverAddressServiceImplIReceiverAddressServiceRFshopAppApplicationServletInitializerpom.xmlReceiverAddressMapper.xmlReceiverAddressMa…

文件存储解决方案-阿里云OSS

文章目录 1.菜单分级显示问题1.问题引出1.苹果灯&#xff0c;放到节能灯下面也就是id大于1272.查看菜单&#xff0c;并没有出现苹果灯3.放到灯具下面id42&#xff0c;就可以显示 2.问题分析和解决1.判断可能出现问题的位置2.找到递归返回树形菜单数据的位置3.这里出现问题的原因…

Golang 的 unmarshal 踩坑指南

文章目录 1. 写在最前面2. 字段区分出空字段还是未设置字段2.1 问题描述2.2 解决 3. 字段支持多种类型 & 按需做不同类型处理3.1 问题描述3.2 解决 4. 碎碎念5. 参考资料 1. 写在最前面 笔者最近在实现将内部通知系统的数据定义转化为产品定义的对外提供的数据结构。 举例…

算法学习笔记(5.0)-基于比较的高效排序算法-归并排序

##时间复杂度O(nlogn) 目录 ##时间复杂度O(nlogn) ##递归实现归并排序 ##原理 ##图例 ##代码实现 ##非递归实现归并排序 ##释 #代码实现 ##递归实现归并排序 ##原理 是一种基于分治策略的基础排序算法。 1.划分阶段&#xff1a;通过不断递归地将数组从中点处分开&…

Java 开发 框架安全:Spring 命令执行漏洞.(CVE-2022-22965)

什么叫 Spring 框架. Spring 框架是一个用于构建企业级应用程序的开源框架。它提供了一种全面的编程和配置模型&#xff0c;可以简化应用程序的开发过程。Spring 框架的核心特性包括依赖注入&#xff08;Dependency Injection&#xff09;、面向切面编程&#xff08;Aspect-Or…

【SpringBoot笔记43】SpringBoot应用程序集成spring-boot-admin监控工具

这篇文章,主要介绍SpringBoot应用程序如何集成spring-boot-admin监控工具。 目录 一、spring-boot-admin监控工具 1.1、创建admin-client客户端 (1)引入依赖

DeepSpeed

文章目录 一、关于 DeepSpeed1、DeepSpeed 是什么2、深度学习训练和推理的极致速度和规模3、DeepSpeed 的四大创新支柱1&#xff09;DeepSpeed 训练2&#xff09;DeepSpeed 推理3&#xff09;DeepSpeed 压缩4&#xff09;DeepSpeed4Science 4、DeepSpeed 软件套件DeepSpeed 库推…

React 第二十七章 Hook useCallback

useCallback 是 React 提供的一个 Hook 函数&#xff0c;用于优化性能。它的作用是返回一个记忆化的函数&#xff0c;当依赖发生变化时&#xff0c;才会重新创建并返回新的函数。 在 React 中&#xff0c;当一个组件重新渲染时&#xff0c;所有的函数都会被重新创建。这可能会…

青少年软件编程(Python)等级考试试卷(五级)2024年3月

2024.03 电子学会 青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;五级&#xff09; 一、单选题 1.以下代码的输出结果是? ) nums list(range(100, 201)) print(nums[::10]) A.[100,110,120,130,140,150,160,170,180,190,200] B.[100,101,1…

QML笔记八

QML与C交互 QML中调用C功能、使用QML或者Quick中的C接口、使用C实现自定义的QML对象 注&#xff1a; 只有QObject的派生类才能与QML交互 QML引擎集成Qt元对象系统&#xff0c;QObject的派生子类的属性、方法、信号都可以在QML中访问 C类可以被注册为一个QML实例 C类可以被注册为…