Vue3 学习笔记

news2024/12/23 1:37:57

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中

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter的专属Skia引擎解析+用法原理

Skia是一款跨平台的2D图形库&#xff0c;是Google公司开发的&#xff0c;可以用于开发各种应用程序&#xff0c;如浏览器、游戏、移动应用程序等。Skia引擎的主要特点是速度快、可移植性强、占用的内存少、稳定性佳&#xff0c;适用于多种硬件平台。 Skia的目标是提供快速、高…

Java SE 25居然有8年的Premier Support !

今天偶然间看了一下Oracle官网发布的Java SE路线图&#xff0c;发现Java 25赫然在列&#xff0c;并且Premier Support居然长达8年&#xff01;上一个有这么长支持的版本还是Java 8。Java 17&#xff08;LTS&#xff09;和Java 21&#xff08;LTS&#xff09;算上Extended Suppo…

鸿蒙开发工具DevEco Studio的下载和安装

一、DevEco Studio概述 1、简介 HUAWEI DevEco Studio&#xff08;获取工具请单击链接下载&#xff0c;以下简称DevEco Studio&#xff09;是基于IntelliJ IDEA Community开源版本打造&#xff0c;为运行在HarmonyOS和OpenHarmony系统上的应用和服务&#xff08;以下简称应用…

计算机中丢失mfc140u.dll怎么解决

mfc140u.dll是一个Microsoft Visual C库文件&#xff0c;主要用于MFC&#xff08;Microsoft Foundation Class&#xff09;应用程序的开发。它包含了MFC应用程序所需的一些常用功能&#xff0c;如对话框、窗口、菜单等。当mfc140u.dll丢失时&#xff0c;可能会导致MFC应用程序无…

轻松连接电商平台:百川 Baichuan2-53B模型在无代码开发环境中的应用

连接AI技术与系统&#xff1a;Baichuan2-53B大模型的应用 AI大模型Baichuan2-53B&#xff0c;已经在无代码开发环境中显示出了其强大的能力。它融合了意图理解、信息检索以及强化学习技术&#xff0c;结合有监督微调与人类意图对齐&#xff0c;表现突出。这款大模型可以通过集…

2023-11-07 C语言链接库编译命令

点击 <C 语言编程核心突破> 快速C语言入门 C语言链接库编译命令 前言一、引入库文件, 包括头文件和lib库二、简单示例总结 前言 要解决问题: 一般没有给新手的链接库编译命令学习资料, 然而, 不解决这个问题, 调用库就能折腾到劝退, 我近日回答一个问题, 很简单, 调用…

干货 | 网络安全入门学习笔记

安全是互联网公司的生命&#xff0c;也是每位网民的基本需求。现在越来越多的人对网络安全感兴趣&#xff0c;愿意投奔到网络安全事业之中&#xff0c;这是一个很好的现象。 很多对网络安全感兴趣的朋友&#xff0c;总是在寻找适合0基础的学习资源&#xff0c;今天就给大家分享…

Labview的分支判断

和其他的编程语言一样的。都会有switch,case, if ,else; 再combo box中实现 再后台程序中对应的写上逻辑就好了。

P5906 【模板】回滚莫队不删除莫队

这一题&#xff0c;虽说在洛谷标的是模板题&#xff0c;但可能没有“历史研究”那一题更加模板。 这一题相对于回滚莫队的模板题&#xff0c;可能在回滚的处理上稍微复杂了一点。对于回滚莫队就不多解释了&#xff0c;可以看一下 回滚莫队模板题 这一篇博客&#xff0c;稍微简单…

SpringBoot自动装配 Spring相关 常用设计模式 双亲委派 MongoDB Redis 适配器模式与策略模式

SpringBoot自动装配 阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 Spring相关 阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 常用设计模式 双亲委派 Java虚拟机定义了三个主要的类加载器: 1、启动类加载器 2、扩展类加载器 …

休闲玩具的软文营销策略

休闲玩具行业作为新兴市场&#xff0c;具有广阔的发展前景&#xff0c;生活水平的提高带来消费观念的升级&#xff0c;城市化进程加速导致人们对休闲娱乐的需求持续上涨&#xff0c;玩具作为娱乐性、放松性、互动性的产品受到广大群体喜爱&#xff0c;休闲玩具市场的竞争也愈发…

我是这样发布成绩的

作为一名老师&#xff0c;每当到了期中或者期末考试后&#xff0c;总是有那么些时刻&#xff0c;想要快点把成绩发布出去&#xff0c;让学生知道他们的努力得到了多少回报。但如何发布成绩呢&#xff1f;传统的纸质方式&#xff1f;太慢&#xff01;一个个发短信&#xff1f;太…

广东开放大学:电大搜题助力学子迎考利器

近年来&#xff0c;广东开放大学一直致力于为广大学子提供优质的教育资源和学习服务。作为一所专注于远程教育的学府&#xff0c;广东开放大学不仅拥有雄厚的师资力量和丰富的教育经验&#xff0c;还致力于创新教学手段&#xff0c;为学生提供更便捷、高效的学习体验。在这个信…

【1++的Linux】之线程(三)含生产者消费者模型

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的Linux】 文章目录 一&#xff0c;可重入与线程安全二&#xff0c;死锁三&#xff0c;线程同步什么是线程同步&#xff1f;怎么实现线程同步条件变量 四&#xff0c;生产者与消费者模型1&…

软件测试用例与分类

测试用例与分类 黑盒测试基于需求的设计方法等价类边界值判定表正交表场景设计法错误猜测法 FiddlerPostman测试用例测试分类按测试对象界面测试可靠性测试容错性测试文档测试兼容性测试易用性安装卸载测试安全测试性能测试内存泄漏测试 白盒测试灰盒测试开发阶段单元测试集成测…

uniapp小程序接入腾讯云【增强版人脸核身接入】

文档地址&#xff1a;https://cloud.tencent.com/document/product/1007/56812 企业申请注册这边就不介绍了&#xff0c;根据官方文档去申请注册。 申请成功后&#xff0c;下载【微信小程序sdk】 一、解压sdk&#xff0c;创建wxcomponents文件夹 sdk解压后发现是原生小程序代…

django+drf+vue 简单系统搭建 (2) - drf 应用

按照本系统设置目的&#xff0c;是为了建立一些工具用来处理简单的文件。 1. 准备djangorestframework 关于drf的说明请参见&#xff1a;Django REST Framework教程 | 大江狗的博客 本系列直接使用drf的序列化等其他功能。 安装 conda install djangorestframework conda i…

第三届 “鹏城杯”(初赛)

第三届 “鹏城杯”&#xff08;初赛&#xff09; WEB Web-web1 反序列化tostring打Hack类 Payload:O%3A1%3A%22H%22%3A1%3A%7Bs%3A8%3A%22username%22%3BO%3A6%3A%22Hacker%22%3A2%3A%7Bs%3A11%3A%22%00Hacker%00exp%22%3BN%3Bs%3A11%3A%22%00Hacker%00cmd%22%3BN%3B%7D%7D…

【Java基础】Java容器相关知识小结

Java容器相关知识 0. 前言1. Collection接口1.1. List接口1.1.1. ArrayList1.1.2. LinkedList1.1.3. Vector1.1.4. Stack 1.2. Set接口1.2.1. HashSet1.2.2. LinkedHashSet1.2.3. TreeSet 1.3. Queue接口1.3.1. PriorityQueue1.3.2. LinkedList 2. Map接口2.1. HashMap2.2. Tre…

Verilog刷题[hdlbits] :Always casez

题目&#xff1a;Always casez Build a priority encoder for 8-bit inputs. Given an 8-bit vector, the output should report the first (least significant) bit in the vector that is 1. Report zero if the input vector has no bits that are high. For example, the …