如果帮助文档可以加载组件,那么在介绍的同时就可以运行演示demo,是不是很酷?
如果可以在线修改运行代码,那么是不是更容易理解?
上一篇 基于 vite2 + Vue3 写一个在线帮助文档工具 介绍了一下基本功能,这里介绍一下关于代码方面的功能。
源码和演示
nf-press-edit_帮助文档的管理平台: 在线文档的编辑环境,可以编写文档。
鍦ㄧ嚎缂栧啓甯姪鏂囨。
https://nfpress.gitee.io/nf-press-edit/
加载组件、运行组件
Vue提供了一个可以动态加载组件的组件,component 和 defineAsyncComponent,我们可以用其实现我们想要的效果。
注册组件
我们可以参考动态路由的设置方式来注册组件:
import { createRouter } from '/nf-press-edit'// 设置 axios 的 baseUrlconst baseUrl = (document.location.host.includes('.gitee.io')) ? '/nf-press-edit/' : '/'export default createRouter({ baseUrl, components: { testComponent: () => import('../components/testCode.vue'), testComponent2: () => import('../components/testCode2.vue') }})
这里的“路由”,只需要定义需要加载的组件即可,文档的导航路由不需要设置。
存入全局状态
nf-press 会把注册的组件存入state,便于使用:
// 注册组件if (info.components) { if (Object.keys(info.components).length > 0) { const { comp } = state for(let key in components) { comp[key] = defineAsyncComponent(components[key]) } }}
加载组件
然后做一个组件来加载指定的组件
<Teleport :to="'#' + item.id" :disabled="moveDisabled"> <el-card class="box-card"> <template #header> <div class="card-header"> <span> {{item.title}} </span> </div> </template> <component :is="$state.comp[item.key]" v-bind="item.props" > </component> </el-card></Teleport>
好吧,其实只需要使用 component 来加载,el-card 是为了外观不是太难看,Teleport 是为了可以“穿越”的文档的指定位置。
组件定位
如果组件只能在文档末尾加载,那么不是太好看,所以还需要一个“定位”功能,在文档里面指定加载位置。
我们可以直接在 md 格式的文档里面加一个div,设置属性即可:
<div id="test2" data-key="testComponent" data-props='{"msg":"div设置的属性"}' data-title="加载组件的测试"> 加载中</div>
因为还不会做 markdown-it 的插件。
因为只有 id 和 data-* 被保留,其他属性都被“吃掉”了。
这样在查看文档的时候,组件就会被加载到这个div里面。
看看效果
在线编写代码、修改代码、运行代码
我知道有很多第三方网站提供了完整的在线写代码的功能,一些官方文档也在用,但是总感觉有点“距离感”。因为需要点个连接打开新窗口,不知道大家有没有体验过。
对于一些简单的演示代码,还是觉得应该在一个页面内实现,所以自己做了一个简单的功能。
defineAsyncComponent
一开始用 script setup + defineAsyncComponent实现,在本地运行(开发模式)一切正常,但是发布后(生成环境)就出问题了,模板部分死活加载不上来。
改为 setup方式,不行,尝试其他方法也没有搞定。但是又不想放弃这个功能,最后只好用 CDN的方式来实现。
iframe + CDN
搞不定问题怎么办?绕过去吧。于是开启了古老的 iframe。
<iframe :src="src" style="width:100%;height:100%"></iframe>
import { defineComponent, watch, ref } from 'vue' import config from '../config/index.js' export default defineComponent({ name: 'el-doc-runcode', inheritAttrs: false, props: { code: { type: Object, default: () => { return { id: 1, js: '', template: '', style: '' } } }, reload: Boolean }, setup (props) { const src = ref('') // 用 Window 传递代码 if (!window.__code) { window.__code = {} } // 重新加载代码 watch(() => props.reload, () => { const id = props.code.id window.__code[id] = props.code src.value = `${config.baseUrl}runcode/index.html?id=${id}&rnd=${new Date().valueOf()}` }, {immediate: true}) return { src } } })
运行代码
首先用CDN加载vue.js等需要的文件,然后设置 template 和代码即可。
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" href="/nfwt.ico" /> <link href="https://unpkg.com/element-plus@1.2.0-beta.3/dist/index.css" rel="stylesheet"/> <script src="https://unpkg.com/vue@3.2.31/dist/vue.global.js"></script> <script src="https://unpkg.com/element-plus@2.1.4/dist/index.full.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>运行代码</title> </head> <body> <div id="app"></div> <script > // 使用 eval编译js代码的模板 const mysetup = ` (function setup (props, ctx) { {{code}} }) ` // 接收参数 const search = decodeURI(window.location.search) const id = search.split('&')[0].replace('?id=','') const code = top.window.__code[id] const temp = code.template const { defineComponent, defineAsyncComponent, ref, reactive, // 其他需要演示的功能 nextTick } = Vue const App = { template: temp, // 设置模板 setup (_props, _ctx) { const tmpJs = code.js // 获取js代码 let fun = null // 转换后的函数 try { if (tmpJs) fun = eval(mysetup.replace('{{code}}', tmpJs)) // 用 eval 把 字符串 变成js代码 } catch (error) { console.error('转换出现异常:', error) } const re = typeof fun === 'function' ? fun : () => {} return { ...re(_props, _ctx) // 运行函数,解构返回对象 } } } const app = Vue.createApp(App) // 挂载需要的第三方插件。 app.use(ElementPlus).mount("#app") </script> </body></html>
这样我们就可以愉快地在线写代码了。
查看效果
https://nfpress.gitee.io/nf-press-edit/1010/18_runcode
鍦ㄧ嚎缂栧啓甯姪鏂囨。
设置代码的方式
可以点右上角,切换为编辑模式,体验一下在线编写文档。好吧,有点简陋。
来源:自然框架
声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!