Vue3 学习笔记

vue3

官网:简介 | Vue.js (vuejs.org)

1. 环境搭建与启动

npm create vue@latest

这一指令将会安装并执行 create-vue,它是 Vue 官方的项目脚手架工具

之后,你将会看到一些诸如 TypeScript 和测试支持之类的可选功能提示:

✔ Project name: … <your-project-name> 
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.

注意project name 输入的时候不要有大写字母

然后会提示:

Done. Now run:

  cd first_vue (刚刚填写的project名称)
  npm install
  npm run dev

按照要求 进入 first_vue,执行 npm install ,npm run dev

  VITE v4.4.9  ready in 494 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h to show help

出现以上界面就成功了,在浏览器界面访问 http://localhost:5173/ 可以看到 vue 界面

使用 vscode 进入项目会发现有很多的文件夹

创建好项目了也可以直接在vscode的左下角使用 npm 脚本

下载 volar 插件:


2. 修改端口

vue3 默认端口5173

想要把端口号修改为9090,在vite.config.js中写入

server: {
    port: 9090,//端口号
    host: true,//ip地址 或 '0.0.0.0' 或 "loaclhost"
    open: false, //启动后是否自动打开浏览器
    https: false, // 是否开启 https
},

3. 组合式API

3.1 setup
  1. 执行时间beforeCreate还要

  2. setup函数中,获取不到 this

  3. setup函数中的 数据 和 函数,需要 return,简化请看第4点

  4. 如果在 script中 使用setup,就不需要return了(语法糖),帮你return了。

  <!-- script加上setup允许在script中直接编写组合式 api-->
  <script setup>
  
  const messge = "qwq";
  const hello = "hello vue3"
  const show = () => {
      console.log(messge);
  }
  
  </script>
  
  <template>
      <p> {{ hello }}</p>
      <button @click="show">button</button>
  </template>

3.2 reactive 和 ref 函数

在这里插入图片描述

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>

import { reactive } from 'vue'
// 接受对象参数传递并返回一个响应式的对象,响应式理解的来说就是同步变化
const state = reactive({
    count:100
})
// 这里{count:100} 是新建了一个匿名对象作为 reactive 的参数,js中的对象就是 name:value 键值对
const setCount = () => {
    state.count++;
}

</script>

<template>
    <div>
        <div> {{ state.count }} </div>
        <button @click="setCount"> +1 </button>
    </div>
</template>

这里不一样的是 既可以接收简单类型,又可以接收对象类型

本质:在原有传入数据的基础上,外层包了一层对象,实际上还是借助了 reactive

注意:在 script 中访问 ref 定义的数据的时候需要通过.value,但是在template中 不需要

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>

import { ref } from 'vue'
const count = ref(0)
console.log(count.value); 

</script>

<template>
    <div>
        {{ count }} 
    </div>
    <div>
        <button @click="() => { count++ }"> +1 </button>
    </div>
</template>


3.3 computed

在这里插入图片描述

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import { computed, ref } from 'vue';

const list = ref([1,1,4,5,1,4])
const computedList = computed(
    () =>{
        return list.value.filter(i => i > 2)
    }
)
const userInput = ref('')

const addValue = (userInput) => {
    if (userInput != '') {
        list.value.push(parseInt(userInput))
    }
}


</script>

<template>
    <div>
        <div>list:{{ list }}</div>
        <div>过滤之后的list:{{ computedList }}</div>
        <div>
          <input v-model="userInput" placeholder="输入一个值" />
          <button @click="addValue(userInput)">添加值到list</button>
        </div>
      </div>
    
</template>


注意:computed中也可以编写 get set方法,可以用来将 ref 对象变为可写 ( ref 对象默认可读)

例如:

<script setup>
import { computed, ref } from 'vue';
const tmp = ref(3)
const tmpComputed = computed({
    get:() => {
        return tmp.value + 1
    },
    set:(val) => {
        tmp.value = val
    }
})

tmpComputed.value = 2
console.log(tmp.value)
console.log(tmpComputed.value)

</script>

3.4 watch

作用:侦听一个或者多个数据的变化,数据变化时立即执行回调函数

使用:

  1. 导入 watch 函数
  2. 执行 watch 函数传入要侦听的响应式数据(ref 对象)和 回调函数

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import { watch, computed, ref } from 'vue';

const number = ref(0)
const name = ref("张三")

const changNumber = () => {
    number.value++;
}

const changeName = () => {
    name.value = "李四"
}

// 监视单个 ref对象 ,number
// 注意这里是对象,不需要取值
// 语法为watch( ref对象, (newValue, oldValue) => {})
watch(number, (newValue, oldValue) => {
    console.log(newValue, oldValue);
})

// 监视多个 ref 对象,number 和 name
// 语法为watch([ref对象1,ref对象2...], (newArr, oldArr) => {})
watch([number, name], (newArr, oldArr) => {
    console.log(newArr, oldArr);
})


</script>

<template>
    <div>
        <div>
            {{ number }}
            <button @click="changNumber">change number</button>
        </div>
        <div>
            {{ name }}
            <button @click="changeName">change name</button>
        </div>
    </div>
    
</template>

这里其实 oldValue 和 oldArr,可以忽略,具体情况具体分析,如果不需要旧值,不接收就好了,这也是newValue等是第一个参数的原因

immediate 和 deep :

immediate:

添加immediate对象,可以让监视在程序加载时立即启动一次,而不需要等待第一次值改变。

例如:

watch(number, (newValue, oldValue) => {
    console.log(newValue, oldValue);
},{
    immediate:true
})

deep:

deep 是深度监视,watch的默认监视进行的是浅层监视,对于简单类型的值可以直接监视,但监视不到复杂类型内部数据的变化。

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import { watch, computed, ref } from 'vue';
const person = ref({
    name:"张三",
    age:18,
    sex:1
})

const changeAge = () => {
    person.value.age++;
}

watch(person, (newValue) => {
    console.log(newValue);
},{
    deep:true
})

</script>

<template>
    <div>
        <div>{{ person }}</div>        
        <button @click="changeAge">age++</button>
    </div>
    
</template>

使用deep相当于监视了对象的所有属性,如果我只需要监听一个特定的属性呢?

也可以实现,例如:

watch(()=>person.value.age, (newValue)=>{
    console.log(newValue);
})

就是把第一个参数从对象,换成了一个返回你需要监听属性的函数


3.5 生命周期

每一个生命周期都有一个对应的方法,进行到该生命周期就会触发这个方法。

在这里插入图片描述

例如:

onMounted(() => {
    console.log("mounted生命周期函数")
})

3.6 父子通信
3.6.1 在父组件中引入子组件:

局部导入:

components包下写子组件,例如sonCom.vue

然后在父组件中 import 导入后,直接在<template>中使用标签使用

例如:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import sonCom from './components/sonCom.vue'
</script>
<template>
    <div>
        <h3> 父组件 </h3>
    </div>
    <div>
        <sonCom></sonCom>
    </div>
</template>
<style>
</style>

3.6.2 父传子:

在这里插入图片描述

例如,父组件:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import sonCom from './components/sonCom.vue'
import { ref } from 'vue';

const money = ref(10000)

</script>

<template>
    <div>
        <h3> 父组件 </h3>
    </div>
    <div>
        <sonCom car="兰博基尼" :money="money"></sonCom>
    </div>
    
</template>

<style>

</style>

子组件,sonCom:

<script setup>
const props = defineProps({
    car: String,
    money: Number
})
console.log(props.car);  //这里注意脚本中需要写 props.属性,但是模板中不需要写,直接用属性

</script>

<template>
    <div class="son">
        <p>我是子组件</p>
        <p>我是父组件中继承了:{{ car }}, {{ money }}</p>
    </div>

</template>

<style>
.son{
   border: solid 2px brown;
   padding: 30px;
}
</style>

3.6.3 子传父:

如果要修改父组件的值:

  1. 调用我需要做的修改父组件的值的方法
  2. 在方法中调用 emit 函数,语法为 emit('事件名', 参数)
  3. 使用defineEmits方法提供 emit 函数,语法const emit = defineEmits(['事件1', '事件2']),理解成注册事件就行
  4. 父组件在 子组件标签中 用@emit传来的事件名='xxxx',绑定子组件的事件
  5. 定义xxxx,其中可以使用emit传来的参数

例如,父组件:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import sonCom from './components/sonCom.vue'
import { ref } from 'vue'

const money = ref(10000);
const earnMoney = () =>{
    money.value += 50;
}
const useMoney = (restMoney) => {
    money.value = restMoney
}

</script>

<template>
    <div>
        <h3> 父组件 </h3>
        <p>
             当前money:{{ money }}
             <button @click="earnMoney"> 赚钱 </button>
        </p>
        
    </div>
    <div>
        <sonCom car="兰博基尼" :money="money" @useMoney="useMoney"></sonCom>
    </div>
    
</template>

<style>

</style>

子组件:

<script setup>
const props = defineProps({
    car: String,
    money: Number
})
const emit = defineEmits(["useMoney"])
const useMoney = () => {
    emit('useMoney', 5)
}


</script>

<template>
    <div class="son">
        <h3>我是子组件</h3>
        <p>
            我是父组件中继承了:{{ car }}, {{ money }}
            <button @click="useMoney"> 花钱 </button>
        </p>
    </div>

</template>

<style>
.son{
   border: solid 2px brown;
   padding: 30px;
   margin-top: 10px;
}
</style>

3.7 模板引用 与 defineExpose

这样也可以实现子传父。


3.8 provide 和 inject 跨层传递


3.8 defineOptions

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


3.9 defineModel

想要使用首先要在vite中修改:

plugins: [
    vue({
      script: {
        defineModel: true, // 启用defineModel
      }
    }),
  ],

在这里插入图片描述


4. pinia

简介 | Pinia (vuejs.org)

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。

安装

npm install pinia

导包:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')
4.1 快速入门

使用:

  1. 在 src 下新建文件夹 store 用来存储仓库
  2. 在 store 下新建仓库 ( js ) 并使用defineStore函数创建对象
  3. 在需要使用仓库的地方 实例化仓库对象,直接调用对象中的值 和 函数

例如:

testStore:

import { defineStore } from 'pinia'
import { ref } from 'vue';
export const useTestStore = defineStore('testStore', () => {
    
    const count = ref(0);

    const subCount = () => {
        count.value--;
    }
    const addCount = () => {
        count.value++;
    }
    

    return{
        count,
        subCount,
        addCount,
    }
})

App.vue:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import sonCom from './components/sonCom.vue';
import sonCom2 from './components/sonCom2.vue';
import { useTestStore } from './store/test';

const testStore = useTestStore() //创建实例

</script>

<template>
    <div>
        <h1>我是父组件 -- {{ testStore.count }}</h1>
        <sonCom></sonCom>
        <sonCom2></sonCom2>
    </div>
</template>

<style>

</style>

sonCom.vue:

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import { useTestStore } from '../store/test';
const testStore = useTestStore()

</script>

<template>
    <div>
        <h2>
            我是儿子组件 -- {{ testStore.count }}
            <button @click="testStore.addCount"> + </button>
        </h2>
    </div>
</template>

<style></style>

4.2 异步请求

我们使用axios来发送异步请求,例如:

import { defineStore } from "pinia";
import axios from 'axios'
import { ref } from "vue";

export const useaxiosStore = defineStore("axiosStore", () => {

    const channellist = ref([])
    const getList = async() => { //async 表示异步函数 
        const { data: { data } } = await axios.get("http://localhost:8080/pinia") // 等待数据获取完毕
        channellist.value = data.channels
    }

    return{
        channellist,
        getList
    }
})

app.vue

<!-- script加上setup允许在script中直接编写组合式 api-->
<script setup>
import { useaxiosStore } from './store/axios';
const axiosStore = useaxiosStore()  //创建实例
</script>
<template>
    <div>
        <button @click="axiosStore.getList"> 获取数据 </button>
        <ul>
            <li  v-for="i in axiosStore.channellist" :key="i.id" > {{ i.name }} </li>
        </ul>

    </div>
</template>
<style>
</style>

java,接收请求并返回数据:

package com.zhx.controller;


import com.zhx.pojo.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.io.PipedReader;
import java.util.*;

@RestController
public class piniaController {
    @GetMapping("/pinia")
    public Result send(){
        class data{
            private List<Object> channels;
            private String message;

            public data(List<Object> channels, String message) {
                this.channels = channels;
                this.message = message;
            }

            public List<Object> getChannels() {
                return channels;
            }

            public void setChannels(List<Object> channels) {
                this.channels = channels;
            }

            public String getMessage() {
                return message;
            }

            public void setMessage(String message) {
                this.message = message;
            }
        }

        List<Object> list = new ArrayList<>();
        for(int i=1;i<=5;i++){
            Map<String, Object> map = new HashMap<>();
            map.put("id", i);
            map.put("name", "name:"+i);
            list.add(map);
        }
        return Result.success(new data(list, "qwq"));
    }
}

这里还需要解决一下跨域请求,使用 java 的 config类:

package com.zhx.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();

        // 允许哪些源访问
        config.addAllowedOrigin("http://localhost:5173");

        // 允许哪些 HTTP 方法
        config.addAllowedMethod("GET");

        source.registerCorsConfiguration("/pinia/**", config);
        return new CorsFilter(source);
    }
}


4.3 仓库解构,storeToRefs(store)

我们之前都是直接导入仓库,然后实例化,然后使用 .进行访问,如果想要直接进行解构的话,需要注意两点:

  1. 解构 store 的状态需要使用storeToRefs(store)
  2. 解构 store 的 action(组合式中就是函数 )直接解构

因为解构会破坏响应性,但是 action ,比如说函数没有响应性可言,就是用就完事了。

例如:

<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// 需要调用方法
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>

4.4 pinia持久化

快速开始 | pinia-plugin-persistedstate (prazdevs.github.io)

我们的响应式数据变更之后,如果刷新页面,响应式数据会重置,如果我们需要对响应式数据进行一个持久化,那么就可以使用上面的插件。

安装:npm i pinia-plugin-persistedstate

配置:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

用法:

创建 Store 时,将 persist 选项设置为 true

import { defineStore } from 'pinia'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('你好 pinia')
    return { someState }
  },
  {
    persist: true, //实际上就是加了一个参数,第三个参数把persist改成true
  },
)

还有一些配置操作,可以参考官网:
配置 | pinia-plugin-persistedstate (prazdevs.github.io)

例如,我不希望把整个 state 进行持久化,我们可以使用 path 进行注册

import { defineStore } from 'pinia'
import { ref } from 'vue';
export const useTestStore = defineStore('testStore', () => {
    
    const count = ref(0);
    const name = ref('feixin')
    const subCount = () => {
        count.value--;
    }
    const addCount = () => {
        count.value++;
    }

    return{
        count,
        subCount,
        addCount,
        name,
    }
},{
    persist: {
        paths:['count'] // 这里就只对 count 进行了持久化,而name没有
    }
})

5. 常用指令

指令作用
v-bind为HTML标签绑定属性值,如设置href,css样式等, v-bind:href 可以省略为 :href
v-model在表单元素上创建双向数据绑定
v-on为HTML标签绑定事件
v-if类下
v-else-if条件性的渲染某元素,判定为true时渲染,否则不渲染
v-else类上
v-show根据条件展示某元素,区别在于切换的是display属性的值
v-for列表渲染,遍历容器的元素或者对象的属性

v-bind 和 v-model

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue test</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        <a v-bind:href="url">这是一个链接</a>
        <!-- v-bind:href 可以省略为 :href -->
        <input type="text" v-model="url">
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data:{
           url:"https://www.baidu.com"
        }
    })
</script>
</html>

可以实现更改表单中的网址,旁边的a标签绑定的网址也会发生相应的变化

注意:通过 v-bind 或者 v-model 绑定的变量,必须在数据模型中声明。


v-on

可以绑定很多时间比如click,blur,focus, 与 js 事件类似

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue test</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="button" value="click me" v-on:click="handle()">
        <!-- v-on:click可以简化为@click -->
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data: {
            url: "https://www.baidu.com"
        },
        methods: {
            handle: function () {
                alert("i have been clicked");
            }
        },
    })
</script>

</html>

效果就是点击后触发事件


条件指令 v-if v-else-if v-else v-show:

if,else-if,else 是一起配套使用的

例如:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue test</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        年龄:<input type="text" v-model="age">经判定,为:
        <span v-if="age<35">年轻人 35岁以下</span>
        <span v-else-if="age>=35 && age<=60">中年人 35-60</span>
        <span v-else>老年人 60以上</span>
        <!-- 注意这里else后面没东西了 -->
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data: {
            age:20,
        },
        
    })
</script>

</html>

效果为修改输入框中的值,后面的判定字会改变,if 这一套 如果 条件为 else 的话标签直接不会在浏览器中被渲染,也就是根本不会出现在浏览器源码当中。

v-show:

上述效果同样可以通过v-show来实现。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue test</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        年龄:<input type="text" v-model="age">经判定,为:
        <span v-if="age<35">年轻人 35岁以下</span>
        <span v-else-if="age>=35 && age<=60">中年人 35-60</span>
        <span v-else>老年人 60以上</span>
        <br><br>
        年龄:<input type="text" v-model="age">经判定,为:
        <span v-show="age<35">年轻人 35岁以下</span>
        <span v-show="age>=35 && age<=60">中年人 35-60</span>
        <span v-show="age>60">老年人 60以上</span>
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data: {
            age:20,
        },
        
    })
</script>

</html>

效果是一样的,区别在于v-show 如果条件为 false 的话标签依然会被浏览器渲染,不过是被display:none设置了不展示


v-for: 遍历数据对象

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue test</title>
    <script src="../js/vue.js"></script>
</head>

<body>
    <div id="app">
        <div v-for="addr in addrs" :key="index">
            {{addr}}
        </div>
        <hr>
        <div v-for="(addr, index) in addrs" :key="index">
            {{index + 1}} : {{addr}}
        </div>
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data: {
            addrs:["beijing","shanghai","xian","guilin"]
        },
        
    })
</script>

</html>

6. Element -plus

6.1 安装

安装 | Element Plus (element-plus.org)

根据文档,在当前目录下安装

或者使用以下方式:

vue3+vite2增加element-plus的CDN链接打包构建 - 掘金 (juejin.cn)

按需引入:

  1. pnpm element-plus

  2. pnpm add -D unplugin-vue-components unplugin-auto-import

  3. 在vite.config.js中配置:

    import AutoImport from 'unplugin-auto-import/vite'  //---1
    import Components from 'unplugin-vue-components/vite' //---2
    import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'//---3
    
    export default defineConfig({
      plugins: [
        vue(),
        AutoImport({
          resolvers: [ElementPlusResolver()] //---1
        }),
        Components({
          resolvers: [ElementPlusResolver()] //---2
        })
      ],
      resolve: {
        alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
        }
      }
    })
    

6.2 使用

创建如下目录

ElementView.vue中编写

<script>
export default{
    
}
</script>

<template>
    <div>
        <el-row class="mb-4">
            <el-button>Default</el-button>
            <el-button type="primary">Primary</el-button>
            <el-button type="success">Success</el-button>
            <el-button type="info">Info</el-button>
            <el-button type="warning">Warning</el-button>
            <el-button type="danger">Danger</el-button>
        </el-row>
		<!-- 各种你想添加的组件 -->	
    </div>
</template>
<style></style>

App.vue中编写

<script>
import ElementView from './views/element/elementView.vue';

export default{
    components: { ElementView }
}


</script>

<template>
    <div>
        <ElementView>

        </ElementView>
    </div>
</template>

<style>

</style>

即可导入。


6.3 常见组件

组件 | Element

进去复制粘贴使用,懂?


6.4 引入

引入组件之后需要在components中声明一下才可以使用

例如:

<script>
import { Menu as IconMenu, Message, Setting } from '@element-plus/icons-vue'; 
// 这里引入了组件
export default {
    data() {
        return {
            searchForm: {
                name: "",
                gender: "",
                entryDate: [],
            }
        }
    },
    components: {
        Message, Setting
        //这里需要声明
    },
    methods: {
        query() {
            alert(JSON.stringify(this.searchForm));
        },
        sizeChange(val){
            alert("每页记录数变化" + val)
        },
        currentChange(val){
            alert("页码发生变化" + val)
        },
    }
}
</script>

7. pnpm

npm install -g pnpm

在这里插入图片描述

在这里插入图片描述


8. ESlint 配合 Prettier

参考旁边的文件 大事件管理系统中的 ESlint配置


9. husky

+ 别打上去

pnpm dlx husky-init && pnpm install

在这里插入图片描述

暂存区 eslint 校验
在这里插入图片描述


10. axios 配置

在这里插入图片描述

10.1. 创建 axios 实例

们会使用 axios 来请求后端接口, 一般都会对 axios 进行一些配置 (比如: 配置基础地址等)

一般项目开发中, 都会对 axios 进行基本的二次封装, 单独封装到一个模块中, 便于使用

  1. 安装 axios
pnpm add axios
  1. 新建 utils/request.js 封装 axios 模块

    利用 axios.create 创建一个自定义的 axios 来使用

    http://www.axios-js.com/zh-cn/docs/#axios-create-config

import axios from 'axios'

const baseURL = 'http://big-event-vue-api-t.itheima.net'

const instance = axios.create({
  // TODO 1. 基础地址,超时时间
})

instance.interceptors.request.use(
  (config) => {
    // TODO 2. 携带token
    return config
  },
  (err) => Promise.reject(err)
)

instance.interceptors.response.use(
  (res) => {
    // TODO 3. 处理业务失败
    // TODO 4. 摘取核心响应数据
    return res
  },
  (err) => {
    // TODO 5. 处理401错误
    return Promise.reject(err)
  }
)

export default instance
10.2. 完成 axios 基本配置
import { useUserStore } from '@/stores/user'
import axios from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'

const baseURL = 'http://big-event-vue-api-t.itheima.net'

const instance = axios.create({
  baseURL,
  timeout: 100000
})

instance.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()
    if (userStore.token) {
      config.headers.Authorization = userStore.token
    }
    return config
  },
  (err) => Promise.reject(err)
)

instance.interceptors.response.use(
  (res) => {
    if (res.data.code === 0) {
      return res
    }
    ElMessage({ message: res.data.message || '服务异常', type: 'error' })
    return Promise.reject(res.data)
  },
  (err) => {
    ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })
    console.log(err)
    if (err.response?.status === 401) {
      router.push('/login')
    }
    return Promise.reject(err)
  }
)

export default instance
export { baseURL }

11. 打包

npm run build 可以进行打包,打包之后会出现在dist中

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/124692.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记|SPSS|描述变量|按照3倍标准差剔除异常值|标准化值另存为变量|剔除个案|Zscore|箱图|Zscore取值范围

目录 学习目的软件版本原始文档概述服从正态分布-按照3倍标准差剔除异常值读数据数据概览描述变量 正态性检验异常值检验及剔除 非正态分布-根据Zscore取值范围确定基础数据数据概览正态性检验Tips&#xff1a;箱图圆圈的含义 异常值检验及剔除描述变量&#xff0c;并将标准化值…

C语言C位出道心法(三):共用体|枚举

C语言C位出道心法(一):基础语法 C语言C位出道心法(二):结构体|结构体指针|链表 一: C语言共用体数据类型认知 二:C语言枚举基本数据类型认知 忙着去耍帅,后期补充完整.............

Verilog刷题[hdlbits] :Alwaysblock2

题目&#xff1a;Alwaysblock2 For hardware synthesis, there are two types of always blocks that are relevant: 对于硬件综合&#xff0c;有两种相关的always块&#xff1a; Combinational: always () 组合型&#xff1a;always ()Clocked: always (posedge clk) 时钟型…

Python实现图片与PDF互相转换

目录 图片转PDF文件夹所有图片转为1个PDF文件夹指定图片转为1个PDF文件夹所有图片分别转为PDF举例 PDF转图片指定PDF转为图片文件夹所有PDF转为图片举例 图片转PDF 之前的一篇博客《Python合并拼接图片》&#xff0c;可对图片进行合并拼接 使用前需要安装PyMuPDF库&#xff0c…

设置区块链节点输出等级为警告级,并把日志存储阈值位100MB并验证;

题目 获取指定区块链节点输出等级为警告级&#xff0c;并设置日志存储阈值位100MB并验证&#xff1b; 操作步骤 1.切换目录 cd nodes/127.0.0.1/node0 2.打开配置文件并修改 vim config.ini warn&#xff1a;警告

力扣最热一百题——每日温度

Python后面的文章&#xff0c;内容都比较多&#xff0c;但是同时我又想保持每天更新的速度&#xff0c;所以Python的文章我继续打磨打磨&#xff0c;先更新一篇算法的文章。 一身正气报国家&#xff0c;旁无乱境不恋她 ヾ(◍∇◍)&#xff89;&#xff9e; 力扣题号&#xff1a…

大语言模型比武

今年随着 ChatGPT 的流行&#xff0c;并在各个领域有一定程度生产级别的应用。国内外也掀起了一股大语言模型浪潮&#xff0c;各大厂商都推出了自己的大语言模型&#xff0c;阿里推出了 通义千问&#xff0c;腾讯推出了 Hunyuan&#xff0c;亚马逊云推出了 Titan&#xff0c;大…

微服务-grpc-consul-protoBuf-micro

微服务 一、微服务&#xff08;microservices&#xff09; 近几年,微服这个词闯入了我们的视线范围。在百度与谷歌中随便搜一搜也有几千万条的结果。那么&#xff0c;什么是微服务 呢&#xff1f;微服务的概念是怎么产生的呢&#xff1f; 我们就来了解一下Go语言与微服务的千丝…

C++ 断言

1.断言的概念 断言(assertion)是一种编程中常用的手段。在通常情况下&#xff0c;断言就是将一个返回值总是需要为真的判别式放在语句中&#xff0c;用于排除在设计的逻辑上不应该产生的情况。比如一个函数总需要输人在一定的范围内的参数&#xff0c;那么程序员就可以对该参数…

汽车标定技术(五)--基于模型开发如何生成完整的A2L文件(1)

1 数据对象的创建 CtrlH打开Model Explorer&#xff0c;在Base workspace中点击工具栏add&#xff0c;出现如下界面&#xff0c; 可以看到Simulink提供了多种数据类型 Matlab Variable&#xff1a;Simulink.Parameter&#xff1a;使用该数据对象表示工程应用中的标定量Simuli…

CSS 渐变、文本效果、字体

一、CSS3渐变&#xff1a; CSS3渐变&#xff08;gradient&#xff09;可以在两个或多个指定的颜色之间显示平稳的过渡。CSS3定义了两种类型的渐变&#xff08;gradient&#xff09;&#xff1a;线性渐变&#xff08;linear gradient&#xff09;-向下/向上/向左/向右/对角方向…

MySQL–第4关:查询用户日活数及支付金额

MySQL–第4关&#xff1a;查询用户日活数及支付金额 – WhiteNights Site 标签&#xff1a;MySQL 非常好的题&#xff0c;爱来自中国。 题目 没啥用 任务描述 现有3张业务表&#xff0c;详见如下: 需要输出结果如下&#xff0c;没有支付的日期不需要显示&#xff0c;请写出对…

设计模式——建造者模式

目录 建造者模式盖房项目需求基本介绍四个角色实例代码注意事项和细节抽象工厂模式 VS 建造者模式 建造者模式 盖房项目需求 传统方式&#xff1a;打地基&#xff0c;砌墙&#xff0c;封顶 盖房子步骤 public abstract class AbstractHouse {// 地基public abstract void b…

【小白专用】PHP中的JSON转换操作指南 23.11.06

一、JSON的基础知识 1.1JSON数据格式 JSON数据格式是一组键值对的集合&#xff0c;通过逗号分隔。键值对由“键”和“值”组成&#xff0c;中间使用冒号分隔。JSON数据格式可以嵌套&#xff0c;而且可以使用数组 二、PHP中的JSON函数 JSON的操作需要使用编程语言进行处理&am…

软考软件设计师刷题笔记整理

软件设计师 HTML代码中&#xff0c;创建指向邮箱地址的链接正确的是ARP攻击造成网络无法跨网段通信的原因是在软件开发过程中进行风险分析关于哈夫曼树的叙述关于风险管理的叙述ISO/IEC9126软件质量模型关于结构化开发方法的叙述分布式数据库中的分片透明、复制透明、位置透明和…

day61--单调栈2

503.下一个更大元素II 42. 接雨水 第一题&#xff1a;下一个更大元素2 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之…

前端工程化(vue2)

一、环境准备 1.依赖环境&#xff1a;NodeJS 官网&#xff1a;Node.js 2.脚手架&#xff1a;Vue-cli 参考网址&#xff1a;安装 | Vue CLI 介绍&#xff1a;Vue-cli用于快速的生成一个Vue的项目模板。主要功能有&#xff1a;统一的目录结构&#xff0c;本地调试&#xff0…

小程序day04

目标 自定义组件 创建组件 引用组件 局部引用 全局引用 组件的函数定义到metods节点中&#xff0c;梦回vue2. 样式 数据&#xff0c;方法&#xff0c;属性 下划线开头的称为自定义方法&#xff0c;非下划线开头的都是事件处理函数。 神特么&#xff0c;this.datathis.pro…

一种ESDF地图实现方法:FIESTA

背景&#xff1a; 在机器人定位、行动规划中建图是一个很重要的工作&#xff0c;只有通过感知器感知到自己在哪、周围有什么&#xff1b;才能为下一步行动作出决策的依据。然而要知道自己在哪&#xff0c;就必须要有一个整体规划和参照也就是所谓的地图。地图相当于是一次规划…

c语言 结构体 简单实例

结构体 简单例子 要求&#xff1a; 结构体保存学生信息操作 代码 #include <stdio.h>//定义结构体 struct student{int ID;char name[20];char sex;char birthday[8];int grade; };int main(){int number;printf("请输入学生个数&#xff1a;");scanf(&quo…