Docusaurus, similar to Vuepress, is a static site generation tool. Unlike Docusaurus, which makes it easy to mix React components into documents, Vuepress is good for mixing Vue components into documents.

This left me confused. If I wanted to use both the Vue and React components in my blog, neither would work for me, so I decided to experiment and use both components in my documentation

The initial goal was to encapsulate the Vue component into the React component and let Docusaurus render the component without having to write the underlying layer, saving a lot of effort

Docusaurus website description:

Using JSX in Markdown:

export const Highlight = ({children, color}) = > (
  <span
    style={{
      backgroundColor: color.borderRadius: '2px',
      color: '#fff',
      padding: '0.2 rem'}} >
    {children}
  </span>
);

<Highlight color="#25c2a0">Docusaurus green</Highlight> and <Highlight color="#1877F2">Facebook blue</Highlight> are my favorite colors.
I can write **Markdown** alongside my _JSX_!
Copy the code

You get the following render result:

Write a method that uses the vue component as input and returns the React component:

export const uvc = (vueComponent) = > {
     return function() {
         return ( // return one JSX each)}}Copy the code

Then there are two things to deal with:

  • How do I parse.vue files
  • How do component transformations take place

Parse the. Vue file

Using the vue – loader

Vue Loader is a Webpack Loader that allows you to write Vue components in a format called single-file Components (SFCs)

Next we need to write a Docusaurus plug-in that will parse the.vue files we encounter

Using the configureWebpack hook in the lifecycle:

module.exports = (content,options) = > {
    return {
        name: 'docusaurus-plugin-usevue'.configureWebpack(config, isServer, utils) {
            return {
                module: {
                    rules: [{
                        test: /\.vue$/,
                        use: ['vue-loader']]}},plugins: [
                    new VueLoaderPlugin()
                ]
            }
        }
    }
}
Copy the code

Component transformation

Vue and React are single-page applications. We can take advantage of this by mounting the render component of the DOM node to vue:

Since the.vue file has been converted by vue-loader, it can be rendered directly with h function

Mount vue components after the React component is rendered:

import React from 'react'
import Vue from 'vue'

export function uvc(test) {
    return class VueComponent extends React.Component {
        constructor(props) {
            super(props)
        }
        componentDidMount() {
            new Vue({
                el: `.app`.render: h= > h(test)
            })
        }
        render() {
            return React.createElement("div", {
                className: app }); }}; }Copy the code

But if only this, globally unique. App class, only one component will be in effect, then need to generate a random class name:

function randomCoding(){
    // Create an array of 26 letters
    let arr = ['A'.'B'.'C'.'D'.'E'.'F'.'G'.'H'.'I'.'J'.'K'.'L'.'M'.'N'.'O'.'P'.'Q'.'R'.'S'.'T'.'U'.'V'.'W'.'X'.'Y'.'Z'];
    let idvalue =' ';
    const n = 16;
    for(let i=0; i<n; i++){ idvalue+=arr[Math.floor(Math.random()*26)];
    }
    return idvalue;
}

export function uvc(test) {
    return class VueComponent extends React.Component {
        constructor(props) {
            super(props)
            this.state = {
                uuid: randomCoding()
            }
        }
        componentDidMount() {
            new Vue({
                el: `.The ${this.state.uuid}`.render: h= > h(test)
            })
        }
        render() {
            return React.createElement("div", {
                className: this.state.uuid }); }}; }Copy the code

Done, test results:

To make it easier for others to use, publish it on NPM as follows:

The installation

yarn add docusaurus-plugin-usevue use-vue-component
Copy the code

Plug-in to introduce

docusaurus.config.js:

module.exports = {
  // ...
    plugins: [['docusaurus-plugin-usevue',
            {
                name: 'usevue'},]],};Copy the code

usage

directory structure:

+-- docs
|   +-- test.vue
|   +-- intro.mdx
Copy the code

test.vue:

<template>
    <div class="red">
        hello world, this is {{name}}
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: 'peter'
        }
    }
}
</script>

<style>
    .red {
        color: red
    }
</style>
Copy the code

intro.mdx:

---
sidebar_position: 1
---

## Getting Started

import {uvc} from 'use-vue-component'   / / import uvc
import test from './text.vue'

export const HelloWorld = uvc(test)

<HelloWorld/>
Copy the code

It looks like the React component of Docusaurus is used similarly

limited

Because it is written casually, there are still many deficiencies

  • Currently, only Vue2 is supported. We are considering introducing Vue3
  • Global import of components to be supported
  • .

Feel free to share your ideas in the comments section!

For more details:

gitHub: docusaurus-plugin-usevue

gitHub: use-vue-component