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

结尾

好了 结束

相关推荐
EricWang135816 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning16 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
web行路人26 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
超雄代码狂1 小时前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石1 小时前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程1 小时前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员
周亚鑫2 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
落魄小二2 小时前
el-table 表格索引不展示问题
javascript·vue.js·elementui
Justinc.2 小时前
CSS3新增边框属性(五)
前端·css·css3