如果帮助文档可以加载组件,那么在介绍的同时就可以运行演示demo,是不是很酷?

如果可以在线修改运行代码,那么是不是更容易理解?

上一篇 https://www.cnblogs.com/jyk/p/15994934.html 介绍了一下基本功能,这里介绍一下关于代码方面的功能。

源码和演示

https://gitee.com/nfpress/nf-press-edit

https://nfpress.gitee.io/nf-press-edit/

加载组件、运行组件

Vue提供了一个可以动态加载组件的组件,component 和 defineAsyncComponent,我们可以用其实现我们想要的效果。

注册组件

我们可以参考动态路由的设置方式来注册组件:

  1. import { createRouter } from '/nf-press-edit'
  2. // 设置 axios 的 baseUrl
  3. const baseUrl = (document.location.host.includes('.gitee.io')) ?
  4. '/nf-press-edit/' : '/'
  5. export default createRouter({
  6. baseUrl,
  7. components: {
  8. testComponent: () => import('../components/testCode.vue'),
  9. testComponent2: () => import('../components/testCode2.vue')
  10. }
  11. })
  • baseUrl: 基础路由,比如要发布到 gitee.com 上,就需要根据情况设计第一级路径。
  • components: 需要加载的组件集合,key-value形式,可以注册多个组件。

这里的“路由”,只需要定义需要加载的组件即可,文档的导航路由不需要设置。

存入全局状态

nf-press 会把注册的组件存入state,便于使用:

  1. // 注册组件
  2. if (info.components) {
  3. if (Object.keys(info.components).length > 0) {
  4. const { comp } = state
  5. for(let key in components) {
  6. comp[key] = defineAsyncComponent(components[key])
  7. }
  8. }
  9. }

加载组件

然后做一个组件来加载指定的组件

  • template
  1. <Teleport :to="'#' + item.id" :disabled="moveDisabled">
  2. <el-card class="box-card">
  3. <template #header>
  4. <div class="card-header">
  5. <span>
  6. {{item.title}} &nbsp; &nbsp;
  7. </span>
  8. </div>
  9. </template>
  10. <component
  11. :is="$state.comp[item.key]"
  12. v-bind="item.props"
  13. >
  14. </component>
  15. </el-card>
  16. </Teleport>

好吧,其实只需要使用 component 来加载,el-card 是为了外观不是太难看,Teleport 是为了可以“穿越”的文档的指定位置。

组件定位

如果组件只能在文档末尾加载,那么不是太好看,所以还需要一个“定位”功能,在文档里面指定加载位置。

我们可以直接在 md 格式的文档里面加一个div,设置属性即可:

  1. <div
  2. id="test2"
  3. data-key="testComponent"
  4. data-props='{"msg":"div设置的属性"}'
  5. data-title="加载组件的测试"
  6. >
  7. 加载中
  8. </div>
  • id:注册组件时对应的key,指定要加载的组件。
  • data-key: 组件的key,要加载哪个组件。
  • data-props: 组件需要的props属性,标准json格式。
  • data-title: 组件上面显示的标题。
  • 为什么用div?

    因为还不会做 markdown-it 的插件。
  • 为什么用 data-*?

    因为只有 id 和 data-* 被保留,其他属性都被“吃掉”了。

这样在查看文档的时候,组件就会被加载到这个div里面。

看看效果

在线编写代码、修改代码、运行代码

我知道有很多第三方网站提供了完整的在线写代码的功能,一些官方文档也在用,但是总感觉有点“距离感”。因为需要点个连接打开新窗口,不知道大家有没有体验过。

对于一些简单的演示代码,还是觉得应该在一个页面内实现,所以自己做了一个简单的功能。

defineAsyncComponent

一开始用 script setup + defineAsyncComponent实现,在本地运行(开发模式)一切正常,但是发布后(生成环境)就出问题了,模板部分死活加载不上来。

改为 setup方式,不行,尝试其他方法也没有搞定。但是又不想放弃这个功能,最后只好用 CDN的方式来实现。

iframe + CDN

搞不定问题怎么办?绕过去吧。于是开启了古老的 iframe。

  1. <iframe :src="src" style="width:100%;height:100%"></iframe>
  1. import {
  2. defineComponent,
  3. watch,
  4. ref
  5. } from 'vue'
  6. import config from '../config/index.js'
  7. export default defineComponent({
  8. name: 'el-doc-runcode',
  9. inheritAttrs: false,
  10. props: {
  11. code: {
  12. type: Object,
  13. default: () => {
  14. return {
  15. id: 1,
  16. js: '',
  17. template: '',
  18. style: ''
  19. }
  20. }
  21. },
  22. reload: Boolean
  23. },
  24. setup (props) {
  25. const src = ref('')
  26. // 用 Window 传递代码
  27. if (!window.__code) {
  28. window.__code = {}
  29. }
  30. // 重新加载代码
  31. watch(() => props.reload, () => {
  32. const id = props.code.id
  33. window.__code[id] = props.code
  34. src.value = `${config.baseUrl}runcode/index.html?id=${id}&rnd=${new Date().valueOf()}`
  35. }, {immediate: true})
  36. return {
  37. src
  38. }
  39. }
  40. })

运行代码

首先用CDN加载vue.js等需要的文件,然后设置 template 和代码即可。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <link rel="icon" href="/nfwt.ico" />
  6. <link href="https://unpkg.com/element-plus@1.2.0-beta.3/dist/index.css" rel="stylesheet"/>
  7. <script src="https://unpkg.com/vue@3.2.31/dist/vue.global.js"></script>
  8. <script src="https://unpkg.com/element-plus@2.1.4/dist/index.full.js"></script>
  9. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  10. <title>运行代码</title>
  11. </head>
  12. <body>
  13. <div id="app"></div>
  14. <script >
  15. // 使用 eval编译js代码的模板
  16. const mysetup = `
  17. (function setup (props, ctx) {
  18. {{code}}
  19. })
  20. `
  21. // 接收参数
  22. const search = decodeURI(window.location.search)
  23. const id = search.split('&')[0].replace('?id=','')
  24. const code = top.window.__code[id]
  25. const temp = code.template
  26. const {
  27. defineComponent,
  28. defineAsyncComponent,
  29. ref,
  30. reactive,
  31. // 其他需要演示的功能
  32. nextTick
  33. } = Vue
  34. const App = {
  35. template: temp, // 设置模板
  36. setup (_props, _ctx) {
  37. const tmpJs = code.js // 获取js代码
  38. let fun = null // 转换后的函数
  39. try {
  40. if (tmpJs)
  41. fun = eval(mysetup.replace('{{code}}', tmpJs)) // 用 eval 把 字符串 变成js代码
  42. } catch (error) {
  43. console.error('转换出现异常:', error)
  44. }
  45. const re = typeof fun === 'function' ? fun : () => {}
  46. return {
  47. ...re(_props, _ctx) // 运行函数,解构返回对象
  48. }
  49. }
  50. }
  51. const app = Vue.createApp(App)
  52. // 挂载需要的第三方插件。
  53. app.use(ElementPlus).mount("#app")
  54. </script>
  55. </body>
  56. </html>

这样我们就可以愉快的在线写代码了。

查看效果

https://nfpress.gitee.io/nf-press-edit/1010/18_runcode

设置代码的方式

可以点右上角,切换为编辑模式,体验一下在线编写文档。好吧,有点简陋。

nf-Press —— 在线文档也可以加载组件和编写代码的更多相关文章

  1. Android浏览本地 API文档 + 解决页面加载慢的问题

    火狐浏览器安装离线浏览插件: 用浏览器打开index.html文件,你会发现加载的很慢,原因你懂的,为此,我们可以通过离线的方式 查看本地API文档,用火狐浏览器  +   Work Offline插 ...

  2. Chrome设计文档-多进程资源加载

    原文:Multi-process Resource Loading 背景 浏览器主进程及browser process处理所有的网络通信.原因有三点: Browser process可以控制每一个re ...

  3. 如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖

    <!DOCTYPE html> <html> <body> <h1>My First Web Page</h1> <p>My F ...

  4. vs2010 单文档MFC 通过加载位图文件作为客户区背景

    实现效果: 这个其实是一个非常常见的功能,大家都会考虑给自己简单的工程做一个背景界面.其实只要在view类中重载OnEraseBkgnd()这个函数就好了. 代码如下: BOOL CdddView:: ...

  5. C# 加载xml文档文件及加载xml字符串

    //创建XmlDocument对象 XmlDocument xmlDoc = new XmlDocument(); //载入xml文件名 xmlDoc.Load(filename); //如果是xml ...

  6. 在线文档预览方案-office web apps续篇

    上一篇在线文档预览方案-office web apps发布后收到很多网友的留言提问,所以准备再写一篇,一来介绍一下域控服务器安装,总结一下大家问的多的问题,二来宣传预览服务安装与技术支持的事情. 阅读 ...

  7. jQuery实现在线文档

    1.1.1 摘要 现在,许多网站都提供在线图片和图书阅读的功能,这种方式比下载后阅读来的直观和人性化,要实现该功能涉及到点击处理和图片动态加载. 在接下来的博文中,我们将通过Javascript方式实 ...

  8. 在线文档预览方案-office web apps

    最近在做项目时,要在手机端实现在线文档预览的功能.于是百度了一下实现方案,大致是将文档转换成pdf,然后在通过插件实现预览.这些方案没有具体实现代码,也没有在线预览的地址,再加上项目时间紧迫.只能考虑 ...

  9. [转载]在线文档预览方案-Office Web Apps

    最近在做项目时,要在手机端实现在线文档预览的功能.于是百度了一下实现方案,大致是将文档转换成pdf,然后在通过插件实现预览.这些方案没有具体实现代码,也没有在线预览的地址,再加上项目时间紧迫.只能考虑 ...

随机推荐

  1. having筛选结果集

    题目要求:让你输出有两科及其以上挂科(60分及格)的学生的名单? name subject score 错误的做法: mysql> select name, count(scoure<60 ...

  2. Codeforces Round #756 (Div. 3)

    本场战绩:+451 题目如下: A. Make Even time limit per test 1 second memory limit per test 256 megabytes input ...

  3. 【ybtoj】二分算法例题

    [基础算法]第三章 二分算法 例一 数列分段 题目描述 对于给定的一个长度为N的正整数数列A,现在将其分成M段,并要求每段连续,且每段和的最大值最小. 输入格式 第1行包含两个正整数N,M. 第2行包 ...

  4. suse 12 编译部署Keepalived + nginx 为 kube-apiserver 提供高可用

    文章目录 编译部署nginx 下载nginx源码包 编译nginx 配置nginx.conf 配置nginx为systemctl管理 分发nginx二进制文件和配置文件 启动kube-nginx服务 ...

  5. [题解]UVA11029 Leading and Trailing

    链接:http://vjudge.net/problem/viewProblem.action?id=19597 描述:求n^k的前三位数字和后三位数字 思路:题目要解决两个问题.后三位数字可以一边求 ...

  6. 一张图看懂IaaS, PaaS和SaaS的区别

    转至:https://blog.csdn.net/liujg79/article/details/84453736 编译:老夫子 原文:https://www.bmc.com/blogs/saas-v ...

  7. 如何在 Spring Boot 优雅关闭加入一些自定义机制

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  8. HTML学习如何布局

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...

  9. selenium+python自动化103-一闪而过的dialog如何定位

    前言 web页面操作的时候经常会遇到一闪而过的 dialog 消息,这些提示语一般只出现了几秒,过后元素节点就会在DOM中消失了. 本篇讲解下用chrome 浏览器如何定位一闪而过的 dialog 消 ...

  10. WPS:从某一页开始编号,并且奇数页偶数页页眉页脚的页码位置不同

    1.开始页的页眉页脚同时取消勾选"同前页" 此后,这一页就是以后所有页的第一页了 2.删去开始页之前所有的页眉页脚 3.页眉页脚选项中,设置奇偶页不同,其它都不用设置