First, technical details

  • Use create-viet-app to build the official website
  • Use vue3 + typescript
  • Markdown syntax is supported to highlight code
  • Use rollup to package the project library and publish the NPM
  • Automate deployment using shell scripts

Second, effect preview

  1. Source link
  2. Results the preview

Home page

The document

Iii. Vite construction process

1. Preparation

  • Install the NodeJS stable version
  • To install NPM, run NPM config set registry registry.npm.taobao.org using Taobao source accelerator
  • Installation of yarn
  • Install vscode or webstorm for project development

2. Use Vite

  • Install create-viet-app globally
Yarn Global add create-viet-app or NPM i-g create-viet-appCopy the code
  • Create a project
Cva bobo-ui or create-vite-app bobo-ui // Bobo-ui can be changed to its own project nameCopy the code
  • Open the project
cd bobo-ui
Copy the code
  • Run the following command to open the local url and begin development
yarn dev 
Copy the code

4. Knowledge summary

1. vue-router

  • Installation:yarn add vue-router
  • Initialize: create a new history object; Creating a Router Object
/ / the main ts file
import { createApp } from 'vue';
import App from './App.vue';
import {createWebHashHistory,createRouter} from 'vue-router';
const history = createWebHashHistory();
const router = createRouter({
    history,
    routes:[
        {path:'/'.component:Bobo},
        {path:'/xxx'.component:Bobo2}
    ]
});

const app = createApp(App);
app.use(router);
app.mount('#app')
Copy the code
  • router-view & router-link
/ / App. Vue file
<template>
  <div>The navigation bar |<router-link to="/">BOBO</router-link>|
    <router-link to="/xxx">BOBO2</router-link></div>
  <hr />
  <router-view />
</template>

<script>
export default {
  name: 'App',}</script>
Copy the code

2. Dojo.provide and inject

// The parent component is marked
<script lang="ts">
import {ref ,provide} from 'vue';
export default {
  name: 'App'.setup(){
    const asideVisible = ref(false);
    provide('asideVisible',asideVisible);
  }

}
</script>
Copy the code
// Child components receive values
<template>
    <aside v-if="asideVisible">
        <h2>Component list</h2>
    </aside>
</template>

<script lang="ts">
import {inject, Ref} from "vue";
export default {
  setup(){
    const asideVisible = inject<Ref<boolean>>('asideVisible')
    return {asideVisible}
  }
}
</script>

Copy the code

3. Props pass values and V-Model

/ / the parent component
<template>
  <div>
    <Switch :value = "y"  @update:value="y=$event"/>
  </div>
</template>

<script lang="ts">
import Switch from '.. /lib/Switch.vue'
import {ref} from 'vue';
export default {
  components:{Switch},
  setup(){
    const y = ref(false);
    return {y}
  }
}

</script>
Copy the code
/ / child component
<template>
  <button @click="toggle" :class="{checked:value}"></button>
</template>

<script lang="ts">
export default {
  props: {value:Boolean
  },
  setup(props,context){
    const toggle = () = >{
      context.emit('update:value',! props.value) }return{toggle}; }}</script>
Copy the code
//v-model
/ / the parent component
<Switch v-model:value = "y" />

/ / child component
context.emit('update:value',! props.value)Copy the code

4. Vue3 attribute Binding (Attrs)

<template>
  // All attributes passed by the parent element are bound to the root element by default
  <div :size = "size">
    <! <button v-bind="$attrs"> <button v-bind="$attrs">
    <button v-bind="rest"> <! -- Bind only attributes except size -->
      <slot/>
    </button>
  </div>
</template>

<script lang="ts">
export default {
  inheritAttrs:false.// The template root element does not inherit events passed by the parent element
  setup(props,context){
    const{onClick,onMouseOver,size,... rest}=context.attrs;// Get the attributes passed by the parent element to deconstruct the assignment
    return{onClick,onMouseOver,size,rest}; }}</script>
Copy the code

5. Named slot

/ / the parent component
<Dialog>
    <template v-slot:title>
      <strong>The title</strong>
    </template>
    <template v-slot:content>
      <strong>content</strong>
    </template>
 </Dialog>
Copy the code
/ / child component
<header>
 <slot name="title"/> 
</header>
<main>
  <slot name="content"/>
</main>
Copy the code

6. Render nested slots

/ / the parent component
<template>
  <Tabs>
    <Tab title=Navigation "1">The content of 1</Tab>
    <Tab title="Navigation 2">Content of the 2</Tab>
  </Tabs>
</template>
Copy the code
// Nest child component tabs. vue
<template>
  <div>
    <component v-for="(c,index) in defaults" :is="c" :key="index"/>
  </div>
</template>

<script lang="ts">
import Tab from "./Tab.vue";
export default {
  setup(props,context){
    const defaults = context.slots.default(); // All tabs can be fetched
    return {defaults};
}
</script>
Copy the code
// Nested child tab. vue, content 1, content 2 of the parent component, will be inserted into slot
<template>
  <div>
    <slot/>  
  </div>
</template>
Copy the code

7. Teleport

Any Portal :Teleport is a technology that allows us to move our templates to a location in the DOM other than the Vue app

// Pass this block directly to the body inside the Dom node
<Teleport to = "body">
<div>A chunk of code</div>
</Teleport>
Copy the code

8. Ref and getgetBoundingClientRect

<template>
<div class="gulu-tabs-nav-indicator " ref="indicator">aaa</div>  
</template>

<script lang="ts">
    const indicator = ref<HTMLDivElement>(null);
    const {width,height,top,left} = indicator.getBoundingClientRect();// Get the width of the div element referenced by indicator
    return {indicator};
</script>

Copy the code

9. Introduce SVG ICONS

  • Iconfont official website select the icon to add the shopping cart project, open the shopping cart, click symbol, click generate code
  • Copy the generated address link into the projectindex.htmltheheaderIn the
 <script src="//at.alicdn.com/t/font_2426847_zhxe2xwikqs.js"></script>
Copy the code
  • Click on the help next to it, search for symbol references, and copy the CSS to the project as instructedindex.cssfile
.icon {
  width: 1em; height: 1em;
  vertical-align: -0.15 em;
  fill: currentColor;
  overflow: hidden;
}
Copy the code
  • Add an SVG icon to your project
<svg class="icon" >
   <use xlink:href="#icon-Vue"></use> // icon-vue specifies the name of the icon in iconfont
</svg>
Copy the code

10. Clip-path and border-radious can be used to draw arcs

11. Support Github markdown style

Markdown making address

Yarn add github-markdown- CSS // InstallationCopy the code
/ / use
import 'github-markdown-css' // in mian. Ts, you can use it directly
<template>
  <article class="markdown-body" >// Add class="markdown-body" to display the markdown style<h1>The title</h1>
   <p>Expand the amplification</P>
  </article>
</template>
Copy the code

12. Support the introduction of Markdown files in projects

  • SRC create a new plugins directory and add the md.ts file
import path from 'path'
import fs from 'fs'
import marked from 'marked';

const mdToJs = str= > {
    const content = JSON.stringify(marked(str))
    return `export default ${content}`
}

export function md() {
    return {
        configureServer: [ // For development purposes
            async ({ app }) => {
                app.use(async (ctx, next) => { // koa
                    if (ctx.path.endsWith('.md')) {
                        ctx.type = 'js'
                        const filePath = path.join(process.cwd(), ctx.path)
                        ctx.body = mdToJs(fs.readFileSync(filePath).toString())
                    } else {
                        await next()
                    }
                })
            },
        ],
        transforms: [{  // for rollup // plug-in
            test: context= > context.path.endsWith('.md'),
            transform: ({ code }) = > mdToJs(code)
        }]
    }
}
Copy the code
  • Install marked:yarn add --dev marked
  • SRC create vite. Config. ts, import plugins/md.ts, and pass it to plugins
import { md } from "./plugins/md";

export default {
    plugins: [md()]
};
Copy the code
  • Using the instance

Md file

<template>
  <article class="markdown-body" v-html="md">
  </article>
</template>

<script lang="ts">
import md from '.. /markdown/intro.md';
export default {
  data() {
    return {
      md
    }
  }
}
</script>
Copy the code

13. CreateApp and h functions

  • Use the createApp API to return an application instance, and you can continue to call other methods through the chain

//openDialog.ts
import Dialog from './Dialog.vue';
import {createApp,h} from 'vue';

export const openDialog = (options) = >{
    const {title,content,ok,cancel,closeOnClickOverlay}= options;
    const div = document.createElement('div');
    document.body.appendChild(div);

    const close=() = >{
        app.unmount(div);
        div.remove();
    }

    const app =createApp({
        render(){
            return h(
                Dialog,
                {
                    visible:true."onUpdate:visible":(newVisible) = >{
                        if (newVisible===false){
                            close();
                        }
                    },
                    ok,
                    cancel,
                    closeOnClickOverlay
                },
                {title,content}
            )
        }
    });
    app.mount(div);
}
Copy the code

14. Display source code

  • Modify the configuration of the vite. Config. ts file
import fs from 'fs'
import {baseParse} from '@vue/compiler-core'

export default {
    vueCustomBlockTransforms: {
        demo: (options) = > {
            const { code, path } = options
            const file = fs.readFileSync(path).toString()
            const parsed = baseParse(file).children.find(n= > n.tag === 'demo')
            const title = parsed.children[0].content
            const main = file.split(parsed.loc.source).join(' ').trim()
            return `export default function (Component) {
        Component.__sourceCode = The ${JSON.stringify(main)
            }
        Component.__sourceCodeTitle = The ${JSON.stringify(title)}} `.trim()
        }
    }
};
Copy the code
  • Appended to template in Switch1demo<demo> General usage </demo>

  • In the switchDemo. vue parent component reference Switch1Demo, add the preview
<div class="demo">
      <h2>Regular use</h2>
      <div class="demo-component">
        <component :is="Switch1Demo"/>// Here is the component</div>
      <div class="demo-actions">
        <Button>Look at the code</Button>
      </div>
      <div class="demo-code">
        <pre>{{Switch1Demo.__sourceCode}}</pre>// Here is the source code for the component</div>
</div>
Copy the code

15. Highlight source code

Install prismjs YARN add Prismjs

2. Import switchDemo. vue where Demo is used

import 'prismjs'
const Prism = (window as any) .Prism
Copy the code

3, look at themes in node_modules prismjs and prisms. CSS, which are the CSS styles that can be referenced, and import them in switchDemo. vue where Demo is used

import 'prismjs/themes/prism.css'
Copy the code

4. Use prism.highlight to highlight the source code

<pre class="language-html" v-html="Prism.highlight(Switch2Demo.__sourceCode, Prism.languages.html, 'html')" />
Copy the code

Rollup package library files and release NPM

1. Create the sr/lib/index.ts file to export components

SRC create rollup.config.js and tell rollup how to package

// Install rollup-plugin-esbuild rollup-plugin-vue rollup-plugin-scss sass rollup-plugin-terser
// Change name to your library name
import esbuild from 'rollup-plugin-esbuild'
import vue from 'rollup-plugin-vue'
import scss from 'rollup-plugin-scss'
import dartSass from 'sass';
import { terser } from "rollup-plugin-terser"

export default {
    input: 'src/lib/index.ts'.output: [{
        globals: {
            vue: 'Vue'
        },
        name: 'Bobo'.file: 'dist/lib/bobo.js'.format: 'umd'.plugins: [terser()]
    }, {
        name: 'Bobo'.file: 'dist/lib/bobo.esm.js'.format: 'es'.plugins: [terser()]
    }],
    plugins: [
        scss({ include: /\.scss$/, sass: dartSass }),
        esbuild({
            include: /\.[jt]s$/,
            minify: process.env.NODE_ENV === 'production'.target: 'es2015'
        }),
        vue({
            include: /\.vue$/,}})]Copy the code

3. Install rollup(global or local) and run rollup -c in the project root directory

Yarn Global add rollup // InstallCopy the code

4. Update the package.json file

5. Release NPM

  • Example Change the NPM source to the official source
NPM config get registry / / view the source of NPM NPM config set registry / / modify NPM source at https://registry.npmjs.org/Copy the code

Tip: NRM quickly switches sources

  • Log in to NPM website to register as a user
  • Project terminal operationnpm login, enter user name, password, email login (usenpm logoutCan log out)
  • Project terminal operationnpm publish, you can publish the packaged library files to NPM
  • Log in to NPM official website, login account, click on the top right corner of the picture, view packages, you can see your published packages
  • Next time, re-rollup -c, change the version number in package.json, and re-npm publish

Automated deployment

1. Modify the vite. Config. ts configuration file (the configuration file cannot be added.

2. Create a source repository on Github. The procedure is omitted

3. Create the automatic script deploy.sh to implement one-click deployment

Note: Orgin source needs to be changed to its own Github repository address

Viii. Problem solving

To complement…