橘莲溢香的学习笔记
  • 首页
  • 归档
  • 分类
  • 标签
  • 友链
  • 关于
  • 登录
bg
_
icon
Made with Next.js
Copyright © 2021 橘莲溢香京ICP备2021035188号

icon目录

  • 安装
  • 初始化
  • 部署服务
  • 一键生成
  • Docsify 源码解读
    • 初始化工作
      • initMixin
      • initLifycycle
      • initPlugin
      • callHook(vm,'init')
      • initRouter
      • initRender
      • initEvent
      • initFetch
      • callHook(vm,'mounted')
      • routerMixin
      • renderMixin
      • fetchMixin
      • eventMixin
      • initGlobalAPI
  • 最后

原文链接: https://juejin.cn/post/6844903497893150734

安装

// 安装docsify-cli
npm install docsify-cli -g

初始化

@desc: 初始化 docsify,将模板文件拷贝至 path 下
@param:local[boolean],local 默认为 false,若设置为 true,则将 js,css 等资源文件拷贝到本地 path 下的 vendor 目录下.
@param:theme[string], theme 默认为'vue',主题可选'buble','dark','pure','vue'.


 docsify init <path> [--local] [--theme]
 - or -
 docsify i <path> [-l] [-t]

部署服务

@desc: 初始化 docsify 后,才能部署 docsify,否则会报出下方的 errorMsg
@errorMsg: No docs found, please run docsify init first.
@param: open[boolean],默认为 false,若为 true,则部署后自动打开默认浏览器该站点地址.
@param: port[number],默认为 3000,可自定义其他未被占用的端口.


docsify serve <path> [--open] [--port]
-- or --
docsify s <path> [-o] [-p]

一键生成

  • 生成初始模板页面结构配置,若能通过 config 读取到配置文件,那么合并至模板页面结构配置,若未读取到,则检查 path 下是否有 package.json,并读取 package.json 中的 docsify 配置,若配置存在,则合并,否则用初始的模板页面结构配置。
  • 文档通过服务端渲染输出
  • 没有 serve 模式下的热加载,所谓热加载,即监控文件更改并重新加载浏览器(对于部署在远程服务器上来说,最好别用热加载)

@desc: 一键生成文档站点.
@param: config[string],默认为 false, 需要加载的配置文件,可自定义 docsify 配置.
@param: port[number],默认为 4000,可自定义其他未被占用的端口.


docsify start <path> [--config] [--port]
--- or ---
docsify start <path> [-c] [-p]

Docsify 源码解读

TOC: table of contents

初始化工作

  • 首先通过  initMixin、routerMixin、renderMixin、fetchMixin、 eventMixin 等方法向 Docsify 对象原型注入方法和属性

  • 然后初始化全局对象 Docsify、DocsifyCompiler、marked、Prism,即挂载到 window 对象之上。

  • dom 加载完成触发回调事件 this._init()

initMixin

export function initMixin(proto) {
    // proto为Docsify原型对象
    proto._init = function () {
        const vm = this;
        vm.config = config || {};
        initLifecycle(vm); // Init hooks
        initPlugin(vm); // Install plugins
        callHook(vm, 'init');
        initRouter(vm); // Add router
        initRender(vm); // Render base DOM
        initEvent(vm); // Bind events
        initFetch(vm); // Fetch data
        callHook(vm, 'mounted');
    };
}

initLifycycle

这里定义了六个钩子函数,即 init、beforeEach、afterEach、doneEach、ready、mounted,钩子函数初始化为空数组。下面介绍下钩子的生命周期:

  • init: 仅在第一次初始化页面时调用。
  • beforeEach: 开始解析 Markdown 内容时前调用。
  • afterEach: markdown 解析成 html 后调用。beforeEach 和 afterEach 支持异步处理,通过回调返回结果。
  • doneEach: 路由切换后数据全部加载完成后调用
  • ready: 首次初始化页面且加载完数据后调用。
  • mounted: 渲染完成后调用

initPlugin

引入用户自定义插件,及其设置的钩子函数,来替换默认钩子函数。

callHook(vm,'init')

调用"init"钩子函数,vm 为当前实例。

initRouter

设置路由模式,默认为'hash',用户可设置为'history'或'hash'。

initRender

这里主要为编译层,初始化 markdown 编译器,重写了 marked 的一些标签编译方法,例如 heading、code、link、paragraph、image 等,最终生成 app 的 DOM 实例,并添加到 DOM 中(注意:此时 Content、navbar 和 sidebar 仅仅是模板实例,内容数据还未获取)。

initEvent

为切换 sidebar 的按钮绑定事件。

initFetch

通过 xhr 请求获取 sidebar、navbar、content、coverpage 的 text 数据,然后填充进 DOM 实例中。

callHook(vm,'mounted')

调用"mounted"钩子函数,vm 为当前实例。

routerMixin

export function routerMixin(proto) {
    // proto为Docsify原型对象
    proto.route = {};
}

router 模块初始化仅仅定义了一个名为 route 的 Docsify 原型对象的对象属性。

renderMixin

export function renderMixin (proto) {
 // proto为Docsify原型对象,下面代码细节就不讲了,感兴趣的话可以down一份研究下
 proto._renderTo = function (el, content, replace) {
  // 如何插入content,replace = ['outerHTML'|'innerHTML']
  ...
 }
 proto._renderSidebar = function (text) {
  // 读取并解析sidebar配置,渲染sidebar
  ...
 }
 proto._bindEventOnRendered = function (activeEl) {
  // 滚动条滑动模块,以及对配置项autoHeader、auto2top的处理
  ...
 }
 proto._renderNav = function (text) {
  // 渲染navbar内容,处理nav上活动标签样式
  ...
 }
 proto._renderMain = function (text, opt = {}) {
  // 渲染content内容: 首先调用beforeEach钩子,然后将markdown编译成html,最后调用afterEach处理后返回html,最后渲染content
  // 然后读取excuteScript配置,若为true,则执行script内嵌脚本。若想执行外链脚本,需要引入external-script插件
  ...
 }
 proto._renderCover = function (text) {
  // 渲染封面页
  ...
 }
 proto._updateRender = function () {
  // 渲染文档站点标题
  ...
 }
}

fetchMixin

export function fetchMixin (proto) {
 // 同renderMixin的proto所述
 let last // 记录上一次请求信息
 proto._fetch = function (cb = noop) {
  ... // 强制结束上一次请求,加载content、nav以及sidebar数据
 }
 proto._fetchCover = function () {
  ... // 请求并渲染封面数据
 }
 proto.$fetch = function (cb = noop) {
  ... // 封装了一个方法用作路由切换的数据请求
 }
}

eventMixin

export function eventMixin(proto) {
    // 同renderMixin的proto所述
    proto.$resetEvents = function () {
        // 滚动到当前路由中id='query.id'的dom块,并使sidebar的活动标签实时响应,获取nav活动标签
        scrollIntoView(this.route.query.id);
        sidebar.getAndActive(this.router, 'nav');
    };
}

initGlobalAPI

export default function () {
    window.Docsify = { util, dom, get, slugify };
    window.DocsifyCompiler = Compiler;
    window.marked = marked;
    window.Prism = prism;
}

这里导出一个方法,里面主要暴露了四个全局对象,方便提供使用。

  • window.Docsify  对象包含了工具类方法->util、 dom 操作方法->dom、  请求 markdown 内容方法->get、  缓存处理方法->slugify
  • window.DocsifyCompiler  为构造函数生成的对象,是对开源项目 marked 做了一些扩展性,自定义了一些如前文所述的标签编译方法。
  • window.marked  即如上所述的 marked 对象
  • window.Prism  即开源项目 prism,一个轻量级,强大,优雅的语法高亮库。

最后

  • 若要配置到远程服务器的话且在 serve 模式下,可在 serve 手动关掉 livereload,因为它会单独开启一个端口服务来监控文件更改。
  • 服务端渲染(SSR),主要依赖 Docsify 的  docsify -server -renderer 模块
4条留言
avatar
title

TEST4

2024-11-09
avatar
title

TEST3

2024-11-09
avatar
title

TEST2

2024-11-09
avatar
title

TEST

2024-11-09
login登录后留言