vue3.2+vite+vant4+sass搭建笔记

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、安装插件

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>

猜你喜欢

转载自blog.csdn.net/qq_38388578/article/details/130508543