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