1、确定node版本
1、下载nvm安装包
官方下载地址:https://github.com/coreybutler/nvm-windows/releases
双击安装
2、在node官网下载安装多个node
3、切换node
2、创建项目
1、安装依赖
pnpm i
2、启动项目
npm run dev
3、配置@指向src
import { defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import path from 'path';
const resolve = (dir) => path.resolve(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig(({mode})=>{
// 获取当前环境的配置
const config = loadEnv(mode, './')
return {
plugins: [vue(),
Components({
resolvers: [VantResolver()],
}),
],
resolve: {
alias: {
'@': resolve('src'),//作为 entries 的选项
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
}
})
3、安装vant4
1、安装
pnpm add vant
2、按需引入
pnpm add unplugin-vue-components -D
3、配置插件
在 vite.config.js
文件中配置插件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
],
})
4、使用组件
<van-button type="primary" >默认按钮</van-button>
tips:函数组件样式有异常,在main.js中引入vant样式
import "vant/lib/index.css"
5、rem布局适配
1、安装插件
- postcss-pxtorem 是一款 PostCSS 插件,用于将 px 单位转化为 rem 单位
- lib-flexible 用于设置 rem 基准值
pnpm install postcss postcss-pxtorem --save-dev
pnpm i -S amfe-flexible
2、PostCSS 示例配置:新建postcss.config.js
// postcss.config.js
module.exports = {
plugins: {
// postcss-pxtorem 插件的版本需要 >= 5.0.0
'postcss-pxtorem': {
rootValue({ file }) {
return file.indexOf('vant') !== -1 ? 37.5 : 75;
},
propList: ['*'],
},
},
};
3、在main.js中引入 amfe-flexible
import 'amfe-flexible'
重启项目报错
修改文件名后缀.cjs, postcss.config.cjs,重启项目即可
4、使用sass
1、安装
pnpm install --save-dev sass
2、新建src/styles文件夹下index.scss,定义默认颜色变量
$defaultColor:#1989fa;
3、vite配置
import { defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import path from 'path';
const resolve = (dir) => path.resolve(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig(({mode})=>{
// 获取当前环境的配置
const config = loadEnv(mode, './')
return {
plugins: [vue(),
Components({
resolvers: [VantResolver()],
}),
],
css:{
preprocessorOptions: {
scss: {
additionalData: ` @import "@/styles/index.scss"; `
}
}
},
resolve: {
alias: {
'@': resolve('src'),//作为 entries 的选项
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
}
})
4、使用scss变量
<script setup>
</script>
<template>
<div>
<van-button type="primary" >默认按钮</van-button>
<div class="test">测试字体大小</div>
</div>
</template>
<style scoped lang="scss">
.test{
font-size: 40px;
color: $defaultColor;
}
</style>
5、配置环境变量
1、新建 .env.development、.env.production文件
.env.development内容如下
VITE_APP_BASE_URL='/api'
#VITE_APP_BASE_URL='http://192.168.1.33:8088'
2、使用环境变量vite.config.js
import { defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import path from 'path';
const resolve = (dir) => path.resolve(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig(({mode})=>{
// 获取当前环境的配置
const config = loadEnv(mode, './')
return {
plugins: [vue(),
Components({
resolvers: [VantResolver()],
}),
],
css:{
preprocessorOptions: {
scss: {
additionalData: ` @import "@/styles/index.scss"; `
}
}
},
server: {
proxy: {
'/api': {
// target: "http://192.168.1.33:8088",
target: config.VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
resolve: {
alias: {
'@': resolve('src'),//作为 entries 的选项
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
}
})
6、vite配置跨域
import { defineConfig,loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
import path from 'path';
const resolve = (dir) => path.resolve(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig(({mode})=>{
// 获取当前环境的配置
const config = loadEnv(mode, './')
return {
plugins: [vue(),
Components({
resolvers: [VantResolver()],
}),
],
css:{
preprocessorOptions: {
scss: {
additionalData: ` @import "@/styles/index.scss"; `
}
}
},
server: {
proxy: {
'/api': {
// target: "http://192.168.1.33:8088",
target: config.VITE_APP_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
},
resolve: {
alias: {
'@': resolve('src'),//作为 entries 的选项
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
},
}
})
7、请求响应加密sm-crypto
1、安装
pnpm i sm-crypto --save
2、新建config/index.js,配置加密解密公钥私钥
export const PUBLICKEY='****************************************'
export const PRIVATEKEY='**************************'
3、新建utils/crypto.js,封装加密解密方法
import { sm2 } from 'sm-crypto';
import {PUBLICKEY,PRIVATEKEY} from '@/config/index'
//加密
export function doEncrypt(msgString) {
let msg = msgString
if (typeof msgString !== 'string') {
msg = JSON.stringify(msgString)
}
// console.log(msg,'加密前')
// 1 - C1C3C2; 0 - C1C2C3; 默认为1
let cipherMode = 0
let publicKey = PUBLICKEY
// 加密结果
let encryptData = sm2.doEncrypt(msg, publicKey, cipherMode)
//Base64编码 自行选择是否使用
//let baseEncode = Base64.encode(encryptData)
// 加密后的密文前需要添加04,后端才能正常解密 (不添加04,后端处理也可以)
let encrypt = '04' + encryptData
return encrypt
}
// 解密
export function doDecryptStr(enStr) {
let msg = enStr
if (typeof enStr !== 'string') {
msg = JSON.stringify(enStr)
}
// 1 - C1C3C2; 0 - C1C2C3; 默认为1
let cipherMode = 0
let privateKey = PRIVATEKEY
let enval = enStr.substring(2)
// 解密结果
let doDecrypt = sm2.doDecrypt(enval , privateKey, cipherMode)
// 解密后类型转换
let objData = JSON.parse(doDecrypt)
return objData
}
8、封装axios
1、安装axios、qs
pnpm i axios qs --save
2、新建utils/request.js,后台是.net,要求传参formData格式
import axios from 'axios'; // 引入axios
import qs from 'qs'
import { showToast,showLoadingToast,showFailToast, closeToast } from 'vant';
import {doEncrypt,doDecryptStr} from './crypto'
let toast=null
// 创建时自定义默认配置,超时设置为全局默认值0秒
let service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_URL, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 50000 ,// request timeout
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/x-www-form-urlencoded'
// 'Content-Type': 'application/json'
}
})
// 请拦截
service.interceptors.request.use(
config => {
//loading
toast=showLoadingToast({
forbidClick: true,
loadingType: 'spinner',
message: '加载中',
});
let token = localStorage.getItem('token')
if (token) {
config.headers['token'] = token
}
// console.log(config.data,'加密前参数')
config.data=qs.stringify({json:doEncrypt(config.data)});
// console.log(config.data,'加密后参数')
return config
},
error => {
// do something with request error
closeToast()//清除loading
console.log(error) // for debug
return Promise.reject(error)
}
)
// 响应拦截
service.interceptors.response.use(
response => {
closeToast()//清除loading
// console.log('response',response);
let {data} = response
if(data.Status!==1) return showFailToast(data.Msg);
return doDecryptStr(data.Data)
},
error => {
console.log('err' + error) // for debug
showFailToast(error || "请求失败");
// return Promise.reject(error)
}
)
export default service
9、api集中管理
1、新建api文件夹,新建user.js
import request from '@/utils/request'
export function loginApi(data) {
return request({
url: '/login.asmx/UserLogin',
method: 'post',
data,
})
}
2、页面调用
import {loginApi} from '@/api/user.js'
const login = async ()=>{
let res = await loginApi({
Account:"admin",
Pwd:"0000"
})
console.log(res,'返回结果')
}
login()
10、安装路由
1、安装
pnpm install vue-router@4
2、新建router/index.js
import {createRouter,createWebHashHistory} from 'vue-router'
import Home from '@/views/home/Home.vue'
import About from '@/views/about/About.vue'
// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
]
// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router =createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router
3、使用
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
11、安装pinia
1、安装
pnpm install pinia --save
2、main.js引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import 'amfe-flexible'
import 'vant/lib/index.css'
import { createPinia } from 'pinia'
const pinia = createPinia()
const app= createApp(App)
app.use(router)
app.use(pinia)
app.mount('#app')
2、新建store/home.js
import { defineStore } from 'pinia'
export const homeStore = defineStore('home',{
state:()=>{
return {
count:100,
price:250
}
},
getters:{
doubleCount(){
return this.count*2
},
doublePrice(){
return this.price*2
}
},
actions:{
changeStoreData(){
this.count+=1
this.price+=1
},
}
})
3、使用
<template>
<div>
<h1> 主页{{ msg }}</h1>
<p>{{count}}</p>
<p>{{doubleCount}}</p>
<van-button size='large' type="primary" @click="changeData">改变数据</van-button>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { storeToRefs } from 'pinia';
import { homeStore } from '@/store/home.js';
import {loginApi} from '@/api/home.js'
const store = homeStore()
let { count,doubleCount,price,doublePrice } = storeToRefs(store)
defineProps({
msg: String,
})
const changeData = ()=>{
//1、直接修改count
// count.value++
// price.value++
//2、$patch批量修改State的值
// store.$patch({
// count:500,
// price:1000
// })
//3、$patch批量修改函数形式
// store.$patch((state)=>{
// state.count++
// state.price++
// })
//4、通过原始对象修改整个实例
//$state您可以通过将store的属性设置为新对象来替换store的整个状态
//缺点就是必须修改整个对象的所有属性
// store.$state={
// count:0,
// price:1
// }
//5、通过actions修改
store.changeStoreData()
}
const login = async ()=>{
let res = await loginApi({
Account:"admin",
Pwd:"0000"
})
console.log(res,'返回结果')
}
login()
</script>
<style lang="scss" scoped>
h1{
font-size: 40px;
color: $defaultColor;
}
</style>