当前位置: 首页 > news >正文

从零开始搭建企业级前端项目模板(vue3+vite+ts)

文章目录

  • 主要内容
  • 一、vite脚手架工具初始化项目
  • 二、项目代码加入eslint校验和自动格式化
    • 2.1安装对应依赖插件
    • 2.2 配置script脚本,项目安装eslint配置
    • 2.3 安装完成后,后面启动项目还缺少一些依赖,提前按需安装好
  • 三,修改eslintrc.cjs文件
  • 四、修改vue.config.ts文件
  • 五、修改添加常见配置
  • 六、Husky、lint-staged、commitlint功能添加
  • 七、stylelint钩子,校验css
  • 八、环境配置(开发,预发,生产环境)
  • 九、vite.config.js配置
  • 十、添加路由
  • 十一、添加api,封装请求(axios)
  • 十二、pinia状态管理器

主要内容

vite,eslint,prettierrc,husky,commitlint,lint-staget,stylelint,vuex,vue-router,axios,pinia
环境:win11,node 18.17.0 ,pnpm 8.12.0

一、vite脚手架工具初始化项目

vite官网:初始化项目:https://cn.vitejs.dev/guide/,本文以pnpm创建项目

# npm 7+, extra double-dash is needed:
npm create vite@latest vue3_project_template --template vue-ts# yarn
yarn create vite vue3_project_template --template vue-ts# pnpm
pnpm create vite vue3_project_template --template vue-ts# bun
bunx create-vite vue3_project_template --template vue-ts
  • 创建好项目
  • 根据创建项目提示输入命令
  cd vue3_project_templatepnpm installpnpm run dev
  • 运行结果如下
    在这里插入图片描述

二、项目代码加入eslint校验和自动格式化

node工具eslint官网
eslint 运行代码前就可以发现一些语法错误和潜在bug,保证团队代码的一直性

prettier格式化官网
prettier 是代码格式化工具,用于检查代码中的格式问题

区别联系:eslint保证代码质量,prettier保证代码风格,eslint有小部分格式化功能,通常和prettier结合使用

2.1安装对应依赖插件

eslint: ESLint的核心代码库
prettier:prettier格式化代码的核心库
eslint-config-airbnb-base: airbnb的代码规范 (依赖plugin-import)
eslint-config-prettier:eslint结合prettier的格式化
eslint-plugin-vue:eslint在vue里的代码规范
eslint-plugin-import:项目里面支持eslint
eslint-plugin-prettier:将prettier结合进入eslint的插件

pnpm install eslint eslint-plugin-vue eslint-config-prettier prettier eslint-plugin-import eslint-plugin-prettier eslint-config-airbnb-base -D

vscode 安装两个插件
在这里插入图片描述

在这里插入图片描述

2.2 配置script脚本,项目安装eslint配置

  • 在package.json文件scripts加入命令
    "lint:create":"eslint --init"
    在这里插入图片描述
  • 执行npm run lint:create
npm run lint:create
  • 执行之后会自动创建.eslintrc.cjs文件
    在这里插入图片描述

2.3 安装完成后,后面启动项目还缺少一些依赖,提前按需安装好

@typescript-esTint/parser: ESLint的解析器,用于解析typescript,从而检查和规范Typescript代码;
@typescript-eslint/eslint-plugin: 这是一个ESLint插件,包含了各类定义好的检测Typescript代码的规范
eslint-import-resolver-alias 让我们可以import的时候使用 @ 别名

pnpm install typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-alias @types/eslint @types/node -D

三,修改eslintrc.cjs文件

  • eslintrc.cjs主要内容如下
module.exports = {// 环境 浏览器,最新ES语法,node环境"env": {"browser": true,"es2021": true,"node": true},/*** 扩展的eslint规范语法,可以被继承的规则,字符串数组,每个配置继承它之前的配置* 分别是eslint-config-vue 提供的* eslint-config-airbnb-base 提供的* eslint-config-prettier 提供的* eslint-config- 前缀可以简写*/"extends": ["eslint:recommended","plugin:@typescript-eslint/recommended","plugin:vue/vue3-essential","airbnb-base","prettier"],// eslint 会对代码进行校验,parser是将代码转换为ESTree(AST),ESlint会对ESTree校验"parser": "vue-eslint-parser",// 解析器的配置项"parserOptions": {// eslint的版本号,或者年份都可以"ecmaVersion": "latest","parser": "@typescript-eslint/parser","sourceType": "module",// 额外的语言类型"ecmaFeatures": {"jsx": true,"tsx": true}},// 全局自定义宏,这样在源文件中使用全局变量不会报错或警告"globals": {"defineProps": 'readonly',"defineEmits": 'readonly',"defineExpose": 'readonly',"withDefaults": 'readonly'},/*** 插件* eslint-plugin- 前缀可以简写* vue官方提供了一个eslint插件eslint-plugin-vue,它提供了parser和rules。* parser为vue-eslint-parser,放在前面的parser字段里,rules放在extends字段里*/"plugins": ["@typescript-eslint","vue"],"settings": {// 设置项目内的别名"import/resolver": {"alias": {"map": [['@','./src']]}},"import/extensions": ['.js','.jsx','.tsx','.ts','.mjs','.cjs']},/*** rules: 自定义规则,覆盖extends继承的规则,对规则进行灵活配置** "off" 或 0    ==>  关闭规则* "warn" 或 1   ==>  打开的规则作为警告(不影响代码执行)* "error" 或 2  ==>  规则作为一个错误(代码不能执行,界面报错)*/"rules": {// eslint(https://eslint.bootcss.com/docs/rules/)'no-var': 'error', // 要求使用 let 或 const 而不是 var'no-multiple-empty-lines': ['warn', { max: 2 }], // 不允许多个空行'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off','no-unexpected-multiline': 'error', // 禁止空余的多行'no-useless-escape': 'off', // 禁止不必要的转义字符'import/no-unresolved': 'off','import/extensions': 'off','import/no-absolute-path': 'off','import/no-extraneous-dependencies': 'off','import/prefer-default-export': 'off',// typeScript (https://typescript-eslint.io/rules)'@typescript-eslint/no-unused-vars': 'error', // 禁止定义未使用的变量'@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型'@typescript-eslint/no-non-null-assertion': 'off','@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。'@typescript-eslint/semi': 'off',// eslint-plugin-vue (https://eslint.vuejs.org/rules/)'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用'vue/no-mutating-props': 'off', // 不允许组件 prop的改变'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式},
}
  • 修改package.json文件,添加如下命令

"lint": "eslint \"src/**/*.{js,ts,vue}\" --fix"

四、修改vue.config.ts文件

pnpm install vite-plugin-eslint -D vite的一个插件,让项目可以方便的得到eslint支持,完成eslint配置后,可以快速的将其集成进vite中,便于在代码不符合eslint规范的第一时间看到提示

pnpm install vite-plugin-eslint -D 

import eslintPlugin from “vite-plugin-eslint”
plugins: [vue(),eslintPlugin()],

五、修改添加常见配置

项目根目录创建以下配置文件
.eslintrcignore 忽略校验文件
.prettierrc.cjs 配置格式化规则
.prettierignore 忽略格式化文件

  • .eslintrcignore
# .eslintrcignore*.sh
node_modules
*.md
*.woff
*.ttf
dist
/pubilc
/docs
.husky
/bin
.eslintrc.js
perttier.config.js
/src/mock/*# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*
lerna-debug.log*.DS_Store
dist-ssr
*.local/cypress/videos/
/cypress/screenshots/# Editor directories and files
.vscode
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?components.d.ts
  • .prettierrc.cjs
module.exports = {printWidth: 80, // 一行最多100字符tabWidth: 2, // 使用2个空格缩进useTabs: false, // 不适用缩进符,使用空格semi: false, // 行尾是否要有分号singleQuote: true, // 使用单引号quoteProps: 'as-needed', // 对象的key,仅仅在必要时使用引号jsxSingleQuote: false, // jsx是否使用双引号trailingComma: 'es5', // 尾随逗号bracketSpacing: true, // 大括号内的首尾需要有空格arrowParens: 'always', // 箭头函数,是有一个参数的时候,也需要小括号rangeStart: 0, // 文件格式化的范围是全部内容rangeEnd: Infinity,requirePragma: false, // 不需要写文件开头的 @prettierinsertPragma: false, // 不需要在文件开头插入 @prettierproseWrap: 'always', // 使用默认执行标准htmlWhitespaceSensitivity: 'css', // 根据显示样式决定html是否执行endOfLine: 'lf' // 换行符是有lf
}
  • .prettierignore
# prettierignore
/dist/*
.local
.output.js
/node_modules/**
src/.DS_Store**/*.svg
**/*.sh
/pubilc/*
components.d.ts
  • 在package.json添加格式化命令

"prettier-format": "prettier --config .prettierrc.cjs \"src/**/*.{js,ts,vue}\" --write"

六、Husky、lint-staged、commitlint功能添加

husky是一个我git客户端增加hook钩子的工具,在一些git操作前自动触发的函数;https://ty.picode.github.io/husky/#/;如果我们希望在检测错误的同事,自动修复eslint语法错误,就可以通过后面的钩子实现

lint-staged过滤出Git代码暂存区文件(被git add的文件)的工具,将所有暂存文件的列表传递给任务

commitlint是对我们git commit提交的注释进行校验的工具

  1. 可以让我们在如git commit,git push执行前,预先处理我们指定的任务
pnpm install lint-staged husky -D

配置package.json文件
(新项目需要先git init 一下)
"prepare":"husky install"
执行命令:
npm run prepare

  1. 后面就开始添加各种git hook钩子

pre-commit钩子一般添加的是lint-stage 去对git暂存区的代码做一些格式化操作
npx husky add .husky/pre-commit "npx lint-staged"
add —> 追加
set —> 直接覆盖

  1. lint-staged对add之后,暂存区里面的文件进行格式化修复等工作
    pnpm install lint-staged -D
    packge.json文件中添加
"lint-staged": {"src/**/*.{js,ts,vue}": ["prettier --write","eslint --fix","git add"]
},

或者放入脚本命令:

"lint-staged": {"*.{js,ts,vue,tsx,jsx}": ["npm run lint","npm run prettier-format"]
}

或者

"*.{ts,js,vue}": ["eslint --fix"
],
"*.{html,scss,css,vue}": ["prettier --write","stylelint --fix"
]

packge.json文件里面, 添加有两个脚本命令
"lint": "eslint \"src/**/*.{js,ts,vue}\" --fix", 既可以检查又可以修复部分语法问题
"prettier-format": "prettier --config .prettierrc.cjs \"src/**/*.{js,ts,vue}\" --write", 利用prettier手动格式化一些样式问题

  1. git commit提交时说明清楚更新内容
    pnpm install @commitlint/config-conventional @commitlint/cli -D 安装两个库,然后新建一个代码提交配置文件config
    添加到git钩子
    npx husky add .husky/commit-msg "npx --no -- commitlint --edit ${1}" 通过一个命令添加钩子
    使用git commit -m “提交说明” ,进行提交,提交说明尽量清晰明了,说明本次提交的目的,推荐使用angular规范,这是目前使用最广泛的写法
    项目根目录添加commitlint.config.cjs文件
// commitlint.config.cjsmodule.exports = {extends: ['@commitlint/config-conventional'],rules: {'type-enum': [2,'always',['build', // 编译相关的修改,例如发布版本,对项目构建或者依赖的改动'feat', // 新功能'fix', // 修复bug'upd', // 更新某个功能'refactor', // 重构'docs', // 文档'chore', // 构建过程或辅助工具的变动,比如增加依赖库'style', // 格式(不影响代码运行的变动)'revert', // 撤销commit,回滚到上一个版本'perf', // 性能优化'test', // 测试(单元,集成测试)],],'type-case': [0],'type-empty': [0],'scope-empty': [0],'scope-case': [0],'subject-full-stop': [0,'never'],'subject-case': [0,'never'],'header-max-length': [0,'always',72],},
};

常用的git hooks
pre-commit:由git commit 调用,在commit之前执行
commit-msg:由git commit或git merge调用
pre-merge-commit:由git merge 调用, 在merge之前执行
pre-push:被git push 调用,在git push 前执行,防止进行推送

七、stylelint钩子,校验css

css 代码检查器(linter),帮助规避css代码中错误并保持一致的编码风格

  1. 安装 vscode插件,stylelint插件
    在这里插入图片描述

  2. 修改setting.json,添加下面几行代码

{"editor.codeActionsOnSave": {"source.fixAll.stylelint": true},"stylelint.validate": [ "css", "scss", "less", "vue"]
}
  1. 安装依赖
    pnpm install --save-dev stylelint stylelint-config-standard
  2. 根目录创建 .stylelintrc.cjs
// @see https://stylelint.bootcss.com/module.exports = {extends: ['stylelint-config-standard', // 配置stylelint拓展插件'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化'stylelint-config-standard-scss', // 配置stylelint scss插件'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,'stylelint-config-prettier', // 配置stylelint和prettier兼容],overrides: [{files: ['**/*.(scss|css|vue|html)'],customSyntax: 'postcss-scss',},{files: ['**/*.(html|vue)'],customSyntax: 'postcss-html',},],ignoreFiles: ['**/*.js','**/*.jsx','**/*.tsx','**/*.ts','**/*.json','**/*.md','**/*.yaml',],/*** null  => 关闭该规则* always => 必须*/rules: {'value-keyword-case': null, // 在 css 中使用 v-bind,不报错'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"'no-empty-source': null, // 关闭禁止空源码'selector-class-pattern': null, // 关闭强制选择器类名的格式'property-no-unknown': null, // 禁止未知的属性(true 为不允许)'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask'selector-pseudo-class-no-unknown': [// 不允许未知的选择器true,{ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修改element默认样式的时候能使用到},],},
}

这是一个标准样式库,也可自动加一下样式规则在.stylelintrc.cjs文件里面

  1. 执行命令
    npx stylelint "**/*.css"
    发现项目里面的style.css全局样式报错,具体到对应文件,安ctrl+s就回执行,自动格式化,我们在setting.json里面添加的json语句
    修改错误的颜色值之后,执行 npx stylelint "**/*.css" 会告诉我们颜色错误

  2. 增加对vue里面的样式校验(附带less和sass的支持)
    pnpm install stylelint-less stylelint-config-recommended-less -D 对less的支持
    pnpm install stylelint-scss stylelint-config-recommended-scss postcss -D 对sass的支持
    pnpm install postcss-html stylelint-config-standard-scss stylelint-config-recommended-vue postcss -D 对vue里面的样式支持(vue样式需要依赖这个库)
    vite 也同时提供了对.scss,.sass,.less,.style和.stylus文件的内置支持,不需要在安装特定插件和预处理器

extends: ["stylelint-config-standard","stylelint-config-recommended-less","stylelint-config-recommended-scss","stylelint-config-recommended-vue"

sass的extends

"extends": ["stylelint-config-standard-scss","stylelint-config-recommended-vue/scss",
]
  1. 新建.stylelintignore文件

.stylelintignore: 忽略文件校验

/node_modules/*
/dist/*
/html/*
/public/*
  1. 修改package.json文件
    "lint:css": "stylelint src/**/*.{css,scss,sass,less,html,vue} --cache --fix"

  2. 给vite添加插件
    pnpm install vite-plugin-stylelint -D
    添加完成依赖,然后修改vite.config.js
    import StylelintPlugin from 'vite-plugin-stylelint'
    plugin:[... StylelintPlugin({fix:true})

  3. 添加到lint-staged,在暂存区自动对文件进行格式化

"lint-staged": {"*.{js,ts,vue,tsx,jsx}": ["npm run lint","npm run prettier-format"],"*.{vue,less,scss,sass,html}": ["npm run lint:css"]}

添加完成后,在进行代码commit的时候就会执行npm run lint:css命令校验我们的css代码了

八、环境配置(开发,预发,生产环境)

开发环境:开发人员开发的环境
测试环境:测试人员测试的环境
预发环境:准备上线的环境,也可叫内测环境
生产环境:正式线上环境,投入生产的环境

这里我们配置两个环境,一个测试环境和生产环境,
开发人员和测试人员使用测试环境,修改package.json文件,添加两个命令
"build:dev": "vue-tsc --noEmit && vite build --mode development",
"build:pro": "vue-tsc --noEmit && vite build --mode production",

  • 新建两个配置文件

.env.development:开发测试环境
.env.production:生产环境

# .env.development
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '项目模版'
VITE_APP_BASE_API = '/dev_api'
# .env.production
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'production'
VITE_APP_TITLE = '项目模版'
VITE_APP_BASE_API = '/pro_api'

九、vite.config.js配置

/* eslint-disable import/no-extraneous-dependencies */
import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import StylelintPlugin from 'vite-plugin-stylelint'// https://vitejs.dev/config/
export default defineConfig(({ mode })=>{const env = loadEnv(mode, process.cwd());return {plugins: [vue(), eslintPlugin(), StylelintPlugin({ fix: true })],base: "./", // 在生产中服务时的基本公共路径publicDir: "public",  // 静态资源服务的文件夹, 默认"public"resolve: {alias: {"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src}},// 本地运行配置server: {host: "0.0.0.0", // 指定服务器主机名  0.0.0.0 可以看见network 通过ip访问port: 3000, // 指定服务器端口open: true, // 在服务器启动时自动在浏览器中打开应用程序strictPort: false, // 设置为false时,若端口被占用会尝试下一个可用端口, 而不是直接退出https: false, // 是否开启 httpscors: true, // 为开发服务器配置 CORS, 默认启用并允许任何源proxy: { // 为开发服务器配置自定义代理规则[env.VITE_APP_BASE_API]: {target: "http://192.168.xxx.xxx:xxxx", // 代理接口changeOrigin: true,rewrite: (_path) => _path.replace(/^\/api/, ""),}}},// 打包配置build: {target: "modules", // 设置最终构建的浏览器兼容目标。modules:支持原生 ES 模块的浏览器outDir: "dist", // 指定输出路径assetsDir: "assets", // 指定生成静态资源的存放路径assetsInlineLimit: "4096", // 小于此阈值的导入或引用资源将内联为base64编码,设置为0可禁用此项。默认4096(4kb)cssCodeSplit: true, // 启用/禁用CSS代码拆分,如果禁用,整个项目的所有CSS将被提取到一个CSS文件中,默认truesourcemap: false, // 构建后是否生成 source map 文件minify: "terser", // 混淆器,terser构建后文件体积更小write: true, // 设置为 false 来禁用将构建后的文件写入磁盘emptyOutDir: true,  // 默认情况下,若 outDir 在 root 目录下,则 Vite 会在构建时清空该目录。chunkSizeWarningLimit: 500,  // chunk 大小警告的限制terserOptions: {compress: {drop_console: true,drop_debugger: true,}}, // 去除 console debugger},}
})

十、添加路由

  1. pnpm install vue-router 安装路由依赖;
  2. 在src目录下新建router文件夹index.ts文件
// index.ts
// 通过vue-router插件实现模板路由配置
import { createRouter, createWebHistory } from 'vue-router'
import { constantRoute } from './routes'
// 创建路由器
const router = createRouter({// 路由模式hashhistory: createWebHistory(),routes: constantRoute,// 滚动行为scrollBehavior() {return {left: 0,top: 0}}
});
export default router;
  1. 新建routers.ts文件
export const constantRoute = [{// 首页path: '/',name: 'home',component: () => import('@/views/home/Home.vue'),meta: {title: '首页',}},{// 404path: '/404',component: () => import('@/views/404/index.vue'),name: '404',meta: {title: '404',}},{// 任意路由path: '/:pathMatch(.*)*',redirect: '/404',name: 'Any',meta: {title: '任意路由'}}
]
  1. 修改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')
  1. 修改App.vue文件
<template><div><router-view></router-view></div>
</template>
<script setup lang="ts">
</script>
<style scoped></style>

十一、添加api,封装请求(axios)

  1. 安装依赖pnpm install axios --save
  2. 新建api文件夹,utils文件夹,及创建request.ts文件
// 进行axios二次封装:使用请求与响应拦截器
import axios from "axios";
// 第一步:利用axios对象的create方法,去创建axios实例(其他的配置:基础路径、超时的时间)
const request = axios.create({// 基础路径baseURL: import.meta.env.VITE_APP_BASE_API,// 基础路径上会携带/apitimeout: 5000// 超时的时间的设置
});// 第二步:request实例添加请求与响应拦截器
request.interceptors.request.use((config) =>// config配置对象,headers属性请求头,经常给服务器端携带公共参数,例如token// 返回配置对象config
);// 第三步:响应拦截器
request.interceptors.response.use((response) =>// 成功回调// 简化数据response.data
, (error) => {// 失败回调:处理http网络错误的// 定义一个变量:存储网络错误信息let message = '';// http状态码const {status} = error.response;switch (status) {case 401:message = "TOKEN过期"break;case 403:message = "无权访问"break;case 404:message = "请求地址错误";break;case 500:message = "服务器出现问题"break;default:message = "网络出现问题";break;}return Promise.reject(message);
});
// 对外暴露
export default request;
  1. api文件夹创建testApi.ts文件,文件中引入request.ts
import request from "@/utils/request";// post接口请求方式
export const testPostApi = (data:any) => request.post('/api/postUrl',data)// get接口请求方式
export const testGetApi = (data:string) => request.post(`/api/getUrl?id=${data}`)
  1. 在页面中调用接口
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue"
import { testPostApi, testGetApi } from '../../api/testApi'const postApiData = () => {testPostApi({ username: 'admin', password: '123456' }).then(res => {console.log(res)})
}const getApiData = () => {testGetApi('SKU12345678').then(res => {console.log(res)})
}// 调用接口
onMounted(() => {postApiData()getApiData()
})
const count = ref(0)
const list = reactive(['你好', '你好世界'])
</script>

调用结果
在这里插入图片描述

在这里插入图片描述

十二、pinia状态管理器

  1. 安装依赖:pnpm install pinia --save
  2. 在src目录下新建文件夹store,在store文件下新建文件index.ts和modules文件夹
// store/index.ts
// 大仓库
import { createPinia } from 'pinia';
// 创建大仓库
const pinia = createPinia();
// 对外暴露:入口文件需要安装仓库
export default pinia;
  1. 在modules文件下新建test.ts文件
// store/modules/test.ts
// 小仓库
import { defineStore } from "pinia";// 选项式API写法
const useTestStore = defineStore('test', {state: () => ({count: 100,list: [1, 2, 3, 4, 5]}),actions: {updateCount() {this.count += 100}},getters: {total() {const num: any = this.list.reduce((prev, next) => prev + next, 0)return num}}
})
export default useTestStore
  1. main.ts内引入store
// 引入store
import store from './stores'
app.use(store)
  1. 再页面中使用
<template><div class=""><h1>欢迎使用项目模板</h1><div class="content"><p>store_count:{{ storeCount }}</p><button @click="count++">count:{{ count }}</button><div class="list"><ul><li v-for="item in list" :key="item">{{ item }}</li></ul></div></div></div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from "vue"
import useTestStore from '../../store/modules/test'
import { testPostApi, testGetApi } from '../../api/testApi'const storeCount = ref(0)
const userTestStoreData = useTestStore()
storeCount.value = userTestStoreData.countconst postApiData = () => {testPostApi({ username: 'admin', password: '123456' }).then(res => {console.log(res)})
}const getApiData = () => {testGetApi('SKU12345678').then(res => {console.log(res)})
}// 调用接口
onMounted(() => {postApiData()getApiData()
})
const count = ref(0)
const list = reactive(['你好', '你好世界'])
</script><style scoped lang="scss"></style>

项目搭建到这里就结束了,引入项目UI框架看需求引入再引入对应框架
文章参考:【vue3企业级项目骨架搭建,涉及vite、eslint、prettierrc、husky、commitlint、lint-staged、stylelint】

相关文章:

从零开始搭建企业级前端项目模板(vue3+vite+ts)

文章目录 主要内容一、vite脚手架工具初始化项目二、项目代码加入eslint校验和自动格式化2.1安装对应依赖插件2.2 配置script脚本&#xff0c;项目安装eslint配置2.3 安装完成后&#xff0c;后面启动项目还缺少一些依赖&#xff0c;提前按需安装好 三&#xff0c;修改eslintrc.…...

ElasticSearch的DSL查询语法解析

Elasticsearch提供了基于ISON的DSL (Domain Specific Lanquage)来定义查询。 目录 一、常见查询类型 二、DSLQuery基本语法 三、全文检索查询 3.1 match查询&#xff1a;会对用户输入内容分词&#xff0c;常用于搜索框搜索 &#xff0c;语法&#xff1a; 3.2 multi match…...

Linux 常用基础命令(2024年最新篇)新手小白必看 初识Linux

CSDN 成就一亿技术人&#xff01; 2024年 借助这篇文章 重新整理Linux 基础常用命令 CSDN 成就一亿技术人&#xff01; 上命令 一 &#xff0c;Linux语法格式 学习命令要掌握命令的格式 command [options] [arguments] 命令 选项 参数 二&#xff0c;Linux基础…...

Golang中for和for range语句的使用技巧、对比及常见的避坑

前言 基础语法不再赘述&#xff0c;写这个原因是之前的某次面试被问道了&#xff0c;我知道会导致问题但具体答下来不是很通顺。再回想自己开发过程中&#xff0c;很多地方都是使用到了for/for range&#xff0c;但是却从没注意过一些细节&#xff0c;因此专门学习一下进行记录…...

Nestjs 微服务实战 - 动态微服务创建链接

所有的微服务都需要做服务治理 服务治理包括&#xff08;配置中心、服务发现、注册服务等等&#xff09;&#xff0c;常见的包括 Java 的 Nacos&#xff0c;这里不关注与服务治理&#xff0c;只说明&#xff0c;如何用 nest 网关&#xff0c;并且在网关层动态实现微服务注入 …...

K8S部署pod状态CreateContainerConfigError问题解决

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…...

PyTorch 简单易懂的实现 CosineSimilarity 和 PairwiseDistance - 距离度量的操作

目录 torch.nn子模块Distance Functions解析 nn.CosineSimilarity 功能 主要参数 输入和输出的形状 使用示例 nn.PairwiseDistance 功能 主要参数 输入和输出的形状 使用示例 总结 torch.nn子模块​​​​​​​Distance Functions解析 nn.CosineSimilarity torc…...

app加载不到aar中的so库

如何将so文件打入到aar包中 1 在main下面新建jniLibs目录并将so放进去 2 在android{}中添加 sourceSets {main {jniLibs.srcDir file(jni/)}}app引用不到aar中的so文件(巨坑&#xff0c;不去查谁知道啊) 在aar 的manifeset application标签中中添加 android:extractNativeLi…...

vue-springboot基于java的实验室安全考试系统

本系统为用户而设计制作实验室安全考试系统&#xff0c;旨在实现实验室安全考试智能化、现代化管理。本实验室安全考试管理自动化系统的开发和研制的最终目的是将实验室安全考试的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的…...

mysql+关掉密码过期

mysql关掉密码过期 要在MySQL中关闭密码过期功能&#xff0c;可以按照以下步骤进行操作&#xff1a; 登录到MySQL服务器。 使用管理员账户&#xff08;如root&#xff09;连接到数据库。 mysql -uroot -ppassword 运行以下命令来查看当前的密码过期设置&#xff1a; SHOW…...

实际项目中的环形缓冲区

在实际项目中&#xff0c;环形缓冲区的设计要比之前讲到的原型稍微复杂一些&#xff0c;需要一些接口函数来实现数据结构封装。GitHub上有个大帅哥写了一个轻量的环形缓冲区库&#xff0c;可以学习参考&#xff0c;也可以直接集成到自己的项目中&#xff0c;功能已经非常完善。…...

输出回文数-第11届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第23讲。 输出回文数&#…...

内存溢出会导致模块测试正常,植入系统失败

前些天&#xff0c;遇到了一个问题&#xff1a;需要在系统中添加一个小功能&#xff0c;单独测试&#xff0c;然后植入系统。 代码使用了从网上下载的函数&#xff0c;模块单独运行&#xff0c;没有问题&#xff0c;但是放在系统中运行就会出问题。 不得已的情况下&#xff0c…...

【taro react】 ---- QRCode 二维码生成

1. 需求分析 需要将输入的值转换为图片资源;由于只是单纯的展示,所以不需要很多比如加 logo 等复杂功能;不需要后端生成,直接前端操作;使用的第三方库尽可能小,功能单一;最后选择使用 qrcode-generator 库,只有 40kb。2. 使用第三方库 qrcode-generator 3. 转换 base…...

rk3566 armbian修复usb2.0并挂载U盘

文章目录 usb接口修复一 执行命令二 修改rk3566-panther-x2.dts⽂件三 查看是否识别 U盘格式化、挂载一 U盘格式化1.1 查看U盘1.2 查看U盘文件系统类型1.3 格式化为ext4系统 二 挂载U盘2.1 手动挂载2.2 自动挂载&#xff08;可选&#xff09; usb接口修复 一 执行命令 将位于…...

猫头虎博主第9期赠书活动:《YOLO目标检测》计算机AI视觉实战YOLO人工智能目标检测与跟踪图像处理深度学习图像检测书籍

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通Golang》…...

python 如何将英语单词翻译成中文

要将英语单词翻译成中文&#xff0c;可以使用 Python 的第三方库 googletrans。该库使用 Google Translate 提供的 API 来进行翻译。 首先&#xff0c;需要安装 googletrans 库。可以使用以下命令在终端或命令提示符中安装&#xff1a; pip install googletrans4.0.0-rc1然后…...

Linux_CentOS_7.9_MySQL_5.7配置数据库服务开机自启动之简易记录

前言&#xff1a; 作为运维保障&#xff0c;都无法准确预估硬件宕机的突发阶段&#xff0c;其生产数据实时在产出&#xff0c;那作为dba数据库服务的其重要性、必要性就突显而出。这里拿虚拟机试验做个配置记录&#xff0c;便于大家学习参考。 # 如出现服务器重启后登入报错无…...

js实现拖动盒子查看内容 内容拖动

一.分析实现过程 1.鼠标拖动的操作是&#xff0c;按下鼠标不松&#xff0c;拖动鼠标&#xff0c;就需要监听鼠标点击事件(onmousedown),鼠标拖动事件(onmousemove) 2.鼠标拖动事件的监听时机&#xff0c;是在按下鼠标之后监听的&#xff0c;所以鼠标拖动事件需要放在鼠标按下事…...

[C#]winform利用seetaface6实现C#人脸检测活体检测口罩检测年龄预测性别判断眼睛状态检测

【官方框架地址】 https://github.com/ViewFaceCore/ViewFaceCore 【算法介绍】 SeetaFace6是由中国科技公司自主研发的一款人脸识别技术&#xff0c;它基于深度学习算法&#xff0c;能够快速、准确地识别出人脸&#xff0c;并且支持多种应用场景&#xff0c;如门禁系统、移动…...

c++ execl 执行 重定向

#include <unistd.h>int main() {pid_t childPid fork(); // 创建子进程if (childPid 0) {// 子进程// 关闭标准输入、输出和错误流close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);// 打开要写入的文件int fd open("output.txt", O_WRONLY…...

uni-app中实现元素拖动

uni-app中实现元素拖动 1、代码示例 <template><movable-area class"music-layout"><movable-view class"img-layout" :x"x" :y"y" direction"all"><img :src"musicDetail.bgUrl" :class&…...

Java系列-Class.forName和ClassLoader.loadClass的区别

Class.forName 和 ClassLoader.loadClass 是 Java 中两种加载类的方式&#xff0c;它们的主要区别在于加载类的时机和对异常的处理。 1.Class.forName Class.forName 是一个静态方法&#xff0c;用于在运行时加载类。它返回一个 Class 对象&#xff0c;但在加载类的过程中&am…...

找不到模块 “path“ 或其相对应的类型声明

src别名的配置 在开发项目的时候文件与文件关系可能很复杂&#xff0c;因此我们需要给src文件夹配置一个别名 // vite.config.ts import {defineConfig} from vite import vue from vitejs/plugin-vue import path from path export default defineConfig({plugins: [vue()],r…...

Linux第17步_安装SSH服务

secure shell protocol简称SSH。 目的&#xff1a;在进行数据传输之前&#xff0c;SSH先对联级数据包通过加密技术进行加密处理&#xff0c;然后再进行数据传输&#xff0c;确保数据传输安全。 1、在安装前&#xff0c;要检查虚拟机可以上网&#xff0c;否则可能会导致安装失…...

C语言—数据类型

变量和基本数据类型 变量类型的概念 变量是在程序中可以发生变化的量&#xff0c;变量是有类型的&#xff0c;变量的类型决定了变量存储空间的大小以及如何解释存储的位模式。 1字节&#xff08;Byte&#xff09;8位&#xff08;bit&#xff09; 定义格式 存储类型 数据…...

静态网页设计——多彩贵州(HTML+CSS+JavaScript)(dw、sublime Text、webstorm、HBuilder X)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 感谢大佬的视频&#xff1a;https://www.bilibili.com/video/BV1cK411v7R2/?vd_source5f425e0074a7f92921f53ab87712357b 源码&#xff1a;https://space.bilibili.com…...

unity PDFRender Curved UI3.3

【PDF】PDFRender 链接&#xff1a;https://pan.baidu.com/s/1wSlmfiWTAHZKqEESxuMH6Q 提取码&#xff1a;csdn 【曲面ui】 Curved UI3.3 链接&#xff1a;https://pan.baidu.com/s/1uNZySJTW0-pPwi2FTE6fgA 提取码&#xff1a;csdn...

基于深度学习的停车位关键点检测系统(代码+原理)

摘要&#xff1a; DMPR-PS是一种基于深度学习的停车位检测系统&#xff0c;旨在实时监测和识别停车场中的停车位。该系统利用图像处理和分析技术&#xff0c;通过摄像头获取停车场的实时图像&#xff0c;并自动检测停车位的位置和状态。本文详细介绍了DMPR-PS系统的算法原理、…...

C#,入门教程(09)——运算符的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(08)——基本数据类型及使用的基础知识https://blog.csdn.net/beijinghorn/article/details/123906998 一、算术运算符号 算术运算符号包括&#xff1a;四则运算 加 , 减-, 乘*, 除/与取模%。 // 加法&#xff0c;运算 int va 1 …...

php动态网站开发环境/流量主广告点击自助平台

小表驱动大表1、概念驱动表的概念是指多表关联查询时&#xff0c;第一个被处理的表&#xff0c;使用此表的记录去关联其他表。驱动表的确定很关键&#xff0c;会直接影响多表连接的关联顺序&#xff0c;也决定了后续关联时的查询性能。2、原则驱动表的选择遵循一个原则&#xf…...

网站后台添加图片链接/网络软文范例

8051单片机的定时/计数器 四、定时/计数器常数的计算 1&#xff0e;计数器初值的计算 设计数器的最大计数值为M(根据不同工作方式&#xff0c;M可以是213、216或28)&#xff0c;则计算初值X的公式如下&#xff1a; XM-要求的计数值 2&#xff0e;定时器初值的计算 在定时器模式…...

成都专业网站建设价格/排名首页服务热线

[极品笑话]太有才了&#xff0c;这是谁编的&#xff1f; 没钱的,养猪 有钱的&#xff0c;养狗。 没钱的,在家里吃野菜 有钱的,在酒店吃野菜。 没钱的,在马路上骑自行车 有钱的&#xff0c;在客厅里骑自行车。 没钱的想结婚&#xff0c; 有钱的想离婚 没钱的老婆兼秘书,…...

现在最好的企业网站管理系统/科技公司网站制作公司

公司要做一个项目的demo&#xff0c;要求地图上可以插红旗&#xff0c;所以就用到了Raphael。 因为是个demo&#xff0c;所以地图就用了一张图片&#xff0c;效果如下&#xff1a; 所以为了更好的封装一下这个功能&#xff0c;就写了一个简单的插件&#xff1a;jquery-pointpai…...

阿里企业网站托管/特色产品推广方案

playbook 剧本 yaml 字典 key&#xff1a;value 列表 [] - 后缀名&#xff1a;yaml、yml playbook 命令格式 Usage: ansible-playbook [options] playbook.yml [playbook2 ...]-C, --check # 检查但是不会真的执行-f FORKS, --forksFORKS # 并发&#xff0c;默认是5个 --list…...

自己做视频网站能赚钱/焊工培训ppt课件

定义快捷键的方法//在form_load的时候写上 //表示窗体接受按键事件 //然后在KeyDown事件中写入如下代码实现输入的是否是CtrlA的组合键&#xff1a; private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode Keys.A && e.Modifiers Keys.Co…...