vite+vue3+ts+eslint+pinia+tailwindcss+element-plus初始化项目

背景

最近有朋友要搭建一个vue3+ts的项目,本着帮一把的原则,搭建了一个,仅仅作为参考,市场很多成熟框架如admin等。好记性不如烂笔头记录下,目录如下 后面不在重复提及

项目搭建

采用vite vue3 ts eslint pinia tailwindcss element-plus 等搭建项目,下面分布记录下

vite初始化项目

js 复制代码
npm create vite

输入文件名称,回车即可,默认名称为vite-project

选择vue ts 回车 创建成功

js 复制代码
cd vite-tets-work
  npm install
  npm run dev

安装依赖 dev项目启动成功, 默认http://localhost:5173/端口

安装sass

js 复制代码
 npm i -D sass

安装@types/node

解决vite.config.ts的 import path from "node:path"; ts报错问题

js 复制代码
npm i @types/node -D

设置别名和sever 设置代理及端口设置

vite.config.ts文件做以下修改,此时端口已更改且默认打开浏览器

js 复制代码
import { defineConfig } from 'vite'
import path from "node:path";
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue()
  ],
  base: "./",
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  // 配置代理
  server: {
    host: "0.0.0.0",
    port: 8861,
    open: true,
    proxy: {
      "/api": {
        target: "***********",
        changeOrigin: true,
        secure: false,
        // rewrite: (path) => path.replace(/^\/api/, ""),
      }
    },
    cors: true,
  },
})

tsconfig.json 做以下修改

js 复制代码
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,

    // @设置
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    },
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.d.ts"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

router路由

js 复制代码
npm i vue-router -S

创建router文件夹,内部创建index.ts

js 复制代码
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
import TestRoutes from '@/views/test/routes';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    name: 'Login',
    component: () => import('@/views/login/index.vue')
  },
  {
    path: '/test',
    name: 'test',
    children: [...TestRoutes],
    meta: {
      sort: 1,
      icon: 'FillSet',
      title: '测试带单',
      menu: true
    }
  }
];
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    return { top: 0 };
  },
  history: createWebHistory(),
  routes
});

router.beforeEach((to: any, from, next) => {
  next();
});

export default router;

创建views文件夹,下一级创建login test文件夹。目录如下,请自行创建对应文件

test 中的 routes.ts如下

js 复制代码
import { RouteRecordRaw } from 'vue-router';

const routes: Array<RouteRecordRaw> = [
  {
    path: 'test1',
    name: 'test1',
    component: () => import('@/views/test/test1.vue'),
    meta: {
      title: '测试1'
    }
  },
  {
    path: 'test2',
    name: 'test2',
    component: () => import('@/views/test/test2.vue'),
    meta: {
      title: '测试2'
    }
  }
];

export default routes;

main.ts 引用路由

js 复制代码
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";

// routes
import router from "./router/index";

const app = createApp(App);
app.use(router);
app.mount("#app");

app.vue文件引入 <router-view/>

js 复制代码
<template>
  <div>
    <router-view/>
  </div>
</template>

<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

此时如果报ts 找不到模块"vue-router"或其相应的类型声明重新打开下vscode即可

重新 npm run dev 默认http://localhost:8861/login 打开你的login组件, http://localhost:8861/test/test1会打开test下的test1组件。

安装pinia

pinia

js 复制代码
 npm i pinia -S
 npm i pinia-plugin-persistedstate -S

pinia-plugin-persistedstate为了持久化pinia

创建 store文件夹,内部创建 use-user.ts,内容如下

js 复制代码
// src/stores/counter.ts
import { defineStore } from 'pinia';
import { reactive } from 'vue';

export const useUserInfoStore = defineStore(
  'userInfo',
  () => {
    const user = reactive({
      name: '',
      age: '',
      sex: ''
    });

    const setUserInfo = (data: { name: string, age: string, sex: string }) => {
      Object.assign(user, data);
    };

    return { user, setUserInfo };
  },
  {
    persist: true,
  }
);

login 中的index.vue修改为

js 复制代码
<template>
  <div>
    <span class="text-[#ff0000]">{{ user }}</span>
    <button @click="addStore">点击</button>
  </div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useUserInfoStore } from "@/store/use-user";

const userInfoStore = useUserInfoStore();

const { user } = storeToRefs(userInfoStore);

const addStore = () => {
  userInfoStore.setUserInfo({
    name: "张三",
    age: Math.random() * 100 + "",
    sex: "男"
  });
};
</script>

test中的 test1.vue修改为

js 复制代码
<template>
    <hl-group class="empty" align="items-center items-middle" dir="vertical" gap="var(--md)">
      {{ JSON.stringify(user) }}
    </hl-group>
  </template>

<script lang="ts" setup>
import { useUserInfoStore } from '@/store/use-user';
import { storeToRefs } from 'pinia';

const userInfoStore = useUserInfoStore();

const { user } = storeToRefs(userInfoStore);
</script>

main.ts中引入pinia

js 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';

//routes
import router from "./router/index";

const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);

const app= createApp(App)

app.use(pinia);
app.use(router);
app.mount('#app');

此时login组件操作,可修改piniatest1组件会获取到pinia状态, 此时ts 报错 store找不到重启vscode即可

安装element-plus @element-plus/icons-vue 及动态导入

element-plus unplugin-vue-components unplugin-auto-import自动导入插件,可以按需引入不用此插件

js 复制代码
npm i element-plus @element-plus/icons-vue -S
npm install unplugin-vue-components unplugin-auto-import -D

vite.config.ts做更改

js 复制代码
import { defineConfig } from 'vite'
import path from "node:path";
import vue from '@vitejs/plugin-vue'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import AutoImport from "unplugin-auto-import/vite"
import Components from 'unplugin-vue-components/vite';

export default defineConfig({
  plugins: [
    vue(),
    Components({
      resolvers: [ElementPlusResolver()],
      dts: "src/components.d.ts",
    }),
    AutoImport({
      imports: ['vue', 'vue-router'],
      dts: "src/auto-import.d.ts",
    })
  ],
  base: "./",
  // base: "/rag",
  // 配置别名
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  // 配置代理
  server: {
    host: "0.0.0.0",
    port: 8861,
    open: true,
    proxy: {
      "/api": {
        target: "***********",
        changeOrigin: true,
        secure: false,
      }
    },
    cors: true,
  },
})

login组件做更改

js 复制代码
<template>
  <div>
    <span>{{ user }}</span>
    <button @click="addStore">点击</button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useUserInfoStore } from "@/store/use-user";

const userInfoStore = useUserInfoStore();

const { user } = storeToRefs(userInfoStore);

const addStore = () => {
  userInfoStore.setUserInfo({
    name: "张三",
    age: Math.random() * 100 + "",
    sex: "男"
  });
};
</script>

可见element-plus已经引入,button组件展示

安装tailwindcss

tailwindcss

js 复制代码
npm install -D tailwindcss postcss autoprefixer
js 复制代码
npx tailwindcss init -p

两步骤操根目录生成 postcss.config.js

js 复制代码
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

tailwind.config.js

js 复制代码
/** @type {import('tailwindcss').Config} */
export default {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

有次两步文件及初始化成功,创建styles文件夹 下级创建index.css tailwind.css

index.css

js 复制代码
@import url('tailwind.css');

tailwind.css

js 复制代码
/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

main.ts 引入 tailwindcss

js 复制代码
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';

import "@/styles/index.css";

//routes
import router from "./router/index";

const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);

const app= createApp(App)

app.use(pinia);
app.use(router);
app.mount('#app');

tailwind.config.js 做如下更改

js 复制代码
/** @type {import('tailwindcss').Config} */
export default {
  darkMode: "class",
  corePlugins: {
    preflight: false
  },
  content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
  theme: {
    extend: {
      colors: {
        title: "#202020",
        secondTitle: "#8A8A8A",
        normal: "#4b4b4b",
        light: "#dddddd",
        active: "#2C54D1",
        disabled: "#aaaaaa",
      },
      fontSize: {
        20: "20px",
        18: "18px",
        16: "16px",
        14: "14px",
      },
    },
  },
  plugins: [],
}

login 中的 index.vue试用下 tailwindcss class="text-[#ff0000]" 样式已生效

js 复制代码
<template>
  <div>
    <span class="text-[#ff0000]">{{ user }}</span>
    <button @click="addStore">点击</button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </div>
</template>
<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useUserInfoStore } from "@/store/use-user";

const userInfoStore = useUserInfoStore();

const { user } = storeToRefs(userInfoStore);

const addStore = () => {
  userInfoStore.setUserInfo({
    name: "张三",
    age: Math.random() * 100 + "",
    sex: "男"
  });
};
</script>

此时如果 tailwind.css 报错 Unknown at rule @tailwindcss(unknownAtRules),在跟目录创建.vscode下级settings.json ,可消除报错

js 复制代码
{
    "css.lint.unknownAtRules": "ignore"
  }
  

eslint

恰逢eslint@9 及扁平化配置出来,技术有限,配置了半天没搞定扁平化配置,还是使用非扁平化的配置方式, package.jsondevDependencies增加如下依赖 eslint,哪位大佬搞出扁平化配置了,踢我一脚

js 复制代码
"@typescript-eslint/parser": "^7.7.0",
"@vue/eslint-config-standard": "^8.0.1",
"@vue/eslint-config-typescript": "^13.0.0",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-vue": "^9.25.0",
"vite-plugin-eslint": "^1.8.1",
"prettier-eslint": "^16.3.0",

重新 npm i 安装依赖

根目录创建.eslintignore

js 复制代码
**/iconfont.js
**/flexable.js
src/apis/modules/*
src/apis/**/model.ts
node_modules

.eslintrc.cjs

js 复制代码
module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    "plugin:vue/vue3-essential",
    "@vue/standard",
    "@vue/typescript/recommended",
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  ignorePatterns: [
    "*.config.*",
    "dist/*",
    "build/*",
    "public/*",
    "src/apis/modules/**",
  ],
  rules: {
    "no-console": "error"
  },
  globals: {
    uap: "readonly",
    uni: "readonly",
    regist: "readonly",
    defineProps: "readonly",
    defineOptions: "readonly",
    defineEmits: "readonly",
    defineExpose: "readonly",
  },
};

打开vscode 安装 eslint 插件,打开保存即可

test test1.vue 写一句console.log(1111) eslint已经生效

安装axios

js 复制代码
npm i axios -S

关于 axios 一个封装请求,尅要根据自己业务需要特定的封装,官方文档如下 axios

结尾

好了 结束

相关推荐
进阶的小木桩2 小时前
Vue 3 + Elementui + TypeScript 实现左侧菜单定位右侧内容
vue.js·elementui·typescript
whysqwhw2 小时前
js之Promise
前端
恋猫de小郭5 小时前
Flutter 3.35 发布,快来看看有什么更新吧
android·前端·flutter
chinahcp20086 小时前
CSS保持元素宽高比,固定元素宽高比
前端·css·html·css3·html5
gnip7 小时前
浏览器跨标签页通信方案详解
前端·javascript
gnip8 小时前
运行时模块批量导入
前端·javascript
hyy27952276848 小时前
企业级WEB应用服务器TOMCAT
java·前端·tomcat
逆风优雅8 小时前
vue实现模拟 ai 对话功能
前端·javascript·html
若梦plus9 小时前
http基于websocket协议通信分析
前端·网络协议
不羁。。9 小时前
【web站点安全开发】任务3:网页开发的骨架HTML与美容术CSS
前端·css·html