最近用vue3做一个移动端的小项目,记录一下所用,主要用到了vue3+vite+axios+pinia+vant4+Ts+echarts+sass
首先创建基于vite的构建设置
在命令行运行
npm init vue@lates
创建你的项目,根据需要选择你要开启的功能,然后
cd
npm install
npm run dev
这时你的项目就启动起来了
安装vant
参照vant官网
1、安装vant > npm i vant
2、引入组件。在main.ts里
import { createApp } from 'vue';
import App from './App.vue'
// 1. 引入你需要的组件
import { Button, ..... } from 'vant';
// 2. 引入组件样式
import 'vant/lib/index.css';
const app = createApp(App)
// 3. 注册你需要的组件
app.use(Button)
app.use(xxx)
// 挂载
app.mount('#app')
3、就可以在组件中使用了
安装pinia及其数据持久化
在创建项目的时候已经选择了pinia,这里需要实现数据持久化。pinia状态存储再浏览器内存,同vuex一样,刷新页面的时候store里的数据会丢失,页面重新加载会初始化pinia。像我们用户的登录信息这些肯定需要记录,vuex是存储到浏览器本地,每次刷新的时候去浏览器localstore或是sessionstore里取,pinia我们使用插件来实现
1、npm i pinia-plugin-persistedstate 安装pinia-plugin-persistedstate插件
2、然后在main.ts里引入,传递给app实例
import piniaPluginPersistedstate from ‘pinia-plugin-persistedstate’
app.use(createPinia().use(piniaPluginPersistedstate))
3、然后在stores的单个store下开启数据持久化
import { ref } from 'vue'
import { defineStore } from 'pinia'
export const useTokenStore = defineStore('tokenkey', () => {
const token = ref('')
return { token }
}, {
persist: true // 开启数据持久化,存储在localStorage
})
// 也可以指定存储在sessionStorage
persist: {
key: 'a',
storage: sessionStorage
}
4、在组件内使用
import { useTokenStore } from ‘@/stores/token’;
const store = useTokenStore();
// store.token 就可以拿到了
在util/request.js下使用
import axios from 'axios';
import { useTokenStore } from '@/stores'; // 使用pinia状态
const store = useTokenStore();
const Axios = axios.create({
baseURL: '/api',
timeout: 3000
});
Axios.interceptors.request.use(req => {
// 请求拦截处理
req.headers.Authorization = "Bearer " + store.token // 这这这
return req;
}, err => {
return Promise.reject(err);
})
Axios.interceptors.response.use(res => {
// 响应拦截处理
if (res.data.errorCode === '401') {
store.$patch({ token: '' }) // 改变状态值
}
return res.data;
}, error => {
const err = error.toString();
//按照实际的响应包进行解析,通过关键字匹配的方式
switch (true) {
case err.indexOf('Network') !== -1:
console.log('后端服务器无响应或者URL错误', err);
break;
case err.indexOf('timeout') !== -1:
console.log('请求后端服务器超时!', err);
break;
}
return Promise.reject(error);
})
export default Axios;
5、在路由里使用(组件外)官方更详细
import { useTokenStore } from '@/stores/token';
router.beforeEach(async (to, from) => {
const store = useTokenStore(); // 在方法里边使用
if (store.token==='' && to.meta.requiresAuth) {
return {
path: '/login',
query: { redirect: to.fullPath },
}
}
})
6、注注注意意意: pinia 和vuex,通过解构的方式获取状态,会导致状态失去响应性,用storeToRefs函数
import useCounterStore from '@/store/count'
import { storeToRefs } from 'pinia'
const counterStore = useCounterStore()
const { count } = storeToRefs(counterStore)
vant4 Toast使用上的变化
因为vue3 setup里拿不到this对象,对于vue3和vant<4的版本可以采用getCurrentInstance
1、main.ts里通过app.config.globalProperties挂载
import { createApp } from 'vue'
import { Toast } from 'vant'
const app = createApp(App);
app.config.globalProperties.$toast = Toast;
const vm = app.mount('#app')
2、组件里使用
<script setup>
import {ref, getCurrentInstance} from "vue";
const {proxy} = getCurrentInstance()
// proxy?.$toast('你好啊');
</script>
但是vant4不是这样的
import {showToast, showSuccessToast, showFailToast } from ‘vant’
然后就可以直接使用了 showToast(你好’); showSuccessToast(‘成功’); showFailToast(‘失败’);
px转vw做分辨率适配
1、安装插件npm i -save-dev postcss-px-to-viewport-8-plugin
最开始装的postcss-px-to-viewport 预览的时候提示不支持,vite.config.ts引入的时候也提示未找到,但是浏览器看css又是转为xw了的,安全起见,换成postcss-px-to-viewport-8-plugin,就不报错了
2、vite.config.ts里配置
import postcssPxToViewport from 'postcss-px-to-viewport-8-plugin';
export default defineConfig({
...
resolve:{},
server: {},
css: {
postcss: {
postcsspxtoviewport({
unitToConvert: 'px', // 要转换的单位,默认为"px"
viewportWidth: 750, // I设计稿的宽度
unitPrecision: 6, // 转换后的精度,即小数点位数
propList: ['*', '!font-size'], // 能指定转换的css属性的单位,*代表全部css属性的单位都进行转换, !font-size 表示 font-size 后面的单位不会被转换
viewportUnit: 'vw', // 指定需要转换成的视窗单位,默认vw
fontViewportUnit: 'vw', // 指定字体需要转换成的视窗单位,默认vw
// 需要忽略的 CSS 选择器,不会转为视口单位,使用原有的px等单位。
selectorBlackList: ['ignore-'], // 指定不转换为视窗单位的类名
minPixelValue: 1, // 设置最小的转换数值,默认值1,小于或等于1px则不进行转换
mediaQuery: false, // 是否在媒体查询的css代码中也进行转换,默认false
replace: true, // 是否直接更换属性值,而不添加备用属性
// exclude: [/node_modules/], // 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
// include: [/src/], // 如果设置了include,那将只有匹配到的文件才会被转换
landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)
// landscapeUnit: 'vw', // 横屏时使用的单位
// landscapeWidth: 1338, // 横屏时使用的视口宽度
})
}
}
})
TS的一些报错修改
1、
类型“HTMLELement nul1”的参数不能赋给类型“HTMLELement”的参数。不能将类型“nul1”分配给类型“HTMLELement”。
myChart = document.getElementById(‘box’) => myChart = document.getElementById(‘box’)!
或者 myChart = document.getElementById(‘box’) as HTMLElement
2、
类型“any”的参数不能赋给类型“never"的参数
const list = ref([]); list.value.push(…res.data.list); => const list = ref([] as any[]);
3、
类型“stringLocationQueryValue[]”的参数不能赋给类型“RouteLocationRaw”的参数。不能将类型“LocationQueryValuer1”分配给类型“RouteLocationRaw”。
router.replace(route.query.redirect); => router.replace(route.query.redirect as any);
4、引入的.vue组件报找不到
ts不能识别.vue的文件
env.d.ts里增加
// env.d.ts
/// <reference types="vite/client" />
// 简单版本
// declare module '*.vue'
// 推荐使用
declare module '*.vue' {
// 引入vue模块中ts的方法
import type { DefineComponent } from 'vue'
// 定义vue组件以及类型注解
const component: DefineComponent<{}, {}, any>
export default component
}
就这样把,先记录下这些。anyscript大法【捂脸】希望6月可以改掉,拥抱ts。6月,你好!6.1快乐!