diff --git a/docs/src/tutorial/hello-world.md b/docs/src/tutorial/hello-world.md index 07a2d5df..441e6b4e 100644 --- a/docs/src/tutorial/hello-world.md +++ b/docs/src/tutorial/hello-world.md @@ -4,7 +4,7 @@ 使用[@vue/cli](https://cli.vuejs.org/zh/guide/installation.html)初始化项目 -``` +```bash npm install -g @vue/cli ``` @@ -24,7 +24,7 @@ npm install -g @vue/cli [关于@vue/cli的详细教程可以查看官方文档](https://cli.vuejs.org/zh/guide/installation.html) -``` +```bash vue create hello-world cd hello-world @@ -50,7 +50,7 @@ cd hello-world ## 添加依赖 -``` +```bash npm install --save @tmagic/editor @tmagic/form element-plus ``` @@ -119,7 +119,7 @@ body { ## 运行项目 -``` +```bash npm run serve ``` diff --git a/docs/src/tutorial/runtime.md b/docs/src/tutorial/runtime.md index 77d609fb..c15f3ce7 100644 --- a/docs/src/tutorial/runtime.md +++ b/docs/src/tutorial/runtime.md @@ -1 +1,203 @@ -# 2.Runtime \ No newline at end of file +# 2.Runtime + +## 创建项目 + +[关于@vue/cli的详细教程可以查看官方文档](https://cli.vuejs.org/zh/guide/installation.html) + +### 创建editor项目 + +将[上一教程](./hello-world.md)中的[hello-world](https://github.com/jia000/tmagic-tutorial/tree/master/course1/hello-world)复制过来,改名hello-editor + + +### 创建runtime项目 + +```bash +vue create editor-runtime + +cd editor-runtime +``` + +删除src/components/HelloWorld.vue + +## 实现runtime + +将hello-editor中的render函数实现移植到runtime项目中 + +新建ui-page.vue文件 + +```vue + + + +``` + +将以下代码覆盖到src/App.vue中 + +```vue + + + +``` + +## 启动runtime + +```bash +npm run serve -- --port=8078 +``` + +## 修改editor + +删除render props,添加runtimeUrl + +修改样式 + +```vue + + + + + +``` + +## 启动editor + +```bash +cd hello-editor + +npm run serve -- --port=8080 +``` + +## 跨域问题 + +在editor-runtime项目下的vue.config.js中添加如下配置 + +```javascript +devServer: { + headers: { + 'Access-Control-Allow-Origin': '*', + }, +}, +``` + +## runtime与editor通信 + +到这里项目就可以正常访问了,但是会发现添加组件没有反应。 + +这是因为在runtime中无法直接获取到editor中的dsl,所以需要通过editor注入到window的magic api来交互 + +在App.vue中通过监听message,来准备知道magic注入时机,然后调用magic.onRuntimeReady,示例代码如下 + +```ts +const root = ref(); + +window.addEventListener('message', ({ data }) => { + if (!data.tmagicRuntimeReady) { + return; + } + + (window as any).magic?.onRuntimeReady({ + /** 当编辑器的dsl对象变化时会调用 */ + updateRootConfig(config: any) { + root.value = config; + }, + + /** 当编辑器的切换页面时会调用 */ + updatePageId(id: string) { + page.value = root.value?.items?.find((item: any) => item.id === id); + }, + + /** 新增组件时调用 */ + add({ config }: any) { + const parent = config.type === 'page' ? root.value : page.value; + parent.items?.push(config); + }, + + /** 更新组件时调用 */ + update({ config }: any) { + const index = page.value.items?.findIndex((child: any) => child.id === config.id); + page.value.items.splice(index, 1, reactive(config)); + }, + + /** 删除组件时调用 */ + remove({ id }: any) { + const index = page.value.items?.findIndex((child: any) => child.id === id); + page.value.items.splice(index, 1); + }, + }); +}); + +``` + +## 同步页面dom给编辑器 + +由于组件渲染在runtime中,对于编辑器来说是个黑盒,并不知道哪个dom节点才是页面(对于dsl的解析渲染可能是千奇百怪的),所以需要将页面的dom节点同步给编辑器 + +```ts +watch(page, async () => { + // page配置变化后,需要等dom更新 + await nextTick(); + (window as any).magic.onPageElUpdate(pageComp.value?.$el); +}); +``` + +以上就是一个简单runtime实现,以及与编辑的交互,这是一个不完善的实现,但是其中已经几乎覆盖所有需要关心的内容 + +当前教程中实现了一个简单的page,tmagic提供了一个比较完善的实现,将在下一节介绍