当前位置: 首页 > news >正文

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.lryc.cn/news/350633.html

相关文章:

  • “分块”算法的基本要素及 build() 函数的构建细节
  • 畅捷通TPlus keyEdit.aspx、KeyInfoList.aspx SQL注入漏洞复现
  • Ubuntu22 下配置 Qt5 环境
  • 普通人也能创业!轻资产短视频带货项目,引领普通人实现创业梦想
  • 【Maven】Nexus简单使用
  • winform嵌入excel 设置父窗体分辨率不是100% 嵌入excel分辨率变成双倍大小
  • 前端系列-4 promise与async/await与fetch/axios使用方式
  • 微信公众号自定义分销商城小程序源码系统 带完整的安装代码吧以及系统部署搭建教程
  • 在另外一个页面,让另外一个页面弹框显示操作(调佣公共的弹框)vue
  • 羊毛-百度Comate领50京东E卡
  • kafka安装部署
  • VBA直连SAP RFC 接口实例
  • 2024如何挑选开放式蓝牙耳机?热门爆款熬夜整理六个点!
  • 3D数据格式转换工具HOOPS Exchange在PLM系统中的5大应用优势
  • 友元是一种允许某些外部函数或类访问另一个类的成员的机制
  • 儿童护眼台灯哪个牌子好,适合儿童使用的护眼台灯推荐
  • 在电脑本地运行llama3-8b模型
  • 深入理解 House of Cat
  • 【Linux玩物志】Linux环境开发基本工具使用(1)——vim
  • Lora训练Windows[笔记]
  • nuget局域网在线包制作,nuget打包,nuget打自己的包
  • Ubuntu 24 换国内源及原理 (阿里源)
  • python学习-使用pandas库分析excel表,并导出所需的表
  • Python中使用C扩展详解
  • llama使用tutorial微调(windows版本)
  • MyBatis操作数据库(动态SQL)
  • python发票真伪查验开发文档、票据OCR、数电票查验
  • Unity构建详解(12)——自动构建
  • 中文编程降低了中文环境下编程入门的门槛
  • 通过内网穿透免费部署我们的springboot+vue项目 实现跟服务器一样的效果