npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

yu-el-ui

v0.0.5

Published

一个简单尝试

Downloads

1

Readme

Vue 3 + TypeScript + Vite + Eslint + prettier

安装pnpm ,node版本16.18.1

npm i -g pnpm 

用vite创建vue3+ts项目

pnpm create vite

安装@types/node

pnpm add @types/node -D

vite.config.ts设置别名

resolve: {
   alias: {
     '@': resolve(__dirname, 'src'),
     components: resolve(__dirname, 'src/components'),
   },
   extensions: ['.js', '.ts', '.jsx', '.tsx', '.json', '.vue', 'mjs'],
 },

tsconfig.json设置别名,不然vscode识别不了

"compilerOptions": {
  "baseUrl": "./",
   "paths": {
      "@/*": ["./src/*"],
      "components/*": ["./src/components/*"]
      }
   }

安装vue-router

pnpm add vue-roter

在src目录创建router文件夹,新建index.ts文件

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

import Home from '@/views/index.vue'

const routes: Array<RouteRecordRaw> = [
  {
    path: '',
    name: 'Home页面',
    component: Home,
  },
]

const router = createRouter({
  history: createWebHistory(),
  routes,
})

export default router

在main.ts文件引入

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'

const app = createApp(App)

// 注册路由
app.use(router)
app.mount('#app')

安装element-plus

pnpm add element-plus @element-plus/icons-vue

在main.ts文件引入

1.全局引用

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)

app.use(ElementPlus, {
  locale,
})

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

// 注册路由
app.use(router)
app.mount('#app')

修改主题,创建样式并修改main.ts的引入

/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  ),
);

// 如果只是按需导入,则可以忽略以下内容。
// 如果你想导入所有样式:
 @use "element-plus/theme-chalk/src/index.scss" as *;

安装sass

pnpm add sass sass-loader -D

安装js-cookies

pnpm add @types/js-cookie js-cookie -D

安装axios并封装

pnpm add axios

新建service文件夹,创建request.ts

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { Result } from './types'
import Cookies from 'js-cookie'

class YBRequest {
  private instance: AxiosInstance
  private options: AxiosRequestConfig
  constructor(options: AxiosRequestConfig) {
    this.options = options
    this.instance = axios.create(this.options)

    this.instance.interceptors.request.use(
      (config: any) => {
        const token = Cookies.get('token')
        if (token) {
          config.headers.Authorization = token
        }
        return config
      },
      (err) => {
        return err
      },
    )

    this.instance.interceptors.response.use(
      (res) => {
        // 拦截响应的数据
        if (res.data.code === 401) {
          Cookies.set('token', '')
          return res.data
        }
        return res.data
      },
      (err) => {
        return err
      },
    )
  }

  request<T = any>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      this.instance
        .request<any, AxiosResponse<Result<T>>>(config)
        .then((res) => {
          resolve(res as unknown as Promise<T>)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }

  get<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'GET' })
  }

  post<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'POST' })
  }

  patch<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'PATCH' })
  }

  delete<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ...config, method: 'DELETE' })
  }
}

export default YBRequest

创建types.d.ts

export interface Result<T = any> {
  code: number
  data: T
}

创建index.ts

import YBRequest from './request'

export default new YBRequest({
  baseURL: '/api',
  timeout: 10000,
})

在service建立对应模块的api文件夹进行分类

main/login/index.ts

import ybRequest from '@/service'
import { GetDepartmentListParams } from './types'

enum DepartmentAPI {
  DepartmentList = '/department/list',
}

export function getDepartmentList(params: GetDepartmentListParams) {
  return ybRequest.post({
    url: DepartmentAPI.DepartmentList,
    data: params,
  })
}

main/login/types.d.ts

export interface GetDepartmentListParams {
  offset: number
  size: number
}
//可继承
// export interface GetDepartmentListParams extends ParamsPagination {}

安装eslint

pnpm add eslint -D

初始化eslint

执行npx eslint --init命令初始化eslint

You can also run this command directly using 'npm init @eslint/config'.
 
? How would you like to use ESLint? ...
To check syntax and find problems
 
? What type of modules does your project use? ...
JavaScript modules (import/export)
 
? Which framework does your project use? ...
Vue.js
 
? Does your project use TypeScript? » No / Yes
Yes
 
? Where does your code run? ... (用空格选中两个,回车确定)
√ Browser
√ Node
 
? What format do you want your config file to be in? ...
JavaScript
 
The config that you've selected requires the following dependencies:
eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now?
No

最后一个提示我们选择No,然后手动npm安装提示的依赖

pnpm add eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest -D

在packeage.json添加命令

"scripts": {
 	// 执行该命令eslint会检测当前项目下所有的.vue,.js,.ts,.jsx,.tsx文件是否符合eslint的代码规范,并尝试自动修复
    "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix"
  },

建立.eslintignore文件

*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
.eslintrc.js
prettier.config.js
/src/mock/*

安装prettier

pnpm add prettier -D

配置.prettier.cjs

/*
 * @Author: yubb
 * @Date: 2023-04-26 15:37:48
 * @LastEditTime: 2023-04-26 15:52:49
 * @LastEditors: yubb
 * @Description: 
 * @FilePath: \yubb-el-ui\.prettierrc.cjs
 */
module.exports = {
  // 一行最多 100 字符
  printWidth: 100,
  // 使用 2 个空格缩进
  tabWidth: 2,
  // 不使用缩进符,而使用空格
  useTabs: false,
  // 行尾不需要有分号
  semi: false,
  // 使用单引号
  singleQuote: true,
  // 对象的 key 仅在必要时用引号
  quoteProps: 'as-needed',
  // jsx 不使用单引号,而使用双引号
  jsxSingleQuote: false,
  // 尾随逗号
  trailingComma: 'all',
  // 大括号内的首尾需要空格
  bracketSpacing: true,
  // jsx 标签的反尖括号需要换行
  jsxBracketSameLine: false,
  // 箭头函数,只有一个参数的时候,也需要括号
  arrowParens: 'always',
  // 每个文件格式化的范围是文件的全部内容
  rangeStart: 0,
  rangeEnd: Infinity,
  // 不需要写文件开头的 @prettier
  requirePragma: false,
  // 不需要自动在文件开头插入 @prettier
  insertPragma: false,
  // 使用默认的折行标准
  proseWrap: 'preserve',
  // 根据显示样式决定 html 要不要折行
  htmlWhitespaceSensitivity: 'css',
  // 换行符使用 lf
  endOfLine: 'lf',
}

建立.prettierignore

/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*

vscode安装eslint,prettier插件

{
  // vscode默认启用了根据文件类型自动设置tabsize的选项
  "editor.detectIndentation": false,
  // 重新设定tabsize
  "editor.tabSize": 2,
  // 每次保存的时候自动格式化
  "editor.formatOnSave": true,
  "editor.codeActionsOnSave": {
    // 使用eslint来fix,包括格式化会自动fix和代码质量检查会给出错误提示
    "source.fixAll.eslint": true
  },
  // 把prettier设置为vscode默认的代码格式化工具
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // vue文件的默认格式化工具选择prettier
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}

ESLint与Prettier会有冲突,和vue的一些语法冲突

pnpm add eslint-config-prettier eslint-plugin-prettier vue-eslint-parser -D

eslint-config-prettier 会关闭ESLint中有关代码格式化的配置 eslint-plugin-prettier 把Prettier配置成ESLint的一个插件,让其当做一个linter规则来运行 去掉驼峰写法,index 修改.eslint.cjs

extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  overrides: [],
  parser: 'vue-eslint-parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    parser: '@typescript-eslint/parser',
  },

  rules: {
    '@typescript-eslint/ban-types': [
      'error',
      {
        extendDefaults: true,
        types: {
          '{}': false,
        },
      },
    ],
    'vue/multi-word-component-names': [
      'error',
      {
        ignores: ['index'], //需要忽略的组件名
      },
    ],
  },

在运行时,检测

pnpm add vite-plugin-eslint -D

修改vite.config.ts配置

import eslintPlugin from 'vite-plugin-eslint'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
import { resolve } from 'path'
export default defineConfig({
  plugins: [
    vue(),
    vueSetupExtend(),
    eslintPlugin({
      include: ['src/**/*.ts', 'src/**/*.js', 'src/**/*.vue', 'src/*.ts', 'src/*.js', 'src/*.vue'],
    }),
  ],
})

加些插件

vite-plugin-vue-setup-extend

此插件解决了:使用setup语法糖的时候没办法直接为组件定义name(页面缓存需要name属性)

pnpm add vite-plugin-vue-setup-extend -D

在vite.config.ts配置

import vueSetupExtend from 'vite-plugin-vue-setup-extend'
plugins: [
    vueSetupExtend ()
    ]

在页面中使用

<script lang="ts" setup name="自定义name">

</script>

unplugin-auto-import

自动引入vue等的api

pnpm add unplugin-auto-import -D

在vite.config.ts配置

import AutoImport from 'unplugin-auto-import/vite'
plugins: [
    AutoImport({
      imports: ['vue', 'vue-router', 'pinia'], // 自动导入vue、vue-router、pinia相关API
      dts: 'src/auto-import.d.ts', // 生成 `auto-import.d.ts` 全局声明
      eslintrc: {
        enabled: true, // Default `false`
      },
    }),
]

在eslintrc.cjs配置'./.eslintrc-auto-import.json',重启

 extends: [
    'eslint:recommended',
    'plugin:vue/vue3-essential',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
    './.eslintrc-auto-import.json',
  ],

vite-plugin-compression

静态文件压缩

pnpm install vite-plugin-compression -D

配置

import viteCompression from 'vite-plugin-compression'
plugins: [
     viteCompression({
      verbose: true,
      disable: false, // 不禁用压缩
      deleteOriginFile: false, // 压缩后是否删除原文件
      threshold: 10240, // 压缩前最小文件大小
      algorithm: 'gzip', // 压缩算法
      ext: '.gz' // 文件类型
    })
   ]

rollup-plugin-visualizer

打包后的视图文件——生成一个stats.html文件

pnpm install rollup-plugin-visualizer -D

配置

import {visualizer} from 'rollup-plugin-visualizer'
plugins: [
    visualizer({
      open:true,  //注意这里要设置为true,否则无效
      gzipSize:true,
      brotliSize:true
    }),
   ]

安装pinia

pnpm add pinia 

在src目录新建store文件夹,新建index.ts文件,代码如下:

// 因为用了“unplugin-auto-import”插件 可以不需要再import Pinia的API
// import { createPinia } from 'pinia'
// 创建pinia状态管理对象
const pinia = createPinia()
export default pinia

在main.ts文件中引入,代码如下:

import pinia from './store'
app.use(pinia)

在store文件夹中新建modules文件夹(当然也可以不建,我这是为了区分管理),新建user.ts文件,代码如下:

const useUserStore = defineStore('user', {
  state: () => {
    return {
      token: '',
      name: '',
      avatar: '',
      nickName: '',
      userId: null,
      dept: {},
      permissions: [],
      permBtn: [],
      permCode: [],
    }
  },
  getters: {},
  actions: {},
})

export default useUserStore

使用 defineStore() 定义一个 Store ;defineStore() 第一个参数是 storeId (必须要),第二个参数是一个选项对象:中有state(是一个函数返回一个对象)、getters、actions store 是一个用 reactive 包裹的对象,如果直接解构会失去响应性。我们可以使用 storeToRefs() 对其进行解构:

import useUserStore from '@/store/modules/user'
const userStore= useUserStore()
const { hello: myHello } = storeToRefs(userStore)

集成qiankun(微前端)父级项目

pnpm install qiankun

修改main.ts

import { registerMicroApps, start } from 'qiankun'
registerMicroApps(
  [
    {
      name: 'subApp', // 必须与微应用注册名字相同
      entry: 'http://192.168.8.50:3301', // 入口路径,开发时为微应用所启本地服务,上线时为微应用线上路径
      container: '#sub-app-container', // app.vue 配置的挂载容器 id
      activeRule: '/subapp', // 当访问路由为 home 时加载微应用
      props: {
        // 主应用向微应用传递参数
      },
    },
  ],
  {
    //生命周期钩子函数
    beforeLoad: async (app) => {
      console.log('beforeLoad', app)
    },
    beforeMount: async (app) => {
      console.log('beforeMount ', app)
    },
    afterMount: async (app) => {
      console.log('afterMount', app)
    },
    beforeUnmount: async (app) => {
      console.log('beforeUnmount ', app)
    },
    afterUnmount: async (app) => {
      console.log('afterUnmount', app)
    },
  },
)

// 启动 qiankun
start()

集成qiankun(微前端)子级项目

安装vite-plugin-qiankun

pnpm add vite-plugin-qiankun

修改vite.config.ts

import qiankun from 'vite-plugin-qiankun'
plugins: [
qiankun('subApp', {
    // 微应用名字,与主应用注册的微应用名字保持一致
    useDevMode: true,
  }),
  ],
server: {
  headers: {
    'Access-Control-Allow-Origin': '*',
  },
  host: '0.0.0.0',
  port: 3301,
},

修改router.ts

import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const router = createRouter({
  history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/subApp/' : '/'),
  routes: routes,
})

修改main.ts

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import pinia from './store'
import router from './router'
import ElementPlus from 'element-plus'
import './style/element/index.scss'
import Cookies from 'js-cookie'
import locale from 'element-plus/lib/locale/lang/zh-cn'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
let instance: any = null
function render(props: any = {}) {
  const { container } = props
  instance = createApp(App)
  instance.use(router)
  instance.use(pinia)
  // 注册全局api方法
  // 注册所有图标
  for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
    instance.component(key, component)
  }
  // 注册ElementPlus
  instance.use(ElementPlus, {
    locale, // 语言设置
    // size: Cookies.get('size') || 'medium' // 尺寸设置
  })
  instance?.mount(container ? container.querySelector('#app') : '#app')
  console.log('开始加载相关内容')
}
renderWithQiankun({
  mount(props: any) {
    render(props)
  },
  bootstrap() {
    console.log('%c', 'color:green;', ' ChildOne bootstrap')
  },
  update() {
    console.log('%c', 'color:green;', ' ChildOne update')
  },
  unmount(props: any) {
    console.log('unmount', props)
    instance.unmount()
    instance._container.innerHTML = ''
    instance = null
  },
})
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
  console.log('并不是qiankun渲染')
  render()
}

封装自己的组件

给各自的组件都加上install

import YuButton from './src/index.vue'

YuButton.install = (App) => {
  App.component(YuButton.name, YuButton)
}

export default YuButton

统一暴露给外部

import YuButton from './button'

//按需引入
export { YuButton }

const components = [YuButton]

const YuUI = {
  install(App) {
    components.forEach((item) => {
      App.component(item.name, item)
    })
  },
}

export default YuUI

安装vitepress

一个md和vue都可以使用的文档

pnpm add vitepress vitepress-theme-demoblock -D

新建doces文件夹,创建首页

---
layout: home

title: Yu-el-ui
# titleTemplate: 选项卡描述
editLink: true
lastUpdated: true
hero:
  name: Yu-el-ui
  text: vue3基础组件
  tagline: Vue3 中基于Element-plus二次封装基础组件文档
  image:
    src: /img/wocwin.jpg
    alt: Yu-el-ui
  actions:
    - theme: brand
      text: 安装指南
      link: /components/
    - theme: brand
      text: 组件预览
      link: /components/TSelect/base.md
features:
  - icon: 🔨
    title: 实际项目
    details: 实际项目中碰到的疑点、难点,致力于更优的自我。。
  - icon: 🧩
    title: 基础组件
    details: 基于Element-plus二次封装;使用组件 Demo 快速体验交互细节。。
  - icon: ✈️
    title: Vue驱动。
    details: 享受 Vue3 + vite3 的开发体验,在 Markdown 中使用 Vue 组件,同时可以使用 Vue 来开发自定义主题。
---
<!-- <p style="display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 10px;">
  <a href="https://github.com/vuejs/vue" target="_blank">
    <img src="https://img.shields.io/badge/vue-3.2.36-brightgreen.svg" alt="vue3">
  </a>
  <a href="https://gitee.com/wocwin/t-ui-plus/stargazers" target="_blank">
    <img src="https://gitee.com/wocwin/t-ui-plus/badge/star.svg?theme=dark" alt="t-ui-plus">
  </a>
   <a href="https://github.com/wocwin/t-ui-plus/stargazers" target="_blank">
    <img src="https://img.shields.io/github/stars/wocwin/t-ui-plus.svg" alt="t-ui-plus">
  </a>
   <a href="https://www.npmjs.com/package/@wocwin/t-ui-plus" target="_blank">
      <img alt="npm" src="https://img.shields.io/npm/v/@wocwin/t-ui-plus.svg" />
    </a>
</p> -->

新建components,放对应的组件说明和示例 新建.vitepress文件夹config.ts

import { defineConfig } from 'vitepress'
import { demoBlockPlugin } from 'vitepress-theme-demoblock'
export default defineConfig({
  title: 'yuui基础组件文档',
  description: '基于Element-plus基础组件封装使用',
  lang: 'cn-ZH',
  base: '/yuui/',
  lastUpdated: true,
  themeConfig: {
    logo: '/favicon.ico',
    siteTitle: 'yuui基础组件文档',
    outline: 3,
    nav:[
      { text: '基础组件', link: '/components/Yubutton/base.md' },
    ],
    sidebar:{
      '/components': [
        // {
        //   text: '常用组件',
        //   items: [
        //     { text: '下拉选择组件', link: '/components/TSelect/base.md' },
        //     { text: '下拉选择表格组件', link: '/components/TSelectTable/base.md' },
        //   ]
        // },
      ]
    }
  },
  markdown: {
    config(md) {
      md.use(demoBlockPlugin, {
        customClass: 'demoblock-custom'
      })
    }
  }
})

新增命令

  "docs:dev": "pnpm run register:components && vitepress dev docs",

  "docs:build": "pnpm run register:components && vitepress build docs",

  "register:components": "vitepress-rc"

通过github预览页面

修改config.ts里面的base

 base: '/yu-el-ui/',

添加命令,deploy.sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
pnpm run docs:build

# 进入生成的文件夹
cd ./docs/.vitepress/dist

git init
git add -A
git commit -m 'deploy'

# 如果发布到 https://<USERNAME>.github.io/<REPO>
git push -f https://github.com/onewebstudy/yu-el-ui.git master:gh-pages

cd -
"deploy": "deploy.sh"