Vue3

cccs7 Lv5

认识 Vue3

选项式 API 与 组合式 API

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
export default {
data(){
return {
count:0
}
},
methods:{
addCount(){
this.count++
}
}
}
</script>
1
2
3
4
5
<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = ()=> count.value++
</script>

特点:

  1. 代码量变少
  2. 分散式维护变成集中式维护

Vue 3的优势

image-20230722174257243

Vue3 项目目录以及关键文件

image-20230722174526947

组合式 API

setup 选项

setup 选项的写法和执行的时机

写法

1
2
3
4
5
6
7
8
9
10
<script>
export default {
setup(){

},
beforeCreate(){

}
}
</script>

执行时机

在beforeCreate钩子之前执行

image.png

setup 中写代码的特点

setup 函数中写的数据和方法 需要在 末尾以对象的方式 return ,才能给模板使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
export default {
setup(){
const message = 'this is message'
const logMessage = ()=>{
console.log(message)
}
// 必须return才可以
return {
message,
logMessage
}
}
}
</script>

<script setup> 语法糖

script 标签添加 setup 标记,不需要再写导出语句,默认会添加 导出语句

1
2
3
4
5
6
<script setup>
const message = 'this is message'
const logMessage = ()=>{
console.log(message)
}
</script>

reactive 和 ref 函数

reactive

接收 对象类型数据的参数 传入 并返回一个响应式对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup>
// 导入
import { reactive } from 'vue'
// 执行函数 传入参数 变量接收
const state = reactive({
msg:'this is msg'
})
const setSate = ()=>{
// 修改数据更新视图
state.msg = 'this is new msg'
}
</script>

<template>
{{ state.msg }}
<button @click="setState">change msg</button>
</template>

ref

接收简单类型 或 对象类型的 数据传入,并返回一个 响应式对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script setup>
// 导入
import { ref } from 'vue'
// 执行函数 传入参数 变量接收
const count = ref(0)
const setCount = ()=>{
// 修改数据更新视图必须加上.value
count.value++
}
</script>

<template>
<button @click="setCount">{{count}}</button>
</template>

修改数据更新视图 必须要加上 .value ,在模板中不用

reactive 对比 ref

  1. 都是用来 生成响应式数据的
  2. 不同点:
    1. reactive 不能处理简单类型数据
    2. ref 参数支持类型更好,但是必须通过 .value 做访问修改
    3. ref 函数内部的使用依赖于 reactive 函数
  3. 在实际工作中的推荐
    • 推荐使用 ref,减少记忆负担

computed

计算属性基本思想和 Vue2 基本一致,组合式API 只是修改了 API写法

以下是在 Vue 3 中使用 computed 函数的一些关键点:

  • 基本用法

    computed函数用于定义计算属性。它是一个只读属性,不能直接修改

  • 返回值:在计算属性中,需要包含一个 return语句,以指定基于依赖关系应该计算的值

    • 在使用 <script setup> 的情况下,可以省略 return 关键字来定义计算属性。这是因为 <script setup> 会自动将计算属性的最后一个表达式作为返回值
  • 同步操作:计算属性是同步的,不能用于异步操作

  • 依赖关系:计算属性可以引用组件内的其他数据属性或计算属性

1
2
3
4
5
6
7
8
9
10
11
12
13
<script setup>
// 导入
import {ref, computed } from 'vue'
// 原始数据
const count = ref(0)
// 计算属性
const doubleCount = computed(()=>count.value * 2)

// 原始数据
const list = ref([1,2,3,4,5,6,7,8])
// 计算属性list
const filterList = computed(item=>item > 2)
</script>

watch

watch 函数是 Vue 3 组合式 API 中的一部分,用于监视响应式状态的变化并执行相应的操作。与 computed 函数不同,watch 函数可以监视任何响应式数据,包括计算属性、ref 和 reactive 对象等。

以下是在 Vue 3 中使用 watch 函数的一些关键点:

  • Basic Usage: watch 函数接受两个参数:第一个参数是要监视的响应式数据源,可以是一个 ref、reactive 对象或计算属性等;第二个参数是回调函数,用于在数据变化时执行相应的操作
  • Immediate Option: 可以通过传入 immediate: true 选项来强制在创建侦听器时立即执行一遍回调函数
  • Deep Option: 可以通过传入 deep: true 选项来强制转成深层侦听器,以侦听嵌套对象的变化
  • Stop Function: watch 函数返回一个停止函数,可以用于停止侦听器的执行

以下是在 Vue 3 中使用 watch 函数的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { ref, watch } from 'vue'

export default {
setup() {
const count = ref(0)

watch(count, (newValue, oldValue) => {
console.log(`count is changed from ${oldValue} to ${newValue}`)
})

return {
count
}
}
}

在这个例子中,watch 函数监视 count ref 的变化,并在每次变化时打印出新旧值。

侦听单个数据

1
2
3
4
5
6
7
8
9
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
})
</script>

侦听多个数据

侦听多个数据,第一个参数可以改写为 数组的写法

1
2
3
4
5
6
7
8
9
10
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
const name = ref('cp')
// 2. 调用watch 侦听变化
watch([count, name], ([newCount, newName],[oldCount,oldName])=>{
console.log(`count或者name变化了,[newCount, newName],[oldCount,oldName])
})
</script>

immediate

在侦听器创建时立即触发 回调,响应式数据变化之后继续执行回调

1
2
3
4
5
6
7
8
9
10
11
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const count = ref(0)
// 2. 调用watch 侦听变化
watch(count, (newValue, oldValue)=>{
console.log(`count发生了变化,老值为${oldValue},新值为${newValue}`)
},{
immediate: true
})
</script>

deep

通过 watch 监听的 ref 对象默认是 浅层侦听 的,直接修改 嵌套的对象属性不会触发 回调执行,需要开启 deep

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
<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({ count: 0 })
// 2. 监听对象state
watch(state, ()=>{
console.log('数据变化了')
})
const changeStateByCount = ()=>{
// 直接修改不会引发回调执行
state.value.count++
}
</script>

<script setup>
// 1. 导入watch
import { ref, watch } from 'vue'
const state = ref({ count: 0 })
// 2. 监听对象state 并开启deep
watch(state, ()=>{
console.log('数据变化了')
},{deep:true})
const changeStateByCount = ()=>{
// 此时修改可以触发回调
state.value.count++
}
</script>

生命周期函数

选项式对比组合式

image-20230723100451146

生命周期函数基本使用

  1. 导入生命周期函数
  2. 执行生命周期函数,传入回调
1
2
3
4
5
6
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
// 自定义逻辑
})
</script>

执行多次

生命周期函数执行多次的时候,会按照顺序依次执行

1
2
3
4
5
6
7
8
9
10
<scirpt setup>
import { onMounted } from 'vue'
onMounted(()=>{
// 自定义逻辑
})

onMounted(()=>{
// 自定义逻辑
})
</script>

父子通信

父传子

基本思想

  1. 父组件中给子组件绑定属性
  2. 子组件内部通过 props 选项绑定接受数据
image-20230723101017610

子传父

基本思想

  1. 父组件中给 子组件标签 通过 @ 绑定事件
  2. 子组件内部 通过 emit 方法 触发事件
image-20230723101139345

模板引用

通过 ref 标识获取真实的 dom 对象 或者 组件实例对象

基本使用

实现步骤

  1. 调用 ref 函数生成一个 ref 对象
  2. 通过 ref 标识 绑定一个 ref 对象到标签
image-20230723101338274

defineExpose

默认情况下 <script setup> 语法糖下 组件内部的属性和方法是不开放给父组件访问的,可以通过 defineExpose 编译宏指定哪些数据和方法 可以访问

说明: 指定 testMessage 属性可以被访问到

image-20230723101552300

Provide 和 inject

作用与场景

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信

image-20230723101735758

跨层传递普通数据

实现步骤:

  1. 顶层组件通过 provide 函数提供数据
  2. 底层组件通过 inject 函数接收数据
image-20230723101850320

跨层传递响应式数据

在调用 provide 函数时,第二个参数设置为 ref 对象

image-20230723101952209

跨层传递方法

顶层组件可以向底层组件传递方法,底层组件调用方法修改顶层组件 的数据

image-20230723102032852

defineOptions

背景说明:

<script setup> 之前,如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。

但是用了 <script setup> 后,就没法这么干了 setup 属性已经没有了,自然无法添加与其平级的属性。


为了解决这一问题,引入了 defineProps 与 defineEmits 这两个宏。但这只解决了 props 与 emits 这两个属性。

如果我们要定义组件的 name 或其他自定义的属性,还是得回到最原始的用法——再添加一个普通的 <script> 标签。

这样就会存在两个<script>标签。让人无法接受。


所以在 Vue 3.3 中新引入了 defineOptions 宏。顾名思义,主要是用来定义 Options API 的选项。可以用 defineOptions 定义任意的选项, props, emits, expose, slots 除外(因为这些可以使用 defineXXX 来做到)

1
2
3
4
5
6
7
<script setup>
defineOptions ({
name: 'xxx',
inheritAttrs: false,
//xxxxx
})
</script>

defineModel

在 Vue 3 中,自定义组件上使用 v-model ,相当于传递一个 modelValue 属性,同时触发 update:modelValue 事件

image-20230723103114805

我们需要先定义 props , 再定义 emits ,其中有许多的重复代码。如果需要修改此值,还需要手动调用 emit 函数

所以 defineModel 诞生

1
2
3
4
<script setup>
const modelValue = defineModel()
modelVale.value++
</script>

生效需要配置 vite.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
script: {
defineModel: true
}
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
  • Title: Vue3
  • Author: cccs7
  • Created at: 2023-07-22 11:01:22
  • Updated at: 2023-07-23 10:33:38
  • Link: https://blog.cccs7.icu/2023/07/22/Vue3/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments