wheel ui

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

添加




provide inject

需求:点击子组件 A ,隐藏子组件 B 某一内容。

App.vue

子组件 A




子组件 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

Snipaste_2022-02-08_15-42-14

解决:

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.vue


开发 UI 库的 CSS 注意事项

不能使用 scoped

因为 data-v-xxx 中的 xxx 不能保证每次运行都相同,必须输出稳定不变的 class 选择器,方便使用者覆盖。

必须加前缀

.button 不行,很容易被使用者覆盖,.wheel-button 行,不太容易被覆盖。

.theme-link 不行,很容易被使用者覆盖,.wheel-theme-link 行,不太容易被覆盖。

插槽

具名插槽

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



获取 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.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"
  }
}

你可能感兴趣的:(wheel ui)