一、技术细节
- 使用create-vite-app搭建官网
- 使用vue3 + typescript实现
- 支持markdown语法高亮展示代码
- 使用rollup进行项目库打包,并发布npm
- 使用shell脚本自动化部署
二、效果预览
首页
文档
三、vite搭建过程
1. 准备工作
- 安装nodejs稳定版
- 安装npm,使用淘宝源加速,运行命令:npm config set registry registry.npm.taobao.org
- 安装yarn
- 安装vscode 或webstorm用于项目开发
2. 使用vite搭建
- 全局安装create-vite-app
yarn global add create-vite-app 或
npm i -g create-vite-app
- 创建项目
cva bobo-ui 或
create-vite-app bobo-ui //bobo-ui可以改成自己的项目名
- 打开项目
cd bobo-ui
- 运行以下命令,打开本地网址,开始开发
yarn dev
四、知识总结
1. vue-router
- 安装:
yarn add vue-router - 初始化:新建 history对象;新建router对象
//main.ts 文件
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')
- router-view & router-link
//App.vue 文件
<template>
<div>导航栏|
<router-link to="/">BOBO</router-link>|
<router-link to="/xxx">BOBO2</router-link></div>
<hr />
<router-view />
</template>
<script>
export default {
name: 'App',
}
</script>
2. provide 和 inject
//父组件做标记
<script lang="ts">
import {ref ,provide} from 'vue';
export default {
name: 'App',
setup(){
const asideVisible = ref(false);
provide('asideVisible',asideVisible);
}
}
</script>
//子组件接收值
<template>
<aside v-if="asideVisible">
<h2>组件列表</h2>
</aside>
</template>
<script lang="ts">
import {inject, Ref} from "vue";
export default {
setup(){
const asideVisible = inject<Ref<boolean>>('asideVisible')
return {asideVisible}
}
}
</script>
3. props传值和v-model
//父组件
<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>
//子组件
<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>
//v-model
//父组件
<Switch v-model:value = "y" />
//子组件
context.emit('update:value',!props.value)
4. vue3属性绑定(Attrs)
<template>
//父元素传过来的所有属性默认绑定到根元素上,可以不继承,并且拆分属性只绑定部分属性
<div :size = "size">
<!-- <button v-bind="$attrs"> 把父元素传过来的所有属性绑定到button上 -->
<button v-bind="rest"> <!-- 只绑定除size外的剩余属性 -->
<slot/>
</button>
</div>
</template>
<script lang="ts">
export default {
inheritAttrs:false,//模板根元素不继承父元素传过来的事件
setup(props,context){
const{onClick,onMouseOver,size,...rest}=context.attrs;//拿到父元素传的属性解构赋值
return{onClick,onMouseOver,size,rest};
}
}
</script>
5. 具名插槽
//父组件
<Dialog>
<template v-slot:title>
<strong>标题</strong>
</template>
<template v-slot:content>
<strong>内容</strong>
</template>
</Dialog>
//子组件
<header>
<slot name="title"/>
</header>
<main>
<slot name="content"/>
</main>
6. 渲染嵌套插槽
//父组件
<template>
<Tabs>
<Tab title="导航1">内容1</Tab>
<Tab title="导航2">内容2</Tab>
</Tabs>
</template>
//嵌套子组件 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(); //可以取到所有的Tab
return {defaults};
}
</script>
//嵌套子组件 Tab.vue,父组件的内容1、内容2,会插到slot
<template>
<div>
<slot/>
</div>
</template>
7. Teleport
任意传送门:Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术
//直接将这一块传送到Dom节点里面的body
<Teleport to = "body">
<div>
一大块代码
</div>
</Teleport>
8. ref 和 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();//获取indicator引用的div元素的宽高等
return {indicator};
</script>
9. 引入SVG图标
- iconfont官网选中图标加入购物车项目,打开购物车该,点击symbol,点击生成代码
- 将生成的地址链接复制到项目中
index.html的header中
<script src="//at.alicdn.com/t/font_2426847_zhxe2xwikqs.js"></script>
- 点击旁边的帮助,搜索symbol引用,按文档指示把css复制到项目的
index.css文件
.icon {
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
- 在项目中加入svg图标
<svg class="icon" >
<use xlink:href="#icon-Vue"></use> //icon-Vue为图标在iconfont的名字
</svg>
10. clip-path和border-radious都可以用于画圆弧
11. 支持github的markdown样式
yarn add github-markdown-css //安装
//使用
import 'github-markdown-css' //在mian.ts引入,就可以直接使用
<template>
<article class="markdown-body" >//加入class="markdown-body"就可以显示为markdown样式
<h1>标题</h1>
<p>扩大放大</P>
</article>
</template>
12. 支持项目中引入markdown文件
- src同级目录下新建plugins,添加文件md.ts
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: [ // 用于开发
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: [{ // 用于 rollup // 插件
test: context => context.path.endsWith('.md'),
transform: ({ code }) => mdToJs(code)
}]
}
}
- 安装marked:
yarn add --dev marked - src同级目录下创建vite.config.ts,引入plugins/md.ts,传给plugins
import { md } from "./plugins/md";
export default {
plugins: [md()]
};
- 使用实例
md文件
<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>
13. createApp和 h 函数
- 使用createApp这个 API返回一个应用实例,并且可以通过链条的方式继续调用其他的方法
//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);
}
14.显示源代码
- 修改vite.config.ts文件配置
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 = ${
JSON.stringify(main)
}
Component.__sourceCodeTitle = ${JSON.stringify(title)}
}`.trim()
}
}
};
-
在 switch1demo中的template前加上
<demo>常规用法</demo> -
在SwitchDemo.vue父组件引用Switch1Demo,添加预览
<div class="demo">
<h2>常规用法</h2>
<div class="demo-component">
<component :is="Switch1Demo"/> //此处是组件
</div>
<div class="demo-actions">
<Button>查看代码</Button>
</div>
<div class="demo-code">
<pre>{{Switch1Demo.__sourceCode}}</pre> //此处展示组件的源代码
</div>
</div>
15.高亮源代码
1、安装prismjs yarn add prismjs
2、在使用Demo的地方SwitchDemo.vue里import
import 'prismjs'
const Prism = (window as any) .Prism
3、查看node_modules里的prismjs里面的themes中和prism.css同级的其他css,就是可以引用的css样式,在使用Demo的地方SwitchDemo.vue里import
import 'prismjs/themes/prism.css'
4、使用Prism.highlight就可以对源代码进行高亮显示
<pre class="language-html" v-html="Prism.highlight(Switch2Demo.__sourceCode, Prism.languages.html, 'html')" />
五、rollup打包库文件,发布npm
1. 创建sr/lib/index.ts文件,导出组件
2. src同级目录创建rollup.config.js,告诉rollup怎么进行打包
// 请先安装 rollup-plugin-esbuild rollup-plugin-vue rollup-plugin-scss sass rollup-plugin-terser
// 把 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$/,
})
],
}
3. 安装rollup(全局或局部安装),项目根目录运行rollup -c
yarn global add rollup //安装
4. 更新package.json文件
5. 发布npm
- 修改npm源为官方源
npm config get registry //查看npm源
npm config set registry https://registry.npmjs.org/ //修改npm源
小技巧:nrm快速切换源
- 登录npm官网,注册用户
- 项目终端运行
npm login,输入用户名,密码,邮箱登录(使用npm logout可以登出) - 项目终端运行
npm publish,就可以把打包好的库文件发布到npm - 登录npm官网,登录账号,点击右上角头像,查看packages,就可以看到自己发布的包
- 下次改动重新rollup -c,修改package.json里的version版本号,重新npm publish
七、自动化部署
1. 修改vite.config.ts配置(没有该配置文件可新增,放在src同级目录下)
2. 在自己github上创建源码仓库,过程略
3. 创建自动化脚本deploy.sh,实现一键部署
注:orgin源需修改为自己的github仓库地址
八、问题解决
待补充...