logo头像

前端从未如此简单有趣

简单梳理一下vue3【BASIC】

本文于 573 天之前发表,文中内容可能已经过时。

1. 简介

https://cn.vuejs.org/guide/introduction.html

2. 创建vue3工程【详细看vue创建前端项目的那篇】

2.1【基于 vue-cli创建】

基本和vue-cli的过程类似,只是选择的时候用vue3创建

2.2【基于vite创建】【推荐】

【官网】https://vitejs.cn/ 【可以先去学一下webpack】
image-20240722230608332
vite 是新一代前端构建工具,官网地址:https://vitejs.cn,vite的优势如下:

  • 轻量快速的热重载(HMR),能实现极速的服务启动。
  • 对 Typescript、Jsx、css 等支持开箱即用。
  • 真正的按需编译、不再等待整个应用编译完成。

2.3 步骤 【https://cn.vitejs.dev/guide/

npm create vue@latest
pnpm create vue

你还可以通过附加的命令行选项直接指定项目名称和你想要使用的模板。例如,要构建一个 Vite + Vue 项目,运行:
bash

1
2
3
4
5
6
7
8
9
10
11
# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-app -- --template vue

# yarn
yarn create vite my-vue-app --template vue

# pnpm
pnpm create vite my-vue-app --template vue

# bun
bun create vite my-vue-app --template vue

查看 create-vite 以获取每个模板的更多细节:vanilla,vanilla-ts, vue, vue-ts,react,react-ts,react-swc,react-swc-ts,preact,preact-ts,lit,lit-ts,svelte,svelte-ts,solid,solid-ts,qwik,qwik-ts。

2.4 命令行创建

image.png
image.png

3. 小结

image.png

4. VUE3核心语法

【optionsAPI】和【compositionAPI】->【vue2】和【vue3】

  • Vue2 的 API 设计是 options(配置)风格的。
  • Vue3 的API 设计是 Composition(组合)风格的。

image-20240722230742503

image-20240722230820537
image.png

5. 拉开序幕的【setup】

image-20240722230836438

  • 新的配置项
  • setup语法糖出现时机在beforecreated之前
  • setup的返回值也是一个渲染函数

【面试题】setup和vue2中的data、method有什么区别?

  • 可以同时存在
  • setup执行的比data的早(data可以拿到setup中的值,但是反过来拿不到)

6. Setup语法糖

之前的写法
image-20240722230857105
缺点是:每次都要返回数据和方法
语法糖写法
image-20240722230917215
不需要返回,setup自动给你返回;只关注数据和方法
因为最新的语法糖省去了name,则利用插件npm i vite-plugin-vue-setup-extend -D来命名
image-20240722230926349
image-20240722230936845
一般其实和文件名一样可以不写

7. ref_可以实现【基本类型】响应式数据 【让数据动起来】

vue2->都放在data中,就是响应式了
vue3->ref 和 reative 此ref不是vue2中的ref
image-20240722230949786

  • 什么时候需要value和什么时候不需要value是需要注意的点
  • 模块中不需要。JS中操作需要!

作用:
image-20240722231004312

8. reactive_创建【对象类型】【只能定义】响应式数据

image-20240722231039843

9. ref_可以实现【对象类型】响应式数据 【让数据动起来】

image-20240722231057121

需要注意的是:

  • 使用ref的时候必须加上.value去拿到值
  • ref的实现也是基于reactive实现的(底层逻辑)
  • ref既可以定义基本类型也可以对象类型

10.【ref对比reactive】

image-20240722231109444

  • 可以用volar插件【目前是官方vue插件】自动添加.value

在设置中进行设置-勾上即可
image-20240722231120776

11. toRefs 和 toRef

image-20240722231129109

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
27
28
29
<template>
<h1>hello</h1>
<h1>姓名:{{ name }}</h1>
<h1>年龄:{{ age}}</h1>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>

</template>

<script setup lang="ts">
import { reactive,toRefs } from 'vue';

let person = reactive({
name: 'John',
age:22
})
// toRefs 就是将reactive中的数据都取出来 数据还是具备响应式
let {name, age} = toRefs(person)
const changeName = () =>{
name.value = 'lisi'
}
const changeAge = () =>{
age.value += 1
}
</script>

<style>

</style>

12. computed属性【是有缓存的与vue2一致】

image-20240722231144348

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<template>
姓:<input type="text" v-model="names"><br>
名:<input type="text" v-model="ming"><br>
姓名: <h1>{{fullname}}</h1>
<button @click="changeFullname">修改全名</button>
</template>

<script setup lang="ts">
import { ref ,computed} from 'vue';

let names= ref('张三')
let ming = ref('ming')


// 只读的不可修改的
// let fullname =computed(()=>{
// return names.value + ming.value.slice(0,1).toUpperCase() + ming.value.slice(1)
// })
// 这样可读可写
let fullname =computed({

get(){
return names.value + ming.value.slice(0,1).toUpperCase() + ming.value.slice(1)
},
set(vals){
const x = vals.split('-')
names.value = x[0]
ming.value = x[1]
console.log(x);
},
})
let changeFullname = ()=>{
console.log(fullname.value);
fullname.value = 'li-si'

}
</script>

<style>

</style>

13. watch监视数据的变化

image-20240722231208833

13.1 情况一【常用】:

监视 ref 定义的【基本类型】数据:直接写数据名即可,监视的是其 value 值的改变。

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
27
<template>
<div class="person">
<h1>情况一</h1>
<h1>sum:{{ sum }}</h1>

<button @click="changeName">点我sum+1</button>
</div>
</template>

<script setup lang="ts">
import {ref,watch} from 'vue'
let sum = ref(100)

let changeName = ()=>{
sum.value += 100
}
const stopWatch = watch(sum,(newValue,oldValue)=>{
console.log(newValue,oldValue);
if(newValue>1000){
stopWatch()
}
})
</script>

<style>

</style>

13.2 情况二:

image-20240722231246468

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
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div class="person">
<h1>姓名:{{person.name }}</h1>
<h2>年龄:{{person.age}}</h2>
<button @click="changename">修改年龄</button>
<button @click="changeperson">修改person</button>

</div>
</template>

<script lang="ts" setup>
import {ref,watch} from 'vue'
let person = ref({
name:"zhangsan",
age:22,
})
const changename = () =>{
person.value.age += 1;
}
const changeperson = () =>{
// 如果是recative 就要用object.assgin
person.value = {name:"zha33ngsan", age:2342}
}
watch(person,(newValue,oldValue)=>{
console.log(newValue,oldValue);

},{deep:true,immediate:true})

</script>

<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 10px;
}
</style>

13.3 情况三:

image-20240722231313264

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
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div class="person">
<h1>姓名:{{person.name }}</h1>
<h2>年龄:{{person.age}}</h2>
<button @click="changename">修改年龄</button>
<button @click="changeperson">修改person</button>

</div>
</template>

<script lang="ts" setup>
import {ref,watch,reactive} from 'vue'
let person = reactive({
name:"zhangsan",
age:22,
})
const changename = () =>{
person.age += 1;
}
const changeperson = () =>{
// 如果是recative 就要用object.assgin
Object.assign(person,{name:"zha33ngsan", age:2342})
}
watch(person,(newValue,oldValue)=>{
console.log(newValue,oldValue);

})

</script>

<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 10px;
}
</style>

13.4 情况四【常用】【函数式】:

image-20240722231330165

结论: 监视的要是对象里面的属性,最好写成函数,注意:若是监视的是地址值,需要关注对象内部。需要开启手动深度监视

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<template>
<div class="person">
<h1>姓名:{{person.name }}</h1>
<h2>年龄:{{person.age}}</h2>
<h2>汽车:{{person.car.car1}}-{{ person.car.car2 }}</h2>
<button @click="changename">修改年龄</button>
<button @click="changeperson">修改person</button>
<button @click="changeCar1">修改car1</button>
<button @click="changeCar2">修改car2</button>
<button @click="changeAll">修改全部</button>
</div>
</template>

<script lang="ts" setup>
import {ref,watch,reactive} from 'vue'
let person = reactive({
name:"zhangsan",
age:22,
car:{
car1:'hello1',
car2:'hello2'
}
})
const changename = () =>{
person.age += 1;
}
const changeperson = () =>{
// 如果是recative 就要用object.assgin
Object.assign(person,{name:"zha33ngsan", age:2342})
}
const changeCar1 = ()=>{
person.car.car1 = 'world1'
}
const changeCar2 = ()=>{
person.car.car2 = 'world2'
}
const changeAll = ()=>{
person.car = {car1:'hello221', car2:'hello241'}
}
watch(()=>{return person.age},(newValue,oldValue)=>{
console.log(newValue,oldValue);

})
watch(()=>person.car,(newValue,oldValue)=>{
console.log(newValue,oldValue);

},{deep:true})
</script>

<style>
.person{
background-color: skyblue;
box-shadow: 0 0 10px;
border-radius: 10px;
padding: 10px;
}
</style>

13.5 情况五:

监视上述的多个数据【多个函数】
image-20240722231349625

1
2
3
watch([()=>person.name,()=>person.car.car1],(newValue,oldValue)=>{
console.log(newValue,oldValue);
},{deep:true})

【多写项目-练习】

14. watchEffect

image-20240722231409908
image-20240722231431014)

15. 标签中ref属性

image-20240722231448962

16. 回顾TS中的接口_泛型_自定义类型

image-20240722231505362

17. Props的使用

vue2【父子之间的通信】
image-20240722231606545
vue3通信
image-20240722231617003
注意点:【区别一下:的绑定和 ref的区别】
image-20240722231632037
【父子之间的传值的多种方式】
image-20240722231642392
【注意:宏函数不用引入,例如defineProps】

18. 理解生命周期【组件的一生】

概念: vue 组件实例在创建时要经历一系列的初始化步骤,在此过程中 vue 会在合适的时机,调用特定的函数,从而让开发者有机会在特定阶段运行自己的代码,这些特定的函数统称为:生命周期钩子创建、挂载、更新、销毁【每个时期都调用特定的函数】created 、 mounted 、updated 、destoyed叫法:生命周期、生命周期函数、生命周期钩子。

18.1 vue2的生命周期

创建、(前与后)(beforeCreate|Created)
挂载、(前与后)(beforeMount|Mounted)
更新、(前与后)(beforeUpdate|updated)
销毁、(前与后)(beforeDestory|destoryed)

18.2 vue3的生命周期

创建、setup —————————-> (前与后)(beforeCreate|Created)
挂载、onBeforeMount|onMounted—>(前与后)(beforeMount|Mounted)
更新、onBeforeUpdate|onUpdated—>(前与后)(beforeUpdate|updated)
卸载、onBeforeUnmount|onUnmounted—->(前与后)(beforeDestory|destoryed)
image-20240722231739326

19. 自定义hooks【mixin】【重】

image-20240722231811161

20【….】. 路由

image.png
image.png
image.png

20.1 两个注意点

image.png
路由组件:pages/views
一般组件:components
image.png

20.2 to的两种写法

image.png

20.3 路由器工作模式

【history 和 hash模式】
image.png
image.png

20.4 命名路由

image.png
image.png

20.5 嵌套路由

image.png
image.png

20.6 路由_query参数

image.png

20.7 路由_params参数

image.png

  • 必须为name
  • 参数如果可传可不传则添加?在占位的地方
  • 参数不能为数组和对象

image.png

21. 路由的Props配置

image.png
image.png
image.png
image.png

【注意】

  • 一般组件和路由组件传参的区别

22. 路由的_replace属性

  • push【默认】
  • replace【替换】

image.png

23.【编程式导航】

image.png

出了routerlink进行跳转还有编程式路由导航

image.png

  • 什么时候进行编程式导航
    • 需要再某个条件下跳转

image.png

24. 路由重定向

image.png

25. Pinia【对比VUE2中vuex】【集中式状态数据管理】

【redux vuex pinia】
image.png
是vue的最新的状态管理工具,是vuex的替代品
image.png

26. 手动添加pinia

官网:https://pinia.vuejs.org/zh/introduction.html

  1. 使用vite创建一个新的vue3项目
  2. 安装pinia到项目中

用vite安装时注意node的版本

26.1 案例

image.png
image.png
lovetalk.vue

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
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div class="lovetalk">
<button @click="getLoveTalk">hello</button>
<ul>
<li v-for="item in newsList" :key="item.id">{{ item.title }}</li>
</ul>
</div>
</template>

<script lang="ts" setup>
import { reactive } from 'vue';
import axios from 'axios';
import { nanoid } from 'nanoid';
const newsList = reactive([
{ id: '12423421', title: 'hel123' },
{ id: '1224231', title: 'h424el123' },
{ id: '1242341', title: 'he4243l123' },
]);
async function getLoveTalk() {
// 下面的写法:连续解构赋值 + 重命名
let {
data: { content:title },
} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json');
// nanoid 可以随机生成ID
let obj = { id: nanoid(),title};
console.log(obj);
newsList.unshift(obj);
}
</script>

<style>
.lovetalk {
background-color: skyblue;
box-shadow: 0 0 10px;
border: 1px solid black;
}
</style>

count.vue

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
27
28
29
30
31
32
<template>
<div class="count">
<h2>当前求和为:{{sum}}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减 </button>
</div>
</template>

<script setup lang="ts">
import {ref} from 'vue'
let sum = ref(1)
let n = ref(1)
function add(){
sum.value += n.value
}
function minus(){
sum.value -= n.value
}
</script>

<style>
.count {
background-color: skyblue;
box-shadow: 0 0 10px;
border: 1px solid black;
}
</style>

【注意】:引入了axios和nanoid【随机生成id】

26.2 搭建pinia环境

npm i pinia
image.png

26.3 存取读取数据

image.png
image.png

27. 修改数据的三种方式

image.png
image.png

28. storeToRefs【只关注store数据】【对数据进行解构操作】

image.png

29. getters

image.png
对数据的加工

30. $subscribe

image.png
image.png

31. store的组合式写法【推荐】

image.png

32. 组件通信_方式1_props 【父子】

image.png
image.png

33. 组件通信_方式2_自定义事件【子传父】

image.png

34. 组件通信_方式3_mitt【任意组件通信】

  • pubsub
  • $bus
  • mitt

image.png
image.png

35. 组件通信_方式4_v-model【通常用于表单】

作用在组件和html的方式【底层】
image.png
image.png
image.png

36. 组件通信_方式5_$atters【祖孙之间通信】【打扰了中间人】

image.png
image.png

37. 组件通信_方式6_$refs-$parent【父->子|子->父】image.png

image.png

38. 组件通信_方式7_provide_inject【提供-注入】【向后代之间通信】【零打扰】

image.png

39. 插槽

39.1 默认插槽

image.png

39.2 具名插槽【template 中 v-solt & #】【重】【动态的摆放】

image.png
可以用【#s1 、#s2代替v-slot】

39.3 作用域插槽

image.png

40. 总结

image-20240722232101767

41. 其他API

41. shallowRef 和 shallowReactive

image.png
image.png

41.2 readonly 和 shallowReadonly

image.png
image.png

41.3 roRaw 和 markRow

image.png
image.png

41.4 customRef

image.png
image.png
image.png

41.5 Teleport【转移】

image.png

41.6 Suspense

image.png

41.7 全局api到应用对象

image.png

41.8 其他【非兼容性改变】

image.png

41.9 面试题:vue3相比vue2做了哪些改变?

https://v3-migration.vuejs.org/zh/breaking-changes/
image-20240722232201592