Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >nf-Press —— 在线文档也可以加载组件和编写代码

nf-Press —— 在线文档也可以加载组件和编写代码

作者头像
用户1174620
发布于 2022-05-09 11:40:07
发布于 2022-05-09 11:40:07
38600
代码可运行
举报
运行总次数:0
代码可运行

如果帮助文档可以加载组件,那么在介绍的同时就可以运行演示demo,是不是很酷? 如果可以在线修改运行代码,那么是不是更容易理解?

上一篇 https://cloud.tencent.com/developer/article/1997773 介绍了一下基本功能,这里介绍一下关于代码方面的功能。

源码和演示

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

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

加载组件、运行组件

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

注册组件

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { createRouter } from '/nf-press-edit'

// 设置 axios 的 baseUrl
const 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')
  }
})
  • baseUrl: 基础路由,比如要发布到 gitee.com 上,就需要根据情况设计第一级路径。
  • components: 需要加载的组件集合,key-value形式,可以注册多个组件。

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

存入全局状态

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 注册组件
if (info.components) {
  if (Object.keys(info.components).length > 0) {
    const { comp } = state
    for(let key in components) {
      comp[key] = defineAsyncComponent(components[key])
    }
  }
}

加载组件

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

  • template
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<Teleport :to="'#' + item.id" :disabled="moveDisabled">
    <el-card class="box-card">
        <template #header>
          <div class="card-header">
            <span>
              {{item.title}} &nbsp; &nbsp; 
            </span>
          </div>
        </template>
        <component
          :is="$state.comp[item.key]"
          v-bind="item.props"
        >
        </component>
    </el-card>
</Teleport>

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

组件定位

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<div
  id="test2"
  data-key="testComponent"
  data-props='{"msg":"div设置的属性"}'
  data-title="加载组件的测试"
>
  加载中
</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。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <iframe :src="src" style="width:100%;height:100%"></iframe>
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  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 和代码即可。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!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

设置代码的方式

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
基于 vite2 + Vue3 写一个在线帮助文档工具
VuePress 是“静态网站生成器”,需要我们自行编写文档,然后交给VuePress变成网站,VuePress 并没有提供编写环境,我知道有很多编写 Markdown 的方式,但是我还是喜欢编写、浏览合为“一体”的方式。
用户1174620
2022/05/09
1.4K0
Vue3 内置组件学习
我们用 vite 搭建一个 Vue3 + TS 项目,我会使用 <script setup lnag="ts"> 和<script lang="ts"> 混合编程的方式来实现
Gorit
2021/12/05
5640
Vue3 内置组件学习
基于 element-plus 封装一个依赖 json 动态渲染的查询控件 文本数字单选组的查询勾选和开关级联选择日期年、年月、年周的查询日期时间的查询快速查询自定义查询方案更多查询
使用 vue3 + element-plus 封装了一个查询控件,专为管理后台量身打造,支持各种查询需求:
用户1174620
2021/06/09
2.2K0
基于 element-plus 封装一个依赖 json 动态渲染的查询控件
    




文本数字单选组的查询勾选和开关级联选择日期年、年月、年周的查询日期时间的查询快速查询自定义查询方案更多查询
【初学者笔记】整理的一些Vue3知识点
拒绝标题党,哈哈哈,看完你就基本可以上手搞开发了,本文适合Vue初学者,或者Vue2迁移者,当然还是建议Vue3官网完全过一遍。不适合精通原理,源码的大佬们。
一尾流莺
2022/12/10
2.4K0
【初学者笔记】整理的一些Vue3知识点
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
引言 界面: Vue.js 3 JavaScript 超集: TypeScript 包管理器: pnpm 前端工程化/打包: Vite 路由: Vue Router 状态管理: Pinia CSS 预处理器: Less 代码格式化: Prettier 代码质量: ESLint 预览
yiyun
2023/07/17
1.2K0
使用 Vue 3 与 TypeScript 构建 Web 应用: Todo
浅谈低代码平台远程组件加载方案
低代码开发平台(LCDP)是无需编码(0代码)或通过少量代码就可以快速生成应用程序的开发平台。通过可视化进行应用程序开发的方法,使具有不同经验水平的开发人员可以通过图形化的用户界面,使用拖拽组件和模型驱动的逻辑来创建网页和移动应用程序。这两年越来越多的公司和开发人员开始自研低代码平台来达到降本提效的目的。今天和大家分享一下低代码平台开发过程中遇的一个问题和对应的解决思路。
CRMEB商城源码
2022/08/03
2.6K1
Vue3.x相对于Vue2.x的变化
ps: 上图中,一种颜色代表一个功能,我们可以看到Options API的功能代码比较分散;Composition API则可以将同一个功能的逻辑,组织在一个函数内部,利于维护。
conanma
2021/11/03
8960
一口气复习完 Vue3 相关基础知识点
看完你就基本可以上手搞开发了,本文适合Vue初学者,或者Vue2迁移者,当然还是建议Vue3官网完全过一遍。不适合精通原理,源码的大佬们。
前端达人
2021/09/09
2.3K0
一口气复习完 Vue3 相关基础知识点
【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs
这个是不是有点繁琐?尤其是路由的设置和菜单的配置,是不是很雷同?那么能不能简单一点呢?如果可以实现设置一次就全部搞定的话,那么是不会很香呢?
用户1174620
2022/05/26
6.3K0
【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs
Vue3 新增 API 使用
我们用 vite 搭建一个 Vue3 + TS 项目,我会使用<script setup lnag="ts">和<script lang="ts">混合编程的方式来实现
Gorit
2021/12/08
6420
Vue3 新增 API 使用
Vue组件化 模板 语法糖 函数 父子组件通信
支持:String、Number、Boolean、Array、Object、Date、Function、Symbol
有勇气的牛排
2023/06/25
2270
做个开源博客学习Vite2 + Vue3 (四)实现博客功能 管理类文件结构config设置路由设置网页入口代码入口首页、博文列表表单 发布博文博文内容 + 讨论博文分组博文列表,编
Composition API,就是组合API的意思,那么是不是应该把js代码分离出来,做成独立的管理类的形式呢?
用户1174620
2021/04/26
8890
做个开源博客学习Vite2 + Vue3 (四)实现博客功能
    




管理类文件结构config设置路由设置网页入口代码入口首页、博文列表表单 发布博文博文内容 + 讨论博文分组博文列表,编
[day-ui]DButton 组件和 DIcon 组件实现
上一篇中我们已经把组件的基础架构和文档的雏形搭建好了。下面我们从最简单的 button 和 icon 组件入手,熟悉下 vue3 的语法结构和组件的单元测试。看这篇文章前最好了解下 vue3 的语法和 compositionAPI,基本就能了解代码为何如此书写,和 vue2 有哪些不同。
测不准
2021/04/08
6030
Vue3—父子组件传值(子组件使用 emit 传值到父组件)
Vue3中,子组件通过setup函数中的第一个参数值 props 拿到定义的组件参数进行使用。如果要向父组件传参,需要使用setup函数中的第二个参数值 context(组件上下文)中的emit。
全栈程序员站长
2022/08/30
6.3K0
Vue3—父子组件传值(子组件使用 emit 传值到父组件)
Vue.js 组件的复用性:真正可复用还是伪装的可复用?
大家讨论在 Vue.js 中创建 UI 组件时,总会提到可复用性的问题。没错,Vue.js 的一大核心原则就是其基于组件的架构,相应的好处自然是有助于可复用性和模块化。但这俩时髦词汇到底该怎么理解?
深度学习与Python
2023/11/01
3780
Vue.js 组件的复用性:真正可复用还是伪装的可复用?
关于 vue3 + typescript 项目中常用的知识点汇总
在实际项目开发中,常常会遇到这么一个场景,某一个路由是不需要渲染到侧边栏导航上的,此时我们可以给该路由添加一个hidden属性来实现。
前端达人
2021/07/19
1.6K0
关于 vue3 + typescript 项目中常用的知识点汇总
使用局部状态(轻量级状态)优化博客代码
做个开源博客学习Vite2 + Vue3 (四)实现博客功能 https://www.cnblogs.com/jyk/p/14696474.html
用户1174620
2021/05/13
4590
使用局部状态(轻量级状态)优化博客代码
vue2升级vue3:Vue2/3插槽——vue3的jsx组件插槽slot怎么处理
vue 在 2.6 版本中,对插槽使用 v-slot 新语法,取代了旧语法的 slot 和 slot-scope,并且之后的 Vue 3.0 也会使用新语法,这并不是仅写法的不同,还包括了性能的提升
周陆军博客
2022/06/24
2.3K0
Vue组件(35)动态组件 component 的 is 到底可以是啥?
Vue官网上提供了一个动态组件 <component :is="currentTabComponent"> ,那么这里的 is 到底是什么呢? 官网介绍的太分散了,这里尽量全面的列举出来。如果有遗漏欢迎补充。
用户1174620
2021/04/04
9K0
Vue3学习笔记
setup等同于原data,通过reactive定义变量病赋值到data,再return出去,就可以在template用双大括号使用,计算特性:doublecounter的定义,注意需要import computed
kif
2023/03/10
1.2K0
推荐阅读
相关推荐
基于 vite2 + Vue3 写一个在线帮助文档工具
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验