Using Vue components in docusaurus ⚡

docusaurus , similar to Vuepress , is a static site generation tool. However, the difference is that using docusaurus can easily mix React components into documents, which is very suitable for writing documents of React related components, while Vuepress is suitable for mixing Vue components.

This makes me confused. If I want to use vue component and react component at the same time in my blog, neither of them can meet my requirements, so I decided to explore by myself and use both components in the document at the same time

The initial purpose is to encapsulate Vue components into react components, and then let docusaurus render this component without writing the underlying layer, saving a lot of effort

Description of docusaurus official website:

Using JSX in Markdown:

export const Highlight = ({children, color}) => (
  <span
    style={{
      backgroundColor: color,
      borderRadius: '2px',
      color: '#fff',
      padding: '0.2rem',
    }}>
    {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_!

You can get the following rendering results:

Then you have a certain idea. Write a method, vue component as input, and return the react component:

export const uvc = (vueComponent) => {
     return function() {
         return ( //Here a jsx is returned one by one
         	
         )
     }
}

Then there are two things to deal with:

  • How to parse. vue files
  • How to convert components

Parsing. vue files

use vue-loader

Vue Loader is a webpack loader, which allows you to Single file components (SFCs) Compose Vue components in the format of

Next, we need to write a docusaurus plug-in to parse the encountered. vue file

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()
                ]
            }
        }
    }
}

Perform component conversion

vue and react are single page applications. By mounting dom node rendering components, we can use this to enable vue to mount the rendered react components:

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

Mount vue components after render of react components:

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
            });
        }
    };
}

However, if only this. app class is globally unique and only one component will take effect, it is necessary 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: `.${this.state.uuid}`,
                render: h => h(test)
            })
        }
        render() {
            return React.createElement("div", {
                className: this.state.uuid
            });
        }
    };
}

Successful, test results:

For the convenience of others, publish it to npm as follows:

install

yarn add docusaurus-plugin-usevue use-vue-component

Plug in introduction

docusaurus.config.js:

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

usage

directory structure:

+-- docs
|   +-- test.vue
|   +-- intro.mdx

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>

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/>

It seems that the use of docusaurus's react component is very similar

limit

Because it is written casually, there are still many deficiencies

  • At present, only Vue2 components are supported, and the version of Vue3 is being considered
  • Global import of components to be supported
  • ...

Welcome to exchange views in the comments area!

For more details:

gitHub: docusaurus-plugin-usevue

gitHub: use-vue-component

Tags: Javascript React Vue Vue.js

Posted on Sun, 17 Oct 2021 23:34:25 -0400 by nysmenu