项目集成 与封装

1.element-plus

硅谷甄选运营平台,UI组件库采用的element-plus,因此需要集成element-plus插件!!!

官网地址:https://element-plus.gitee.io/zh-CN/

由于是后台管理系统 所以我们全部引入

pnpm install element-plus
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'const vm =  createApp(App)vm.use(ElementPlus)vm.mount('#app')

2.element 图标引入

pnpm install @element-plus/icons-vue

全局引入 

// main.ts// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}

也可以按需引入

Icon 图标 | Element Plus (element-plus.org)

 3.src文件夹别名配置

tsconfig.app.json

{"compilerOptions": {"target": "ES2020","useDefineForClassFields": true,"module": "ESNext","lib": ["ES2020", "DOM", "DOM.Iterable"],"skipLibCheck": true,/* Bundler mode */"moduleResolution": "bundler","allowImportingTsExtensions": true,"isolatedModules": true,"moduleDetection": "force","noEmit": true,"jsx": "preserve",/* Linting */"strict": true,"noUnusedLocals": true,"noUnusedParameters": true,"noFallthroughCasesInSwitch": true,"baseUrl": ".","paths": {"@/*": ["./src/*"]}},// include也需要配置以下:"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],"exclude": ["node_modules"]
}

vite.config.ts

import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),VueSetupExtend()],resolve: {alias: {"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src}
}
})

4.环境变量的配置

 

.env.development

# 开发环境配置文件
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '硅谷甄选运营平台'
VITE_APP_BASE_API = '/dev-api'VITE_SERVE="http://xxx.com"

 .env.production

NODE_ENV = 'production'
VITE_APP_TITLE = '硅谷甄选运营平台'
VITE_APP_BASE_API = '/prod-api'
VITE_SERVE="http://yyy.com"

.env.test

NODE_ENV = 'test'
VITE_APP_TITLE = '硅谷甄选运营平台'
VITE_APP_BASE_API = '/test-api'
VITE_SERVE="http://zzz.com"

配置运行命令 

package.json

 "scripts": {"dev": "vite --open","build:test": "vue-tsc && vite build --mode test","build:pro": "vue-tsc && vite build --mode production","preview": "vite preview"},

获取环境变量

console.log(import.meta.env);

5.SVG图标

pnpm install vite-plugin-svg-icons -D

 vite.config.ts中配置插件

import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// https://vitejs.dev/config/
export default defineConfig({plugins: [vue(),VueSetupExtend(),createSvgIconsPlugin({// Specify the icon folder to be cachediconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],// Specify symbolId formatsymbolId: 'icon-[dir]-[name]',})],resolve: {alias: {"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src}
}
})

入口文件导入

import 'virtual:svg-icons-register'

去阿里矢量图库

iconfont-阿里巴巴矢量图标库

 粘贴进去

在组件中使用 

<template><div><!-- 测试SVG图标的使用 --><!-- svg:图标外层容器节点,内部需要与use标签结合使用 --><svg  ><!-- xlink:href 执行用哪一个图标,属性值务必 #icon-文件名字 不加后缀 --><use xlink:href="#icon-phone" fill="red" width="30px" height="30px"></use></svg></div></template><script setup lang="ts" name="App"></script><style lang="css" scoped></style>

1.封装成全局组件

element-plusPlugins.ts

//element组件插件
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'//证明有效的在这里引入
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
export default {install(app) {/*** ElementPlus 国际化的配置*/app.use(ElementPlus, {locale: zhCn,})/*** 全局引入 element-icon*/for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)}}}

globalComponentsPlugins.ts

//对外暴露插件对象
import SvgIcon from "@/components/svgIcon/SvgIcon.vue";
// svg插件需要配置的代码
import 'virtual:svg-icons-register'const globalComponents = {SvgIcon}export default {//插件对象中install(app){for (const [key, component] of Object.entries(globalComponents)) {app.component(key, component)}}}

SvgIcon 组件

<template><!-- 测试SVG图标的使用 --><!-- svg:图标外层容器节点,内部需要与use标签结合使用 --><svg:width="width":height="height"><!-- xlink:href 执行用哪一个图标,属性值务必 #icon-文件名字 不加后缀 --><use:xlink:href="prefix + iconName":fill="color"></use></svg>
</template><script setup lang="ts" name="SvgIcon">
withDefaults(defineProps<{iconName: stringprefix?: stringcolor?: stringwidth?: stringheight?: string}>(),{prefix: '#icon-',color: 'red',width: '16px',height: '16px',},
)
</script><style lang="css" scoped>
</style>

main.ts

import { createApp } from 'vue'
import App from '@/App.vue'//引入自定义插件
import globalComponentsPlugins from './components/globalComponentsPlugins'
import elementPlugins from './components/elementPlugins'const app = createApp(App)app.use(globalComponentsPlugins)
app.use(elementPlugins)app.mount('#app')

6.集成sass

stylelint为css的lint工具。可格式化css代码,检查css语法错误与不合理的写法,指定css书写顺序等。

我们的项目中使用scss作为预处理器,安装以下依赖:  

pnpm add sass sass-loader stylelint postcss postcss-scss postcss-html stylelint-config-prettier stylelint-config-recess-order stylelint-config-recommended-scss stylelint-config-standard stylelint-config-standard-vue stylelint-scss stylelint-order stylelint-config-standard-scss -D
.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默认样式的时候能使用到},],},
}
.stylelintignore忽略文件
/node_modules/*
/dist/*
/html/*
/public/*
运行脚本
"scripts": {"lint:style": "stylelint src/**/*.{css,scss,vue} --cache --fix"
}
最后配置统一的prettier来格式化我们的js和css,html代码  
 "scripts": {"dev": "vite --open","build": "vue-tsc && vite build","preview": "vite preview","lint": "eslint src","fix": "eslint src --fix","format": "prettier --write \"./**/*.{html,vue,ts,js,json,md}\"","lint:eslint": "eslint src/**/*.{ts,vue} --cache --fix","lint:style": "stylelint src/**/*.{css,scss,vue} --cache --fix"},
测试sass语法
<template><div><h1>测试代码</h1></div>
</template><script setup lang="ts" name="App">
</script><style lang="scss" scoped>
div {h1 {color: red;}
}
</style>

7.清除默认样式

reset.scss

 *,*:after,*:before {box-sizing: border-box;outline: none;}html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {font: inherit;font-size: 100%;margin: 0;padding: 0;vertical-align: baseline;border: 0;}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {display: block;}body {line-height: 1;}ol,ul {list-style: none;}blockquote,q {quotes: none;&:before,&:after {content: '';content: none;}}sub,sup {font-size: 75%;line-height: 0;position: relative;vertical-align: baseline;}sup {top: -.5em;}sub {bottom: -.25em;}table {border-spacing: 0;border-collapse: collapse;}input,textarea,button {font-family: inhert;font-size: inherit;color: inherit;}select {text-indent: .01px;text-overflow: '';border: 0;border-radius: 0;-webkit-appearance: none;-moz-appearance: none;}select::-ms-expand {display: none;}code,pre {font-family: monospace, monospace;font-size: 1em;}

index.scss

//引入清除默认样式
@import url(./reset.scss);

main.ts

import { createApp } from 'vue'
import App from '@/App.vue'
import '@/styles/index.scss'//引入自定义插件
import globalComponentsPlugins from './components/globalComponentsPlugins'
import elementPlugins from './components/elementPlugins'const app = createApp(App)app.use(globalComponentsPlugins)
app.use(elementPlugins)app.mount('#app')

h1样式被消除了

8.为sass配置全局变量

但是你会发现在src/styles/index.scss全局样式文件中没有办法使用$变量.因此需要给项目中引入全局变量$.

在style/variable.scss创建一个variable.scss文件!

在vite.config.ts文件配置如下:

export default defineConfig((config) => {css: {preprocessorOptions: {scss: {javascriptEnabled: true,additionalData: '@import "./src/styles/variable.scss";',},},},
}

variable.scss

//给项目提供scss全局变量
$color:red;

9.axios二次封装

先安装axios

pnpm i axios

封装 request.ts

/* eslint-disable @typescript-eslint/no-explicit-any */
//进行axios 二次封装import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import { ElMessage } from "element-plus";
import { R } from "@/type/GlobalType";//第一步:利用axios对象的create方法,去创建一个axios实例(其他的配置:基础路径,超时的时间)const request = axios.create({//基础路径baseURL: import.meta.env.VITE_APP_BASE_API,//基础路径尚会携带/apitimeout: 30000 //超时的时间的设置})//第二部 :request实例添加请求与响应拦截器
request.interceptors.request.use((config) => {//config配置对象,headers属性请求头,经常给服务器端携带公共参数// config.headers.token = '123'// console.log(config);// config.url += "?token=123"// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'return config;//返回配置对象,执行链
})//第三步:响应拦截器
request.interceptors.response.use((response) => {//成功的回调//简化数据return response.data;
}, (error) => {//失败的回调:处理http网络错误//定义一个变量:存储网络错误的信息let message = '';//http状态码console.log(error);const status = error.statusif (!status) {message = '网络路径错误'ElMessage({type: 'error',message})//需要返回终结这个对象 return Promise.reject(error);}message = error.response.data.messageElMessage({type: 'error',message})//需要返回终结这个对象 return Promise.reject(error);
})
export type Query = {[key: string]: string | number | boolean
}export type Header = {[key: string]: string
}
/*** T 响应的类型 解体*/
class HttpHandler<T> {private requestProxy: AxiosInstance = request;private config: AxiosRequestConfig<any> = {};get(url: string): this {this.config.method = 'get';this.config.url = url;return this;}post(url: string): this {this.config.method = 'post';this.config.url = url;return this;}put(url: string): this {this.config.method = 'put';this.config.url = url;return this;}delete(url: string): this {this.config.method = 'delete';this.config.url = url;return this;}query(params: Query): this {/*** 给它赋值*/if (!this.config.params) {this.config.params = params} else {Object.assign(this.config.params, params)}return this;}header(header: Header): this {for (const [key, value] of Object.entries(header)) {header[key] = encodeURIComponent(value)}/*** 给它赋值*/if (!this.config.headers) {this.config.headers = header} else {const headers: any = this.config.headersObject.assign(headers, header)}return this}data(obj: any): this {/*** 给它赋值*/if (!this.config.data) {this.config.data = obj} else {const d: any = this.config.dataObject.assign(d, obj)}return this;}excute(): Promise<R<T>> {return this.requestProxy(this.config)}}export default function $http<T>(): HttpHandler<T> {return new HttpHandler<T>()
}
function getData() {$http().post(`/user/getUserInfo/你好`).query({page:1,size:10,type:'你好啊'}).header({token:'123',gou:'213'}).excute().then((res) => {userList.value = res.data}).catch(err => {console.log(err)})}

10.API接口统一管理

type

import { Query } from "@/utils/request";export interface LoginVo {userId: number,userName: string,token: string
}
export interface LoginForm extends Query {login: string;pwd: string;
}export interface User {id: number;userName: string;login: string;pwd: string;createTime: string;updateTime: string;createUserId: string;updateUserId: string;
}

 index.ts

/* eslint-disable @typescript-eslint/no-explicit-any */
//统一管理咱们项目用户相关的接口
import $http from "@/utils/request";
import { LoginForm, LoginVo, User } from "./type";
import {AxiosResponse} from "axios";
import { R } from "@/type/GlobalType";
//统一管理接口
const userPrefix = "/user"
enum API {LOGIN_URL = userPrefix + "/login",USER_INFO_URL = userPrefix + "/getUserInfo",}
/*** 获取用户信息* @returns user*/
export function getUserInfo():Promise<AxiosResponse<User[]>> {return $http().get(API.USER_INFO_URL).excute()
}/*** 登录接口*/
export function login(data:LoginForm):Promise<AxiosResponse<R<LoginVo>>> {return $http().post(API.LOGIN_URL).query(data).excute()
}
<template><div></div>
</template><script setup lang="ts" name="App">
import { onMounted } from 'vue';
import { login } from './api/user';onMounted(()=>{login({login:'admin',pwd:'admin'}).then(res=>{console.log(res);})})</script><style lang="scss" scoped></style>

import { onMounted } from 'vue'
import { getUserInfo } from './api/user'onMounted(() => {getUserInfo().then((res) => {console.log(res.data[0].updateTime)})
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1542121.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Spring:项目中的统一异常处理和自定义异常

介绍异常的处理方式。在项目中&#xff0c;都会进行自定义异常&#xff0c;并且都是需要配合统一结果返回进行使用。 1.背景引入 &#xff08;1&#xff09;背景介绍 为什么要处理异常&#xff1f;如果不处理项目中的异常信息&#xff0c;前端访问我们后端就是显示访问失败的…

Trace纳米侦查无人机技术详解

纳米无人机&#xff0c;作为微型无人机的一种&#xff0c;通常指尺寸和重量都非常小的无人机&#xff0c;其重量一般不超过几百克&#xff0c;甚至更小。这类无人机由于体积小、重量轻&#xff0c;具备高度的隐蔽性和灵活性&#xff0c;在军事侦察、环境监测、搜救行动等领域具…

Linux文件IO(八)-文件共享

什么是文件共享&#xff1f;所谓文件共享指的是同一个文件&#xff08;譬如磁盘上的同一个文件&#xff0c;对应同一个 inode&#xff09;被多个独立的读写体同时进行 IO 操作。多个独立的读写体大家可以将其简单地理解为对应于同一个文件的多个不同的文件描述符&#xff0c;譬…

【吊打面试官系列-MySQL面试题】MySQL_fetch_array 和 MySQL_fetch_object 的区别是什么?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL_fetch_array 和 MySQL_fetch_object 的区别是什么&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MySQL_fetch_array 和 MySQL_fetch_object 的区别是什么&#xff1f; 以下是 MySQL_fetch_array 和 MySQL_fe…

主语部分、谓语部分、限定动词 (谓语动词) 和非限定动词 (非谓语动词)

主语部分、谓语部分、限定动词 {谓语动词} 和非限定动词 {非谓语动词} 1. 主语部分 (subject)1.1. Forms of the subject 2. 谓语部分 (predicate)2.1. Cambridge Dictionary2.2. Longman Dictionary of Contemporary English2.3. 谓语部分和谓语动词2.4. Traditional grammar …

广度优先搜索算法及其matlab程序详解

#################本文为学习《图论算法及其MATLAB实现》的学习笔记################# 算法用途 广度优先搜索算法的应用 算法思想 广度优先搜索算法的步骤: ①,标号,令。 ②当所有标号为 的、与顶点 相关联的边的端点都已标号时,则停止;否则,把与 相关联的边的未标号的…

上位机图像处理和嵌入式模块部署(linux小系统开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 和若干年前相比较&#xff0c;现在嵌入式linux开发要简单得多。稍微贵一点的有树莓派&#xff0c;国产的有各种水果派&#xff0c;基本上都可以按照…

LeetCode 面试经典150题 190.颠倒二进制位

复习知识&#xff1a;正数的原码、反码、补码相同&#xff0c;负数的反码在其原码的基础上, 符号位不变&#xff0c;其余各个位取反&#xff0c;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后1 (即在反码的基础上1)。 题目&#xff1a;颠倒给定的 32 位无符号…

【SQLite数据库常规使用命令】

之前在做围绕数据库相关的一些小工具的时候&#xff0c;想找一款数据库作为小工具的资料库。需求是&#xff1a;不用复杂的安装&#xff0c;支持简单SQL&#xff0c;空间占用小&#xff0c;操作简单等等。 结合着之前接触到的一些研发同事做的产品的使用经验&#xff0c;我想到…

华为HarmonyOS地图服务 3 - 如何开启和展示“我的位置”?

一. 场景介绍 本章节将向您介绍如何开启和展示“我的位置”功能&#xff0c;“我的位置”指的是进入地图后点击“我的位置”显示当前位置点的功能。效果如下&#xff1a; 二. 接口说明 “我的位置”功能主要由MapComponentController的方法实现&#xff0c;更多接口及使用方法…

基于LSTM的温度时序预测

1.背景 本文接【时序预测SARIMAX模型】 一文&#xff0c;采用LSTM模型进行平均温度数据预测。具体的背景和数据分析就不做重复说明&#xff0c;感兴趣可以去看上文即可。 2.LSTM模型 RNN&#xff08;Recurrent Neural Network&#xff0c;循环神经网络&#xff09;是一种特殊…

【ARM】armv8的虚拟化深度解读

Type-1 hypervisor Type-1虚拟化也叫做Bare metal, standalone, Type1 Type2 hypervisor Type-2虚拟化也叫做hosted, Type-2 VM和vCPU(虚拟机和虚拟cpu) 在一个VM&#xff08;虚拟机&#xff09;中有多个vCPU&#xff0c;多个vCPU可能属于同一个Vritual Processor。 EL2…

java-----异常

目录 异常&#xff1a;代表程序出现的问题 运行时异常和编译时异常的区别&#xff1f; 异常的作用&#xff1a; 异常的处理方式: 异常中常见的方法: 抛出异常: 自定义异常: 异常&#xff1a;代表程序出现的问题 Exception:叫做异常&#xff0c;代表程序可能出现的问题。…

【alluxio编译报错】Some files do not have the expected license header

Some files do not have the expected license header 快捷导航 在开始解决问题之前&#xff0c;大家可以通过下面的导航快速找到相关资源啦&#xff01;&#x1f4a1;&#x1f447; 快捷导航链接地址备注相关文档-ambaribigtop自定义组件集成https://blog.csdn.net/TTBIGDA…

【JavaScript】LeetCode:46-50

文章目录 46 翻转二叉树47 对称二叉树48 二叉树的直径49 二叉树的层序遍历50 将有序数组转换为二叉搜索树 46 翻转二叉树 递归前序遍历 / 后序遍历&#xff0c;这里给出前序遍历的代码。遍历节点&#xff0c;交换左右子树。 /*** Definition for a binary tree node.* functio…

vue3快速入门(看心情更新)

vue3初始化工程目录 编写一个App .vscode下的extensions.json 配置插件的地方 public 页签图标 src 你的.vue文件都是在这个目录下的 .gitgnore 忽略文件 env.d.ts 让Ts去识别一些文件 index.html 入口文件 vite.config.ts 整个工程的配置文件 .vue文件中可以写的内容 template…

Windows安装Oracle11gR2(图文教程)

本章教程&#xff0c;记录在Windows10上安装Oracle11gR2过程。 一、下载安装包 通过网盘分享的文件&#xff1a;oracle11g 链接: https://pan.baidu.com/s/15ilciQ5NlKWtClklmdAH_w?pwds4dd 提取码: s4dd 二、下载并解压文件 将网盘中的安装包文件下载到本地&#xff0c;在此之…

心觉:感恩何其重要,感恩之心如何培养

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作177/1000天 上篇文章我们讲了保持感恩之心&#xff0c;可以吸引更多的机会和财富 但是现实中很多人是缺乏感恩之心 这是由于他们…

c++day3 手动封装一个顺序表(SeqList),分文件编译实现

要求: 有私有成员&#xff1a;顺序表数组的起始地址 ptr、 顺序表的总长度&#xff1a;size、顺序表的实际长度&#xff1a;len 成员函数&#xff1a;初始化 init(int n) 判空&#xff1a;empty 判满&#xff1a;full 尾插&#xff1a;push_back 插入&#xff1a;insert&…

进程间的通信4 共享内存

共享内存 1.共享内存简介 共享内存是将分配的物理空间直接映射到进程的用户虚拟地址空间中&#xff0c;减少数据在内核空间缓存共享内存是一种效率较高的进程间通讯的方式在 Linux 系统中通过 ipcs -m 查看所有的共享内存 共享内存模型图 2.共享内存的创建 1.函数头文件 #…