Vue3笔记

Vue3官方文档

参考文章:

手把手教你使用Vite创建Vue3项目

尚硅谷甄选

创建项目

终端运行:

1
npm create vue@latest

使用 Vite 创建项目

注意:Vite 需要 Node.js 版本 18+,20+

终端执行:

1
npm create vite@latest

指令

v-html

{{ button }}中元素不会被解析,需要用<div v-html="button">

1
2
3
4
5
6
7
8
<script setup>
import { ref } from 'vue'
const button = ref('<button>Click Me</button>')
</script>

<template>
<div v-html="button"></div>
</template>

相当于将<div>的innerHTML设为button中的元素

v-bind

使用指令v-bind:属性名=""或其简写:属性名=""为元素添加单个属性,或者使用v-bind=""添加多个属性,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script setup>
import { ref } from 'vue'
const myId = ref('nav')
const myClass = ref('container')
const isButtonDisabled = ref(true)
const myAttr = {
id: 'nav',
class: 'container'
}
</script>

<template>
<div v-bind:id="myId" :class="myClass">bind</div>
<button :disabled="isButtonDisabled">Button</button>
<span v-bind="myAttr"></span>
</template>

v-for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script setup>
import { reactive } from 'vue'
const stars = reactive([
{ name: '角木蛟', part: '东方苍龙' },
{ name: '井木犴', part: '南方朱雀' },
{ name: '奎木狼', part: '西方白虎' },
{ name: '斗木獬', part: '北方玄武' },
])
</script>


<template>
<ul v-for="star in stars">
<li>星宿名:{{ star.name }},所属星象:{{ star.part }}</li>
</ul>
</template>

v-if 和 v-show 的区别

v-show不管初始条件是否为真,元素都会被渲染,只不过是根据条件修改元素的样式来判断是否显示。当v-show="false"时,给元素加上style="display: none;",当v-show="true"时,移除该样式。因此元素始终是存在的。

v-if="false"则是将元素直接删除,DOM元素不再存在。

由于v-show始终都会渲染元素,因此有更高的初始渲染消耗,而v-if若为假则初始时不需要渲染,则没有这部分的消耗。但切换时v-show只需要移除display: none,因此相比v-if的切换消耗会更低。

如果需要频繁切换则用v-show,如果在运行时很少改变则用v-if

响应式数据

ref 和 reactive 的区别

1
2
3
4
5
<script setup>
import { ref, reactive } from 'vue'
const count = ref(0)
const user = reactive({ id: 1, name: '星日马' })
</script>
  • ref可以用于基本数据类型和对象,但reactive只能用于对象
  • 访问ref的值要count.value,而访问reactive的值直接user不需要加value
  • ref适合基本数据类型,reactive适合对象
  • 单独将ref对象中的变量赋值给新变量,新变量也支持响应式;但对reactive进行同样操作则新变量不具备响应式
  • ref通过外层包裹一个对象来实现,reactive通过proxy实现

toRef

将普通变量和响应式对象的成员变量进行双向响应式绑定,不论是改变普通变量的值还是成员变量的值,数据都会更新,解决了reactive无法抽离出响应式变量的问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script setup>

import { ref, reactive, toRef } from 'vue'

const flower = ref({ name: '梅花', price: 48 })
const user = reactive({ id: 1, name: '房日兔' })

const flowerPrice = toRef(flower.value, 'price')
let userId = toRef(user, 'id')

setInterval(() => {
flower.value.price++ // 改变对象的成员变量的值,普通变量的值也会更新
userId.value++ // 改变普通变量的值,成员变量也会更新
}, 1000);

</script>


<template>

<h1>flowerPrice: {{ flowerPrice }}</h1>
<h1>userId: {{ userId }}</h1>

</template>

toRefs

toRef的区别尚不明确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script setup>

import { ref, reactive, toRefs } from 'vue'

const flower = ref({ name: '梅花', price: 48 })
const user = reactive({ id: 1, name: '房日兔' })

let flowerPrice = toRefs(flower.value)['price']
let userId = toRefs(user).id

setInterval(() => {
flower.value.price++
userId.value++
}, 1000);

</script>


<template>

<h1>flowerPrice: {{ flowerPrice }}</h1>
<h1>user.id: {{ user.id }}</h1>

</template>

事件处理

可以使用v-on指令来监听DOM事件,也可缩写成@,用法:

1
2
3
4
5
6
7
8
9
10
11
12
<script setup>

function myFunction() {
console.log('触发了myFunction方法')
}

</script>

<template>
<button v-on:click="myFunction"></button>
<button @click="myFunction"></button>
</template>

事件修饰符

在原生JS中,我们可以使用even.preventDefault()来阻止默认事件或使用event.stopPropagation()阻止事件冒泡,Vue提供了更优雅的实现方式,即事件修饰符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script setup>

function myFunction() {
console.log('触发了myFunction方法')
}

function clickDiv() {
console.log('点击了div')
}

function clickP() {
console.log('点击了p')
}

</script>

<template>
<a href="https://PrinceSaoKe.github.io" @click.prevent="myFunction">点了不会跳转的超链接</a>

<div @click="clickDiv">
<p @click.stop="clickP">Hello World!</p>
</div>
</template>

输出为:

1
点击了p

若不加.stop,则输出为:

1
2
点击了p
点击了div

该写法等同于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script setup>

function myFunction(event) {
event.preventDefault()
console.log('触发了myFunction方法')
}

function clickDiv(event) {
event.stopPropagation()
console.log('点击了div')
}

function clickP(event) {
event.stopPropagation()
console.log('点击了p')
}

</script>

<template>
<a href="http://princesaoke.github.io" @click.prevent="myFunction">点了不会跳转的超链接</a>

<div @click="clickDiv">
<p @click="clickP">Hello World!</p>
</div>
</template>

/public 文件夹和 /src/assets 文件夹的区别

  • 引用/public中的文件时不需要写public目录,直接<img src="/logo.png">,而引用/src/assets中的文件要写全路径<img src="@/assets/logo.png">
  • 打包时/src/assets下的文件会被打包工具处理,包括压缩、重命名等,而/public则不会,是直接复制到dist
  • 如果文件不需要被处理,如网站的结构用图(favicon.ico、logo图片等),放public;否则如内容图片或者需要被构建为base64的小图标放assets

开发过程中的跨域问题

浏览器和后端服务器之间存在跨域问题,但服务器和服务器之间可以随意访问,因此要在本地配置一个代理服务器来做中转,浏览器将请求发到本地代理服务器,代理服务器再发到后端服务器,就不会跨域报错了。

先将axios的baseURL设置为'/api',然后修改vite.config.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export default defineConfig({
plugins: [
// ...
],
server: {
port: 5173,
open: true,
proxy: {
'/api': {
target: 'http://saoke.fun:8080', // 代理地址,这里设置的地址会代替axios中设置的baseURL
changeOrigin: true, // 如果接口跨域,需要进行这个参数配置
rewrite: (path) => path.replace(/^\/api/, '')
secure: false, // 如果是https接口需要进行此配置
}
}
}
})

参考文章:一篇看懂vue如何做调试后台接口的配置和proxy的工作原理以及为什么能解决跨域

简单请求与复杂请求

满足以下条件的才是简单请求:

  • 请求方式为GETPOSTHEAD
  • 不能手动设置除AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type之外的请求头
  • Content-Type的值只限于application/x-www-form-urlencodedmultipart/form-datatext/plain
  • 不能为XMLHttpRequestUpdate注册监听器
  • 请求中没有使用readableStream对象

非简单请求就是复杂请求。

复杂请求会多发一次OPTIONS预请求,服务器返回预响应,成功后才会发送真实请求。预请求存在跨域问题。

参考文章:

简单请求和复杂请求的区别

ajax请求:简单请求&复杂请求

项目构建

要将打包好的文件按css、js进行分类,在vite.config.ts进行以下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default defineConfig({
plugins: [
// ...
],
build: {
rollupOptions: {
output: {
chunkFileNames: 'static/js/[name]-[hash].js',
entryFileNames: 'static/js/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash][extname]',
//manualChunks 两种使用形式
// manualChunks:{
// elementPlus:['element-plus']
// }
manualChunks(id) {
if (id.includes('element-plus')) {
return 'element-plus';
}
}
}
}
}
})

参考文章:

vue3打包后没有默认进行分包?立马解决⚡

Vite

Vite官方文档

Vue Router

Vue Router 官方文档

参考文章

Element Plus

Element Plus 官方文档

Pinia

Pinia官方文档

参考文章

可能用到的工具

名称 下载方式 官方文档 描述
NVM NVM下载地址 一个nodejs的版本管理工具,通过它可以安装和切换不同版本的nodejs
NRM npm install -g nrm npm的镜像管理工具,可以在npm镜像源间快速切换
v-md-editor npm i @kangc/v-md-editor -S v-md-editor官方文档 markdown编辑器
highlight.js npm install highlight.js highlight.js 官方文档 为markdown代码块添加高亮