基于vite2+Vue3編寫(xiě)一個(gè)在線幫助文檔工具
提起幫助文檔,想必大家都會(huì)想到 VuePress等,我也體驗(yàn)了一下,但是感覺(jué)和我的思路不太一樣,我希望的是那種可以直接在線編輯文檔,然后無(wú)需編譯就可以直接發(fā)布的方式,另外可以在線寫(xiě)(修改)代碼并且運(yùn)行的效果。
VuePress 是“靜態(tài)網(wǎng)站生成器”,需要我們自行編寫(xiě)文檔,然后交給VuePress變成網(wǎng)站,VuePress 并沒(méi)有提供編寫(xiě)環(huán)境,我知道有很多編寫(xiě) Markdown 的方式,但是我還是喜歡編寫(xiě)、瀏覽合為**“一體”**的方式。
似乎沒(méi)有,那么 —— 自己動(dòng)手豐衣足食吧,開(kāi)干!
技術(shù)棧
- vite: ^2.7.0
- vue: ^3.2.23
- axios: ^0.25.0 獲取json格式的配置和文檔
- element-plus: ^2.0.2 UI庫(kù)
- nf-ui-elp": ^0.1.0 二次封裝的UI庫(kù)
- @element-plus/icons-vue: ^0.2.4 圖標(biāo)
- @kangc/v-md-editor:"^2.3.13 md 編輯器
- vite-plugin-prismjs: ^0.0.8 代碼高亮
- nf-state": ^0.2.4 狀態(tài)管理
- nf-web-storage": ^0.2.3 訪問(wèn) indexedDB
建立庫(kù)項(xiàng)目(@naturefw/press-edit)實(shí)現(xiàn)文檔的編寫(xiě)、瀏覽功能
首先使用 vite2 建立一個(gè) Vue3 的項(xiàng)目:
- 安裝 elementPlus 實(shí)現(xiàn)頁(yè)面效果;
- 安裝 v-md-editor 實(shí)現(xiàn) Markdown 的編輯和顯示;
- 安裝 @naturefw/storage 操作 indexedDB ,實(shí)現(xiàn)幫助文檔的存儲(chǔ);
- 安裝 @naturefw/nf-state 實(shí)現(xiàn)狀態(tài)管理;
- 安裝axios 用于加載 json文件,實(shí)現(xiàn)導(dǎo)入功能。
- 用node寫(xiě)一個(gè)后端API,實(shí)現(xiàn)寫(xiě)入json文件的功能。
注意:庫(kù)項(xiàng)目需要安裝以上插件,幫助文檔項(xiàng)目只需要安裝 @naturefw/press-edit 即可。
基本功能就是這樣,心急的可以先看在線演示和源碼。
編輯頁(yè)面

瀏覽頁(yè)面

兩個(gè)狀態(tài):編輯和瀏覽
一開(kāi)始做了兩個(gè)項(xiàng)目,分別實(shí)現(xiàn)編輯文檔和顯示文檔的功能,但是后來(lái)發(fā)現(xiàn),內(nèi)部代碼大部分是相同的,維護(hù)的時(shí)候有點(diǎn)麻煩,所以改為在編輯文檔的項(xiàng)目里加入“瀏覽”的狀態(tài),然后設(shè)置切換的功能,這樣便于內(nèi)部代碼的維護(hù),以后成熟了可能會(huì)分為兩個(gè)單獨(dú)的項(xiàng)目。
編輯狀態(tài)的功能
- 菜單維護(hù)
- 文檔維護(hù)
- 文檔展示
- 導(dǎo)入導(dǎo)出
- 在線編寫(xiě)/執(zhí)行代碼
我喜歡在線編輯的方式,這樣更省心,于是我用 el-menu 實(shí)現(xiàn)導(dǎo)航和左側(cè)的菜單,然后加上了維護(hù)功能。 使用 v-md-editor 實(shí)現(xiàn) Markdown 的編輯和顯示。 然后用node寫(xiě)了一個(gè)后端API,實(shí)現(xiàn)保存 json文件的功能,這樣就完美了。
瀏覽狀態(tài)的功能
- 導(dǎo)航
- 菜單
- 文檔展示
- 執(zhí)行代碼
就是在編輯狀態(tài)的功能的基礎(chǔ)上,去掉一些功能?;蛘咂鋵?shí)可以反過(guò)來(lái)思考。
實(shí)現(xiàn)導(dǎo)航
首先參考 VuePress 設(shè)置一個(gè)json文件,用于加載和保存網(wǎng)站信息、導(dǎo)航信息。
/public/docs/.nfpress/project.json
{
"projectId": "1000",
"title": "nf-press-edit !",
"description": "這是一個(gè)在線編輯、展示文檔的小工具",
"navi": [
{
"naviId": "1010",
"text": "指南",
"link": "menu"
},
{
"naviId": "1020",
"text": "組件",
"link": "menu"
},
{
"naviId": "1380",
"text": "Gitee",
"link": "https://gitee.com/nfpress/nf-press-edit"
},
{
"naviId": "1390",
"text": "在線演示",
"link": "https://nfpress.gitee.io/nf-press-edit/"
},
{
"naviId": "1395",
"text": "我要提意見(jiàn)",
"link": "https://gitee.com/nfpress/nf-press-edit/issues"
}
]
}- projectId:項(xiàng)目ID,可以用于區(qū)分不同的幫助文檔項(xiàng)目。
- navi: 存放導(dǎo)航項(xiàng)。
- naviId: 關(guān)聯(lián)到菜單。
- text: 導(dǎo)航上顯示的文字。
- link: 連接方式或鏈接地址。menu:表示要打開(kāi)對(duì)應(yīng)的菜單;URL:在新頁(yè)面里打開(kāi)連接。
然后做一個(gè)組件,用 el-menu 綁定數(shù)據(jù)渲染出來(lái)即可實(shí)現(xiàn)導(dǎo)航效果。
/lib/navi/navi.vue
<el-menu
:default-active="activeIndex2"
class="el-menu-demo"
mode="horizontal"
v-bind="$attrs"
:background-color="backgroundColor"
@select="handleSelect"
>
<el-menu-item
v-for="(item, index) in naviList"
:key="index"
:index="item.naviId"
>
{{item.text}}
</el-menu-item>
</el-menu>可以是多級(jí)的導(dǎo)航,暫時(shí)沒(méi)有實(shí)現(xiàn)在線維護(hù)功能。
import { ref } from 'vue'
import { ElMenu, ElMenuItem } from 'element-plus'
import { state } from '@naturefw/nf-state'
const props = defineProps({
'background-color': { // 默認(rèn)背景色
type: String,
default: '#ece5d9'
},
itemProps: Object
})
// 獲取狀態(tài)和導(dǎo)航內(nèi)容
const { current, naviList } = state
// 激活第一個(gè)導(dǎo)航項(xiàng)
const activeIndex2 = ref(naviList[0].naviId)
const handleSelect = (key, keyPath) => {
const navi = naviList.find((item) => item.naviId === key)
if (navi.link === 'menu') {
// 打開(kāi)菜單
current.naviId = key
} else {
// 打開(kāi)連接
window.open(navi.link, '_blank')
}
}@naturefw/nf-state
自己寫(xiě)的一個(gè)輕量級(jí)狀態(tài)管理,可以當(dāng)做大號(hào) reactive 來(lái)使用,通過(guò)狀態(tài)管理加載 project.json 然后綁定渲染。
naviList
導(dǎo)航列表,由狀態(tài)管理加載。
current
當(dāng)前激活的各種信息,比如“current.naviId”表示激活的導(dǎo)航項(xiàng)。
實(shí)現(xiàn)菜單
和導(dǎo)航類(lèi)似,只是需要增加兩個(gè)功能:n級(jí)分組和維護(hù)。
首先參考 VuePress 設(shè)置一個(gè)json文件,保存菜單信息。
/public/docs/.nfpress/menu.json
[
{
"naviId": "1010",
"menus": [
{
"menuId": "110100",
"text": "介紹",
"description": "描述",
"icon": "FolderOpened",
"children": []
},
{
"menuId": "111100",
"text": "快速上手",
"description": "描述",
"icon": "FolderOpened",
"children": [
{
"menuId": 111120,
"text": "編輯文檔項(xiàng)目",
"description": "",
"icon": "UserFilled",
"children": []
},
{
"menuId": 111130,
"text": "展示文檔項(xiàng)目",
"description": "",
"icon": "UserFilled"
}
]
}
],
"ver": 1.6
},
{
"naviId": "1020",
"menus": [
{
"menuId": "21000",
"text": "導(dǎo)航(docNavi)",
"description": "描述",
"icon": "Star",
"children": []
}
],
"ver": 1.5
}
]- naviId: 關(guān)聯(lián)導(dǎo)航項(xiàng)ID,可以是數(shù)字,也可以是其他字符。需要和導(dǎo)航項(xiàng)ID對(duì)應(yīng)。
- menus: 導(dǎo)航項(xiàng)對(duì)應(yīng)的菜單項(xiàng)集合。
- menuId: 菜單項(xiàng)ID,關(guān)聯(lián)一個(gè)文檔,可以是數(shù)字或者英文。
- text: 菜單項(xiàng)名稱。
- description: 描述,考慮以后用于查詢。
- icon: 菜單使用的圖標(biāo)名稱。
- children: 子菜單項(xiàng)目,沒(méi)有的話可以去掉。
- ver: 版本號(hào),便于更新文檔。
然后用 el-menu 綁定數(shù)據(jù)渲染,因?yàn)橐獙?shí)現(xiàn)n級(jí)分組,所以做一個(gè)遞歸組件實(shí)現(xiàn)n級(jí)菜單的效果。
實(shí)現(xiàn)n級(jí)分組菜單
做一個(gè)遞歸組件實(shí)現(xiàn)n級(jí)分組的功能:
/lib/menu/menu-sub-edit.vue
<template v-for="(item, index) in subMenu">
<!--樹(shù)枝-->
<template v-if="item.children && item.children.length > 0">
<el-sub-menu
:key="item.menuId + '_' + index"
:index="item.menuId"
style="vertical-align: middle;"
>
<template #title>
<div style="display:inline;width: 100%;">
<component
:is="$icon[item.icon]"
style="width: 1.5em; height: 1.5em; margin-right: 8px;vertical-align: middle;"
>
</component>
<span>{{item.text}}</span>
</div>
</template>
<!--遞歸子菜單-->
<my-sub-menu2
:subMenu="item.children"
:dialogAddInfo="dialogAddInfo"
:dialogModInfo="dialogModInfo"
/>
</el-sub-menu>
</template>
<!--樹(shù)葉-->
<el-menu-item v-else
:index="item.menuId"
:key="item.menuId + 'son_' + index"
>
<template #title>
<div style="display:inline;width: 100%;">
<span style="float: left;">
<component
:is="$icon[item.icon]"
style="width: 1.5em; height: 1.5em; margin-right: 8px;vertical-align: middle;"
>
</component>
<span >{{item.text}}</span>
</span>
</div>
</template>
</el-menu-item>
</template> import { ElMenuItem, ElSubMenu } from 'element-plus'
// 展示子菜單 - 遞歸
import mySubMenu2 from './menu-sub.vue'
const props = defineProps({
subMenu: Array, // 要顯示的菜單,可以n級(jí)
dialogAddInfo: Object, // 添加菜單
dialogModInfo: Object // 修改菜單
})- subMenu 要顯示的子菜單項(xiàng)
- dialogAddInfo 添加菜單的信息
- dialogModInfo 修改菜單的信息
實(shí)現(xiàn)菜單的維護(hù)功能
這個(gè)就比較簡(jiǎn)單了,做個(gè)表單實(shí)現(xiàn)菜單的增刪改即可,篇幅有限跳過(guò)。
實(shí)現(xiàn) Markdown 的編輯
使用 v-md-editor 實(shí)現(xiàn) Markdown 的編輯和展示,首先該插件非常好用,其次支持VuePress的主題。
建立 /lib/md/md-edit.vue 實(shí)現(xiàn)編輯 Markdown 的功能:
<v-md-editor
:toolbar="toolbar"
left-toolbar="undo redo clear | tip emoji code | h bold italic strikethrough quote | ul ol table hr | link image | save | customToolbar"
:include-level="[1, 2, 3, 4]"
v-model="current.docInfo.md"
:height="editHeight + 'px'"
@save="mySave"
>
</v-md-editor> import { watch,ref } from 'vue'
import { ElMessage, ElRadioGroup, ElRadioButton } from 'element-plus'
import mdController from '../service/md.js'
// 狀態(tài)
import { state } from '@naturefw/nf-state'
// 獲取當(dāng)前激活的信息
const current = state.current
// 文檔的加載和保存
const { loadDocById, saveDoc } = mdController()
// 可見(jiàn)的高度
const editHeight = document.documentElement.clientHeight - 200
// 單擊 保存 按鈕,實(shí)現(xiàn)保存功能
const mySave = (text, html) => {
saveDoc(current)
}
// 定時(shí)保存
let timeout = null
let isSaved = true
const timeSave = () => {
if (isSaved) {
// 保存過(guò)了,重新計(jì)時(shí)
isSaved = false
} else {
return // 有計(jì)時(shí),退出
}
timeout = setTimeout(() => {
// 保存文檔
saveDoc(current).then(() => {
ElMessage({
message: '自動(dòng)保存文檔成功!',
type: 'success',
})
})
isSaved = true
}, 10000)
}
// 定時(shí)保存文檔
watch(() => current.docInfo.md, () => {
timeSave()
})
// 根據(jù)激活的菜單項(xiàng),加載對(duì)應(yīng)的文檔
watch( () => current.menuId, async (id) => {
const ver = current.ver
loadDocById(id, ver).then((res) => {
// 找到了文檔
Object.assign(current.docInfo, res)
}).catch((res) => {
// 沒(méi)有文檔
Object.assign(current.docInfo, res)
})
})- mdController 實(shí)現(xiàn)文檔的增刪改查的controller
- timeSave 定時(shí)保存文檔,避免忘記點(diǎn)保存按鈕
是不是挺簡(jiǎn)單的。
實(shí)現(xiàn)在線編寫(xiě)代碼并且運(yùn)行的功能
因?yàn)槭腔赩ue3建立的項(xiàng)目,而且也是為了寫(xiě)vue3相關(guān)的幫助文檔,那么就有一個(gè)很實(shí)用的要求:在線寫(xiě)代碼并且可以運(yùn)行。
個(gè)人感覺(jué)這個(gè)功能還是很實(shí)用的,我知道有第三方網(wǎng)站提供了這種功能,但是網(wǎng)速有點(diǎn)慢,另外有一種大炮打蚊子的感覺(jué),我只需要實(shí)現(xiàn)簡(jiǎn)單的代碼演示。
于是我基于 vue 的 defineAsyncComponent 寫(xiě)了一個(gè)簡(jiǎn)單版的在線編寫(xiě)代碼且運(yùn)行的功能:
/lib/runCode/run.vue
<div style="padding: 5px; border: 1px solid #ccc!important;">
<async-comp></async-comp>
</div> import {
defineAsyncComponent,
ref, reactive,...
// 其他常用的vue內(nèi)置指令
} from 'vue'
// 使用 eval編譯js代碼
const mysetup = `
(function setup () {
{[code]}
})
`
// 通過(guò)屬性傳入需要運(yùn)行的代碼和模板
const props = defineProps({
code: {
type: Object,
default: () => {
return {
js: '',
template: '',
style: ''
}
}
}
})
const code = props.code
// 使用 defineAsyncComponent 讓代碼運(yùn)行起來(lái)
const AsyncComp = defineAsyncComponent(
() => new Promise((resolve, reject) => {
resolve({
template: code.template, // 設(shè)置模板
style: [code.style], // 大概是樣式設(shè)置,但是好像沒(méi)啥效果
setup: (props, ctx) => {
const tmpJs = code.js // 獲取js代碼
let fun = null // 轉(zhuǎn)換后的函數(shù)
try {
if (tmpJs)
fun = eval(mysetup.replace('{[code]}', tmpJs)) // 用 eval 把 字符串 變成 函數(shù)
} catch (error) {
console.error('轉(zhuǎn)換出現(xiàn)異常:', error)
}
const re = typeof fun === 'function' ? fun : () => {}
return {
...re(props, ctx) // 運(yùn)行函數(shù),解構(gòu)返回對(duì)象
}
}
})
})
)- defineAsyncComponent
實(shí)用 defineAsyncComponent 加載組件,需要設(shè)置三個(gè)部分:模板、setup和style。
- template: 字符串形式,可以直接傳入
- setup: js代碼,可以用eval的方式進(jìn)行動(dòng)態(tài)編譯。
- style: 可以設(shè)置樣式。
這樣即可讓在線編寫(xiě)的代碼運(yùn)行起來(lái),當(dāng)然功能有限,只能用于一些簡(jiǎn)單的代碼演示。
導(dǎo)出
以上這些功能都是基于 indexedDB 進(jìn)行的,想要發(fā)布的話,需要先導(dǎo)出為json文件。
因?yàn)闉g覽器里不能直接寫(xiě)文件,所以需要使用折中的方式:
- 復(fù)制粘貼
- 下載
- 導(dǎo)出
復(fù)制粘貼
這個(gè)簡(jiǎn)單,用文本域顯示json即可。
下載
使用 chrome 瀏覽器提供的下載功能下載文件。
const uri = 'data:text/json;charset=utf-8,\ufeff' + encodeURIComponent(show.navi)
//通過(guò)創(chuàng)建a標(biāo)簽實(shí)現(xiàn)
var link = document.createElement("a")
link.href = uri
//對(duì)下載的文件命名
link.download = fileName
document.body.appendChild(link)
link.click()
document.body.removeChild(link)以上介紹的是內(nèi)部原理,如果只是想簡(jiǎn)單使用的話,可以跳過(guò),直接看下面的介紹。
用后端寫(xiě)文件
以上兩種都不太方便,于是用node做了個(gè)簡(jiǎn)單的后端API,用于實(shí)現(xiàn)寫(xiě)入json文件的功能。
代碼放在了 api文件夾里,可以使用 yarn api運(yùn)行。當(dāng)然需要在 package.json 里做一下設(shè)置。
"scripts": {
"dev": "vite",
"build": "vite build --mode project",
"lib": "vite build --mode lib",
"serve": "vite preview",
"api": "node api/server.js"
},實(shí)現(xiàn)一個(gè)幫助文檔的項(xiàng)目
上面介紹的是庫(kù)項(xiàng)目的基本原理,我們要做幫助文檔的時(shí)候,并不需要那么復(fù)雜。
使用 vite2 建立一個(gè)vue3的項(xiàng)目,然后安裝 @naturefw/press-edit,使用提供的組件即可方便的實(shí)現(xiàn)。
main.js
首先需要在 main.js 里面做一些設(shè)置。
import { createApp } from 'vue'
import App from './App.vue'
// 設(shè)置 axios 的 baseUrl
const baseUrl = (document.location.host.includes('.gitee.io')) ?
'/doc-ui-core/' : '/'
// 輕量級(jí)狀態(tài)
// 設(shè)置 indexedDB 數(shù)據(jù)庫(kù),存放文檔的各種信息。
import { setupIndexedDB, setupStore } from '@naturefw/press-edit'
// 初始化 indexedDB 數(shù)據(jù)庫(kù)
setupIndexedDB(baseUrl)
// UI庫(kù)
import ElementPlus from 'element-plus'
// import 'element-plus/lib/theme-chalk/index.css'
// import 'dayjs/locale/zh-cn'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 二次封裝
import { nfElementPlus } from '@naturefw/ui-elp'
// 設(shè)置icon
import installIcon from './icon/index.js'
// 設(shè)置 Markdown 的配置函數(shù)
import setMarkDown from './main-md.js'
// 主題
import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js'
const {
VueMarkdownEditor, // Markdown 的編輯器
VMdPreview // Markdown 的瀏覽器
} = setMarkDown(vuepressTheme)
const app = createApp(App)
app.config.globalProperties.$ELEMENT = {
locale: zhCn,
size: 'small'
}
app.use(setupStore) // 狀態(tài)管理
.use(nfElementPlus) // 二次封裝的組件
.use(installIcon) // 注冊(cè)全局圖標(biāo)
.use(ElementPlus, { locale: zhCn, size: 'small' }) // UI庫(kù)
.use(VueMarkdownEditor) // markDown編輯器
.use(VMdPreview) // markDown 顯示
.mount('#app')- baseUrl: 根據(jù)發(fā)布平臺(tái)的情況進(jìn)行設(shè)置,比如這里需要設(shè)置為:“/doc-ui-core/”
- setupIndexedDB: 初始化 indexedDB 數(shù)據(jù)庫(kù)
- setupStore: 設(shè)置狀態(tài)
- element-plus:element-plus 可以不掛載,但是css需要 import 進(jìn)來(lái),這里采用CDN的方式引入。
- nfElementPlus: 二次封裝的組件,便于實(shí)現(xiàn)增刪改查。
- setMarkDown: 加載 v-md-editor ,以及需要的插件。
- vuepressTheme: 設(shè)置主題。
設(shè)置 Markdown
因?yàn)?v-md-editor 相關(guān)設(shè)置比較多,所以設(shè)置了一個(gè)單獨(dú)文件進(jìn)行管理:
/src/main-md.js
// Markdown 編輯器
import VueMarkdownEditor from '@kangc/v-md-editor'
import '@kangc/v-md-editor/lib/style/base-editor.css'
// 在這里引入,不被識(shí)別?
// import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js'
import '@kangc/v-md-editor/lib/theme/style/vuepress.css'
// 代碼高亮
import Prism from 'prismjs'
// emoji
import createEmojiPlugin from '@kangc/v-md-editor/lib/plugins/emoji/index'
import '@kangc/v-md-editor/lib/plugins/emoji/emoji.css'
// 流程圖
// import createMermaidPlugin from '@kangc/v-md-editor/lib/plugins/mermaid/cdn'
// import '@kangc/v-md-editor/lib/plugins/mermaid/mermaid.css'
// todoList
import createTodoListPlugin from '@kangc/v-md-editor/lib/plugins/todo-list/index'
import '@kangc/v-md-editor/lib/plugins/todo-list/todo-list.css'
// 代碼行號(hào)
import createLineNumbertPlugin from '@kangc/v-md-editor/lib/plugins/line-number/index';
// 高亮代碼行
import createHighlightLinesPlugin from '@kangc/v-md-editor/lib/plugins/highlight-lines/index'
import '@kangc/v-md-editor/lib/plugins/highlight-lines/highlight-lines.css'
// 復(fù)制代碼
import createCopyCodePlugin from '@kangc/v-md-editor/lib/plugins/copy-code/index'
import '@kangc/v-md-editor/lib/plugins/copy-code/copy-code.css'
// markdown 顯示器
import VMdPreview from '@kangc/v-md-editor/lib/preview'
// import '@kangc/v-md-editor/lib/style/preview.css'
/**
* 設(shè)置 Markdown 編輯器 和瀏覽器
* @param {*} vuepressTheme
* @returns
*/
export default function setMarkDown (vuepressTheme) {
// 設(shè)置 vuePress 主題
VueMarkdownEditor.use(vuepressTheme,
{
Prism,
extend(md) {
// md為 markdown-it 實(shí)例,可以在此處進(jìn)行修改配置,并使用 plugin 進(jìn)行語(yǔ)法擴(kuò)展
// md.set(option).use(plugin);
},
}
)
// 預(yù)覽
VMdPreview.use(vuepressTheme,
{
Prism,
extend(md) {
// md為 markdown-it 實(shí)例,可以在此處進(jìn)行修改配置,并使用 plugin 進(jìn)行語(yǔ)法擴(kuò)展
// md.set(option).use(plugin);
},
}
)
// emoji
VueMarkdownEditor.use(createEmojiPlugin())
// 流程圖
// VueMarkdownEditor.use(createMermaidPlugin())
// todoList
VueMarkdownEditor.use(createTodoListPlugin())
// 代碼行號(hào)
VueMarkdownEditor.use(createLineNumbertPlugin())
// 高亮代碼行
VueMarkdownEditor.use(createHighlightLinesPlugin())
// 復(fù)制代碼
VueMarkdownEditor.use(createCopyCodePlugin())
// 預(yù)覽的插件
VMdPreview.use(createEmojiPlugin())
VMdPreview.use(createTodoListPlugin())
VMdPreview.use(createLineNumbertPlugin())
VMdPreview.use(createHighlightLinesPlugin())
VMdPreview.use(createCopyCodePlugin())
return {
VueMarkdownEditor,
VMdPreview
}
}不多介紹了,可以根據(jù)需要選擇插件。
布局
在App.vue文件里面進(jìn)行整體布局
<el-container>
<el-header>
<!--導(dǎo)航-->
<div style="float: left;">
<!--寫(xiě)網(wǎng)站logo、標(biāo)題等-->
<h1>nf-press</h1>
</div>
<div style="float: right;min-width: 100px;height: 60px;padding-top: 13px;">
<!--寫(xiě)網(wǎng)站logo、標(biāo)題等-->
<el-switch v-model="$state.current.isView" v-bind="itemProps"></el-switch>
</div>
<div style="float: right;min-width: 600px;height: 60px;">
<!--網(wǎng)站導(dǎo)航-->
<doc-navi ></doc-navi>
</div>
</el-header>
<el-container>
<!--左側(cè)邊欄-->
<el-aside width="330px">
<!--菜單-->
<doc-menu ></doc-menu>
</el-aside>
<el-main>
<!--文檔區(qū)域-->
<component
:is="docControl[$state.current.isView]"
/>
</el-main>
</el-container>
</el-container> import { reactive, defineAsyncComponent } from 'vue'
import { ElHeader, ElContainer ,ElAside, ElMain } from 'element-plus'
import { docMenu, docNavi, config } from '@naturefw/press-edit' // 菜單 導(dǎo)航
import docView from './views/doc.vue' // 顯示文檔
// 加載菜單子控件
const docControl = {
true: docView,
false: defineAsyncComponent(() => import('./views/main.vue')) // 修改文檔
}
const itemProps = reactive({
'inline-prompt': true,
'active-text': '看',
'inactive-text': '寫(xiě)',
'active-color': '#378FEB',
'inactive-color': '#EA9712'
})- $state:全局狀態(tài),$state.current.isView 設(shè)置是否是瀏覽狀態(tài)。
- doc-navi:導(dǎo)航組件
- doc-menu:菜單組件
- docControl:根據(jù)狀態(tài)選擇加載顯示組件或者編輯組件的字典。
這種方式雖然有點(diǎn)麻煩,但是比較靈活,可以根據(jù)需要進(jìn)行各種靈活設(shè)置,比如添加版權(quán)信息、備案信息、廣告等內(nèi)容。
導(dǎo)航、菜單、編輯和瀏覽
直接使用組件實(shí)現(xiàn),比較簡(jiǎn)單不搬運(yùn)了,直接看源碼即可。
打包發(fā)布與版本管理
需要打包的情況分為兩種:第一次打包、修改代碼(非在線編輯的代碼)后打包。
如果只是文檔內(nèi)容有變化的話,只需要直接上傳json文件即可,不需要再次打包。
內(nèi)置了一個(gè)簡(jiǎn)單的版本管理功能,可以通過(guò) ver.json文件里的版本號(hào)實(shí)現(xiàn)更新功能。
以上就是基于vite2+Vue3編寫(xiě)一個(gè)在線幫助文檔工具的詳細(xì)內(nèi)容,更多關(guān)于vite2 Vue3幫助文檔的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue封裝自定義指令之動(dòng)態(tài)顯示title操作(溢出顯示,不溢出不顯示)
這篇文章主要介紹了vue封裝自定義指令之動(dòng)態(tài)顯示title操作(溢出顯示,不溢出不顯示),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Vue實(shí)現(xiàn)淘寶購(gòu)物車(chē)三級(jí)選中功能詳解
這篇文章主要介紹了通過(guò)Vue實(shí)現(xiàn)淘寶購(gòu)物車(chē)中三級(jí)選中的功能,文中的實(shí)現(xiàn)過(guò)程講解詳細(xì),對(duì)我們學(xué)習(xí)Vue有一定的幫助,感興趣的可以了解一下2022-01-01
Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的完整實(shí)例
Vue.js中的遞歸組件是一個(gè)可以調(diào)用自己的組件,遞歸組件一般用于博客上顯示評(píng)論,形菜單或者嵌套菜單,文章主要給大家介紹了關(guān)于Vue3+TypeScript實(shí)現(xiàn)遞歸菜單組件的相關(guān)資料,需要的朋友可以參考下2021-08-08
vscode 配置vue+vetur+eslint+prettier自動(dòng)格式化功能
這篇文章主要介紹了vscode 配置vue+vetur+eslint+prettier自動(dòng)格式化功能,本文通過(guò)實(shí)例代碼圖文的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
vue3?setup語(yǔ)法糖下父組件如何調(diào)用子組件
這篇文章主要介紹了vue3?setup語(yǔ)法糖下父組件如何調(diào)用子組件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
vue項(xiàng)目如何讀取本地json文件數(shù)據(jù)實(shí)例
很多時(shí)候我們需要從本地讀取JSON文件里面的內(nèi)容,這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目如何讀取本地json文件數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2023-06-06

