yarn global add create-vite-app
cva wheel-ui
// 等价于
npm init vite-app <
cd wheel-ui
yarn install
yarn dev
// 查看 vue-router 所有版本号
npm info nue-router versions
// 安装 vue-router
yarn add vue-router
yarn add -D sass
vite 文档给出的命令是
npm init vite-app 项目名
yarn create vite-app 项目名
等价于
yarn global creat-vite-app
cva 项目名
也等价于
npx create-vite-app 项目名
即 npx 会帮你全局安装用到的包
初始化 vue-router
新建 history 对象
新建 router 对象
app.use(router)
const history = createWebHashHistory();
const router = createRouter({
history: history,
routes: [{ path: "/", component: HelloWorld }],
});
const app = createApp(App);
app.use(router);
app.mount("#app");
添加
导航栏 |
frank |
frank2
provide inject
需求:点击子组件 A ,隐藏子组件 B 某一内容。
App.vue
子组件 A
LOGO
子组件 B
TS 引入 .vue文件
找不到模块“./App.vue”或其相应的类型声明。ts(2307)
src 目录下创建以 .d.ts 为结尾的文件
// shims-vue.d.ts
declare module '*.vue' {
import { ComponentOptions } from "vue";
const componentOptions:ComponentOptions
export default componentOptions
}
error Command failed with exit code 1.
![Snipaste_2022-02-08_15-42-14](https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2022-02-08_15-42-14.png)
![Snipaste_2022-02-08_15-42-14](https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2022-02-08_15-42-14.png)
解决:
rm -rf node_modules/
yarn cache clean
yarn install
父子组件通信
父组件
子组件
或者使用 v-model
父组件
子组件
context.emit("update:value", !props.value);
属性绑定
默认所有属性都绑定到根元素。
使用 inheritAttrs: false
可以取消默认绑定。
使用 $attrs
或者 context.attrs
获取所有属性。
使用 v-bind=“$attrs”
批量绑定属性。
使用 cons {size, ...rest} = context.attrs
将属性放分开。
父组件
// ButtonDemo.vue
Button 示例
示例1
子组件
// Button.vue
// 将 size 属性绑定到根元素
// 将其余的属性绑定到目标元素
开发 UI 库的 CSS 注意事项
不能使用 scoped
因为 data-v-xxx 中的 xxx 不能保证每次运行都相同,必须输出稳定不变的 class 选择器,方便使用者覆盖。
必须加前缀
.button 不行,很容易被使用者覆盖,.wheel-button 行,不太容易被覆盖。
.theme-link 不行,很容易被使用者覆盖,.wheel-theme-link 行,不太容易被覆盖。
插槽
具名插槽
你好
hello
xxx
Teleport
将 xxx 传送到 body 下
xxx
openDialog
openDialog.js
import Dialog from './Dialog.vue';
import {createApp, h} from 'vue';
export const openDialog = (options) => {
const {title, content, closeOnClickOverlay, ok, cancel} = options;
const div = document.createElement('div');
document.body.appendChild(div);
const close = () => {
//@ts-ignore
app.unmount(div);
div.remove();
};
const app = createApp({
render() {
return h(Dialog, {
visible: true,
closeOnClickOverlay,
'onUpdate:visible': (newVisible) => {if (newVisible === false) close(); },
ok,
cancel
}, {title, content});
}
});
app.mount(div);
};
vue 组件使用
const showDialog = () => {
openDialog({
title: '标题',
content: '你好啊',
closeOnClickOverlay: false,
ok() {console.log('ok');},
cancel() {console.log('cancel');}
});
};
检查子组件的类型
获取插槽内容 const defaults = context.slots.default()
Tabs 组件
获取 el 的 width、left const {width, height, left, top} = el.getBoundingClientRect()
CSS 最小影响原则
css 绝对不能影响库的使用者。
markdown
yarn add --dev marked
新建 plugins/md.ts
// @ts-nocheck
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)
}]
};
}
新建 vite.config.ts
import {md} from './plugins/md';
export default {
plugins: [md()]
};
使用
消除重复 markdown
使用动态引入 import()
==异步操作==
Markdown.vue
使用
Intro.vue
或者直接全局引入 Markdown 组件,就不需要每个组件单独引入了。
main.ts app.component('Markdown', Markdown)
进一步优化:
直接在 router.js 里渲染,删除无用的 intro.vue
const history = createWebHashHistory();
// 核心
const md = filename => h(Markdown, {path: `../markdown/${filename}.md`, key: filename});
export const router = createRouter({
history: history,
routes: [
{path: '/', component: Home},
{
path: '/doc',
component: Doc,
children: [
{path: '', component: DocDemo},
// 核心
{path: 'intro', component: md('intro')},
{path: 'install', component: md('install')},
{path: 'get-started', component: md('get-started')},
//
{path: 'switch', component: SwitchDemo},
...
],
},
],
});
展示源代码
配置 vite.config.ts
import {md} from './plugins/md';
import * as fs from 'fs';
import {baseParse} from '@vue/compiler-core';
export default {
plugins: [md()],
vueCustomBlockTransforms: {
demo: (options) => {
const {code, path} = options;
const file = fs.readFileSync(path).toString();
//@ts-ignore
const parsed = baseParse(file).children.find(n => n.tag === 'demo');
//@ts-ignore
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();
}
}
};
SwitchDemo.vue
{{ Switch1Demo.__sourceCode }}
Switch1Demo.vue 组件开头添加上 xxx
高亮源代码
使用 prismjs
yarn add prismjs
导入
import Prism from 'prismjs';
import '../../node_modules/prismjs/themes/prism.min.css';
...
set(){
return (Prism)
}
...
使用
Vue2 和 Vue3 的区别
- Vue3 的 template 支持==多个跟标签==,Vue2 不支持。
- Vue3 有
createApp()
,而Vue2 的是 new Vue()
- Vue3
createApp(组件)
,Vue2 new Vue({template, render})
v-model 代替以前的 v-model,.sync。
新增 context.emit 和 this.$emit 作用相同。
部署上线注意事项
配置 vite.config.ts
添加以下代码,
base: './',
assetsDir: 'assets',
报错
runtime-core.esm-bundler.js?5c40:38 [Vue warn]: Invalid VNode type: Symbol(Comment) (symbol)
解决:
vue.config.js
const path = require(`path`);
module.exports = {
configureWebpack: {
resolve: {
symlinks: false,
alias: {
vue: path.resolve(`./node_modules/vue`)
}
}
}
};
打包部署
rollup -c
{
"name": "whl-ui",
"version": "0.0.2",
"files": [
"dist/lib/*"
],
"main": "dist/lib/whl.js",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"resolutions": {
"node-sass": "npm:sass@^1.26.11"
},
"dependencies": {
"github-markdown-css": "4.0.0",
"marked": "4.0.12",
"prismjs": "1.21.0",
"vue": "3.0.0",
"vue-router": "4.0.0-beta.3"
},
"devDependencies": {
"@types/prismjs": "^1.26.0",
"@vue/compiler-sfc": "3.0.0",
"rollup-plugin-esbuild": "2.5.0",
"rollup-plugin-scss": "2.6.0",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-vue": "6.0.0-beta.10",
"sass": "1.26.11",
"vite": "1.0.0-rc.1"
}
}
yarn build
{
"name": "whl-ui",
"version": "0.0.2",
"files": [
"dist/lib/*"
],
"main": "dist/lib/whl.js",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"resolutions": {
"node-sass": "npm:sass@^1.26.11"
},
"dependencies": {
"github-markdown-css": "4.0.0",
"marked": "4.0.12",
"prismjs": "1.21.0",
"vue": "^3.0.0",
"vue-router": "4.0.0-beta.3"
},
"devDependencies": {
"@types/prismjs": "^1.26.0",
"@vue/compiler-sfc": "^3.0.0",
"rollup-plugin-esbuild": "2.5.0",
"rollup-plugin-scss": "2.6.0",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-vue": "6.0.0-beta.10",
"sass": "1.26.11",
"vite": "1.0.0-rc.13"
}
}