设计技术点
- vue3
- 不适用ts
- 配置vant3
- 移动端适配
创建vue3项目
vue create vue3-project
部分步骤说明
选择一种创建方式
- 默认 vue2版本
- 默认 vue3版本
- 手动配置 我们这里选第三种
选择项目所需要的特征属性
- 选择vue版本
- babel用于处理兼容
- 这里不使用ts
- PWA(Progressive Web App) 相关链接
- 十分不建议勾选Linter/Formatter,这里的eslint十分不友好,后续需要可手动增加
添加vant3.0样式
# Vue 3 项目,安装 Vant 3:
npm i vant@next -S
移动端rem适配
Vant 官方也为我们提供了方案 Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具: postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem lib-flexible 用于设置 rem 基准值
postcss配置
项目根目录新建postcss.config.js
module.exports = {
"plugins": {
"autoprefixer": {
// 配置使用 autoprefixer
overrideBrowserslist: ["last 15 versions"],
browsers: ["Android >= 4.0", "iOS >= 7"]
},
"postcss-pxtorem": {
rootValue: 100, // Vant 官方根字体大小是 37.5
propList: ['*'],
selectorBlackList: ['.norem'] // 过滤掉.norem-开头的class,不进行rem转换
}
}
}
注意:rootValue设置为100是为了方便将ui图中尺寸进行换算,这里1rem=100px
src文件夹下新建utils文件夹 utils文件夹下新加rem.js
// rem等比适配配置文件
// 基准大小
const baseSize = 100
// 注意此值要与 postcss.config.js 文件中的 rootValue保持一致
// 设置 rem 函数
function setRem() {
// 当前页面宽度相对于 375宽的缩放比例,可根据自己需要修改,一般设计稿都是宽750(图方便可以拿到设计图后改过来)。
const scale = document.documentElement.clientWidth / 375
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
console.log("我执行了")
setRem()
}
main.js中使用rem.js
import './utils/rem'
注意rem.js中基准大小要与postcss.config.js中设置的rootValue值相同,rem.js主要用于等比适配配置文件
axio二次封装
utils中新建http.js
// src/utils/http.js
import axios from 'axios';
const getBaseUrl = (env) => {
let base = {
production: '/',
development: 'https://www.baidu.com',
test: 'http://localhost:3001',
}[env];
if (!base) {
base = '/';
}
return base;
};
class NewAxios {
constructor() {
this.baseURL = getBaseUrl(process.env.NODE_ENV);
this.timeout = 10000;
this.withCredentials = true;
}
setInterceptors = (instance, url) => {
instance.interceptors.request.use((config) => {
// 在这里添加loading
// 配置token
config.headers.AuthorizationToken = localStorage.getItem('AuthorizationToken') || '';
return config;
}, err => Promise.reject(err));
instance.interceptors.response.use((response) => {
// 在这里移除loading
// todo: 想根据业务需要,对响应结果预先处理的,都放在这里
return response;
}, (err) => {
if (err.response) { // 响应错误码处理
switch (err.response.status) {
case '403':
// todo: handler server forbidden error
break;
// todo: handler other status code
default:
break;
}
return Promise.reject(err.response);
}
if (!window.navigator.online) { // 断网处理
// todo: jump to offline page
return -1;
}
return Promise.reject(err);
});
}
request(options) {
// 每次请求都会创建新的axios实例。
const instance = axios.create();
const config = { // 将用户传过来的参数与公共配置合并。
...options,
baseURL: this.baseURL,
timeout: this.timeout,
withCredentials: this.withCredentials,
};
// 配置拦截器,支持根据不同url配置不同的拦截器。
this.setInterceptors(instance, options.url);
return instance(config); // 返回axios实例的执行结果
}
}
export default new NewAxios();
src文件夹下新建api,api下 1:index.js 2:home.js
//index.js
export * from './home';
//home.js
import axios from '@/utils/http';
export const fetchData = data => axios.request({
method:'get',
url: '/123/data',
params:data
});
export default {};
注意:这种封装方式每次请求都会新建一个实例,过多实例是否会影响包体积或其他问题等这里有待讨论
这里用class的封装方式原因参考如下: 给这个类创建实例上的方法request 在 request 方法里,创建新的axios实例,接收请求配置参数,处理参数,添加配置,返回axios实例的请求结果(一个promise对象)。 你也可以不创建,直接使用默认导出的axios实例,然后把所有配置都放到它上面,不过这样一来整个项目就会共用一个axios实例。虽然大部分项目下这样够用没问题,但是有的项目中不同服务地址的请求和响应结构可能完全不同,这个时候共用一个实例就没办法支持了。所以为了封装可以更通用,更具灵活性,我会使用axios的create方法,使每次发请求都是新的axios实例。