封装类
# 封装类
# axios封装
导入axios函数
import axios,{AxiosResponse // 请求返回值类型 ,AxiosPromise ,AxiosInstance //axios实例类型 ,AxiosRequestConfig, //请求配置参数类型 AxiosRequestHeaders, // 请求头参数 } from 'axios'
创建axios实例
const axiosInstance:AxiosInstance = axios.create({ baseURL:"" // 默认地址 timeout:3000 // 超时默认值 }) // 请求拦截器 axiosInstace.interceptors.request.use((config:AxiosRequestConfig)=>{ const userId ='1' // 获取用户id,并携带 const headers:AxiosRequestHeaders={ userId } headers['distributorId'] = '1' return ...config,headers }) //请求拦截器 axiosInstace.interceptors.response.use((response:AxiosResponse)=>{ // 请求成功走这里 const powerStore = useStore().power if(data.code == '0') //当为0的时候代表正确 powerStore.changePower(true) //存储到vuex中 return data ) if(data.code == 'distribution.memberNotInDistributor' ){ reoter.push({name:"nolog"}) // 没有权限 return Promise.reject( response) // 返回一个错误 // 没有权限 } if(data.code === 'distribution.member_not_permission'){ return Promise.reject(data) } // 无效的UAT if(data.code == 'idServer.1020'){ return Promise.reject(data) } //返回错误信息 const errMessage = data.message message.error(errMessage) retrun Promise.reject(response) },(err)=>{ // 请求失败走这里 if(error.response){ const { data,status } = error.response const message = !data ? '网络连接异常,请稍后再试' : showMessage(status) if(status===401){ window.location.href ='地址’ //不知道什么地址 return } router.push({name:”error‘,params:{status,message}}) return Promise.reject(data) } }} }) //导出 封装工具 export default function request<T>(url='',params={},type='Post',query?:{}):Promise<requestReturnType<T>{ let promise:AxiosPromise return new Promise<requestReturnType<T>>(resolve,reject)=>{ //返回一个promise对象 if(type.toUpperCase == 'GET'){ promise = axiosInstance({ method: 'GET', url, params }) } else if (type.toUpperCase() === 'POST') { promise = axiosInstance({ method: 'POST', url, data: params, params: query }) } else if (type.toUpperCase() === 'DELETE') { promise = axiosInstance.delete(url, params) } else if (type.toUpperCase() === 'PUT') { promise = axiosInstance.put(url, params) } else { promise = axiosInstance({}) } promise.then((res)=>{ resolve(res as unknown as requestReturnType<T>) }).catch((error)=>{reject(error)}) } } } }
# svg封装
<template> <svg aria-hidden="true" //aria-hidden 为了避免现在的辅助技术能够识别并朗读 :style="{width:size+`${rem ? 'rem':'px'}`}" <use :href='symboid' :fill="color"> </svg> </template> <script lang="ts"> export default defineComponent({ name:"SvgIcon", props:{ profix:{ type:String, default:'icon', }, name:{ type:String, required:true, }, color:{ typr:sTRING }, size:{ type:Nuber, default:'36' rem:{ type:Boolean, default:"10" } } setup(props){ const symboiId=computed(()=>`#${props.prefix}-${props.name}` ) return { symbolIds} } } })
# 按钮封装
<template> <a-button v-bind='attrs' :disable="disable"> <tempalte v-if="props.hsaIcop"> <a-space align="center" :size="4"> {{props.text}} <span class="app-button-icon-wrap"> <SvgIcon :name="props.iconDir!" style="font-size:16px"></SvgIcon> </span> <a-space> </template> <template v-else> {{props.text}} </template> </template> <script setup lang="ts"> const attrs=useAttrs() //穿透,继承父元素的类和属性 const props = withDefaults( withDefaults // 是给defineProps 绑定默认值 defineProps<{ text:string, iconDir?:string, hasIcon?:boolean, disabled?:boolean}>(),{ iconDir:"", hasIcon:false } ) </script>
# 封装弹除层
<template> <a-modal :mask-closable = 'false' v-bind="attrs" warpClassName="app-confirm-modal-warp" :okButtonProps="okBittonProps" centered> <template #title> <span> <i> <SvgIcon v-if="props.type === 'DISABLE'" name="components-warning</SvgIcon> <SvgIcon v-if="props.type === 'DISABLE'" name="components-warning"></SvgIcon> <SvgIcon v-if="props.type === 'DISABLE'" name="components-warning"></SvgIcon> </i> {{props.titleText}} <template #footer v-if="hide"> <a-button @click="handleCancel" type="primary">我知道了</a-button> </template> </tempalte> <script> const props = defineProps<{titleText:string type:"ENABLE" | "DIS" | 'PRO' hide?:boolean}>() const attrs = useAttrs() const okButtonProps = computed(()=>(props.type === 'DISABLE' ? {danger:true}:{})) const emit = defineEmits(['handleCancel']) const handleCancel = () =>{ emit('handleCancel') } </script>
mask-closable // 点击遮罩层不关闭 attrs //穿透。 warpClassName //对话框外层容器的类名 okButtonProps //ok按钮Props centered //中心位置
# 封装筛选按钮
<template> <div> <a-form ref="formRef" name='table_advanced_search' :model=formState> <a-row :gutter="24"> <tempalte v-if="useFlex"> <template v-for="item in filterOptions" :key="item.field"> <a-col :flex="item.flex"> <a-form-item v-if="formState[`${item.field}`] !== undefined" :name="`${ item.field}`" :label="`${irem,type !=='INPUT-GRPOUP' ? item,label :''}`" :required = "item.required"> <tempalate v-if=”item.type === 'STRING'“> <a-input v-model:vlaue="formState[`${item.fiweld}`] :palceholder ="item.placeholder"> </a-input> </tempalate> <template v-if="item.type === 'SELECT'"> <a-select v-model:value="formState[`${item.field}`]" @change="onChange($event,item.field)" :mode="item.options?.multiple ? 'multiple':undefuned" > </a-select> </tempalte> </a-form-item> </a-col> </tempalte> </a-row> </a-form> </div> </template>
# 取别名@
先在vite.config.js中配置
resolve: {
alias: [
{
find: '@',
replacement: pathResolve('src') + '/'
},
{
find: 'components',
replacement: pathResolve('src/components') + '/'
},
{
find: 'utils',
replacement: pathResolve('src/utils') + '/'
},
{
find: 'store',
replacement: pathResolve('src/store') + '/'
},
{
find: /\/types\//,
replacement: pathResolve('types') + '/'
}
]
},
如何配置了ts 需要在tsconfig.json中配置
"baseUrl": "./",
"paths": {
"@/*": ["src/*"],
"components/*": ["src/components/*"],
"utils/*": ["src/utils/*"],
"store/*": ["src/store/*"],
"/types/*": ["types/*"],
}
# 自动导入vue3的API
下载
npm i -D unplugin-auto-import
在vite-config中使用
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
// import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
// https://vitejs.dev/config/
在plugins中中使用
plugins: [
vue(),
AutoImport({
include: [
/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
/\.vue$/,
/\.vue\?vue/, // .vue
],
imports: ["vue", "vue-router", "pinia"],
eslintrc: {
enabled: false,
filepath: "./.eslintrc-auto-import.json",
globalsPropValue: true,
},
dirs: ["./src/store"],
vueTemplate: true,
dts: "src/types/auto-import.d.ts",
}),
Components({
resolvers: [AntDesignVueResolver({ importStyle: false })],
dts: "src/types/components.d.ts",
}),
// 自动导入图标
// createSvgIconsPlugin({
// iconDirs: [resolve(process.cwd(), "src/assets/icons")],
// symbolId: "icon-[dir]-[name]",
// }),
],
ts文件需要创建一个/auto-import.d.ts
这可能自动导入,看项目
如何在vite中使用到响应式布局
使用到插件
在vite中使用postcss和autoprefixer
npm i postcss autoprefixer postcss-pxtorem -D
----
在vite.config.js 配置
// 自动根据px转换成rem
css: {
postcss: {
plugins: [
autoprefixer({
overrideBrowserslist: ["Android>=4.0", "iOS>=7"], //大于android或ios
}),
pxtorem({
rootValue: 16,
propList: ["*"],
selectorBlackList: [":root"],
}),
],
},
},
---
自动配置根节点的fontsize
创建一个工具函数
const basesize =14
function setSize(){
let scale=1
if(document.documentElement.clientWidth < 1325 ){
sclae= document.documentElement.clientWidth / 1325
if(document.docuemntElement.clientWidth<1097){
scale = 1097 / 1325
}
}
document.documentElement.style.fontSize= baseSize *Math.min(scale,1)+'px'
}
setRem()
window.onresize = useDebounceFn(()=>{
setRem()
},150)
export{}
--在全局使用type类型
在src目录下新建一个types目录
types新建home.d.ts文件
--homde.d.ts-- //
export interface IPreps{
value:'1',
lable:'1
}
--index.ts ---
export * from './home' // 导出所有类中home的
--调用---
import type { IProps } from ‘@。。/。/。’
---defineProps---
deineProps<Iprops>()
定义搜索框组件
KeyboardEvent:是ts内置的鼠标键盘事件
函数定义接口
interface IEmits interface IEmits {
(e: "search", v?: string | number): void; //e是事件,v是参数,void是返回值
(e: "cancel"): void;
(e: "clear"): void;
(e: "update:modelValue", v?: string | number): void;
}
emit使用update
父组件
由于vue3废弃掉了.sync,所有在调用时需要通过 v-model:drawerShow绑定
子组件
const emit = defineEmits(['update:drawerShow'])
如何触发点击事件e
获取目标元素的类
e.target.classList
判断该类中是否包含这个类名
e.target.classList.contains(')