当前位置: 首页 > news >正文

vue3基础知识

书接上文,这篇继续来学习vue3的核心语法,可以先看上一篇再来看这篇效果更好。

1. computed

computed 用于创建 计算属性,即基于其他响应式数据的值动态计算并缓存的属性。它的主要作用是优化性能和提高代码的可维护性,避免不必要的重复计算。

a. 基本语法

computed 是通过 computed() 函数创建的。在 setup() 函数中,你可以使用 computed 来定义计算属性。

import { computed, ref } from 'vue';export default {setup() {const count = ref(0);const doubledCount = computed(() => count.value * 2);return { count, doubledCount };}
};

解释:

  • count 是一个响应式数据,初始值为 0
  • doubledCount 是一个计算属性,它依赖于 count,并返回 count 的两倍。
  • count 的值发生变化时,doubledCount 会自动重新计算。

b. 计算属性的缓存

computed 的一个重要特性是 缓存。只有当计算属性依赖的响应式数据发生变化时,computed 才会重新计算,否则会直接返回上一次计算的结果。

import { computed, ref } from 'vue';export default {setup() {const count = ref(0);// 计算属性:返回 count 的平方const squaredCount = computed(() => {console.log('Computing squared count');return count.value * count.value;});return { count, squaredCount };}
};

在上面的例子中,如果你多次访问 squaredCount,你会看到 “Computing squared count” 只会在 count 改变时打印一次,而不会在每次访问时都打印,这就是 computed 的缓存机制。

c. 使用 computed 的场景

  • 计算派生状态:当你需要基于现有的响应式数据计算新的值时,computed 很有用。例如,计算一个总价、折扣后价格、过滤后的列表等。

    const price = ref(100);
    const discount = ref(0.2);const discountedPrice = computed(() => price.value * (1 - discount.value));
    
  • 优化性能:通过缓存计算结果,computed 可以避免重复计算,提升性能。

  • 条件渲染:你可以使用 computed 来做一些复杂的条件判断,而不需要在模板中使用大量的 v-if

watch 的对比

watch 用于观察响应式数据的变化,并执行副作用操作,如更新外部状态或执行异步操作。它适合处理需要副作用的场景,而 computed 更适合处理计算派生状态并返回值。

import { watch, ref } from 'vue';const count = ref(0);// 使用 watch
watch(count, (newValue) => {console.log('Count changed:', newValue);
});// 使用 computed
const doubledCount = computed(() => count.value * 2);
  • watch 用于监听 count 的变化,并在变化时执行某个副作用。
  • computed 用于计算并返回派生值,在模板中或其他地方直接使用。

2. watch

在 Vue 3 中,watch 是用于 监听响应式数据的变化 并在数据变化时执行副作用操作的 API。它特别适用于处理那些需要在数据变化时执行的逻辑,例如异步请求、数据处理、或者与外部系统交互。

watch 的基本概念

  • 监听watch 允许你监控一个或多个响应式数据的变化。
  • 副作用:当被监听的数据发生变化时,watch 会执行一个回调函数,你可以在回调中执行任何副作用操作(例如,发起异步请求、更新外部状态等)。
  • 深度监听watch 也可以深度监听对象或数组的变化,适合用于嵌套对象或数组的更新。

a. 基本语法

watch 接受三个参数:

  • 第一个参数:要观察的响应式数据或计算属性。
  • 第二个参数:回调函数,监听到数据变化时会调用它。
  • 第三个参数(可选):配置对象,可以设置一些附加选项,如 immediatedeep

最简单的使用方式

import { ref, watch } from 'vue';export default {setup() {const count = ref(0);// 监听 count 的变化watch(count, (newValue, oldValue) => {console.log(`count changed from ${oldValue} to ${newValue}`);});return { count };}
};

解释

  • watch 监听 count 的变化,每当 count 发生变化时,会调用回调函数。
  • 回调函数接收两个参数:newValue(新的值)和 oldValue(旧的值),可以在回调中执行任何副作用操作。

b. watch 的高级用法

监听多个响应式数据

你可以同时监听多个响应式数据,当它们中的任意一个变化时,回调都会被触发。

import { ref, watch } from 'vue';export default {setup() {const count = ref(0);const name = ref('Alice');// 同时监听 count 和 name 的变化watch([count, name], ([newCount, newName], [oldCount, oldName]) => {console.log(`count changed from ${oldCount} to ${newCount}`);console.log(`name changed from ${oldName} to ${newName}`);});return { count, name };}
};

深度监听对象或数组

默认情况下,watch 只会监听对象或数组的 引用变化,而不会递归监听其内部属性或元素。要实现深度监听,可以使用 deep: true 配置选项。

import { ref, watch } from 'vue';export default {setup() {const user = ref({name: 'Alice',age: 25});// 深度监听 user 对象的变化watch(user, (newValue, oldValue) => {console.log('User changed:', newValue);}, { deep: true });return { user };}
};

立即执行(immediate

watch 默认在被监听的数据发生变化时才会执行回调。如果你希望在监听开始时立即执行回调,可以使用 immediate: true 配置。

import { ref, watch } from 'vue';export default {setup() {const count = ref(0);// 监听 count 的变化,并立即执行回调watch(count, (newValue, oldValue) => {console.log(`count changed from ${oldValue} to ${newValue}`);}, { immediate: true });return { count };}
};

执行异步操作

watch 是非常适合用于执行异步操作的。比如,当某个数据变化时,你可能需要去发起一个 API 请求。

import { ref, watch } from 'vue';export default {setup() {const searchQuery = ref('');// 监听 searchQuery 的变化,发起一个异步操作watch(searchQuery, async (newQuery) => {if (newQuery) {const results = await fetch(`https://api.example.com/search?q=${newQuery}`);console.log(await results.json());}});return { searchQuery };}
};

2.1 watchEffect 的使用

watchEffectwatch 的一个变体,它会在组件挂载时立即执行,并且会自动追踪作用域内所有的响应式依赖。与 watch 主要是用于监听特定数据的变化不同,watchEffect 会自动检测你使用的所有响应式数据。

import { ref, watchEffect } from 'vue';export default {setup() {const count = ref(0);// watchEffect 会自动监听 count 的变化watchEffect(() => {console.log(`Count has changed: ${count.value}`);});return { count };}
};

watchEffectwatch 的区别:

  • watch:用于精确监听一个或多个特定的数据源,并可以对变化做出响应。
  • watchEffect:自动追踪你在其作用域内使用的所有响应式数据,并在数据变化时重新执行回调。

c. watch 的使用场景

  • 监听数据变化并执行副作用:例如,发起 API 请求、更新外部状态等。
  • 异步操作:比如在数据变化时发起一个网络请求或进行复杂的数据处理。
  • 表单验证:在表单字段变化时执行验证逻辑。
  • 数据持久化:监听数据变化并将数据持久化到本地存储或服务器。

3. props

props 是父组件向子组件传递数据的一种方式。通过 props,父组件可以将数据或参数传递给子组件,从而实现组件之间的通信。

a. 基本概念

  • 父组件 -> 子组件props 是单向数据流(单向绑定)的机制,数据只能从父组件传递到子组件,子组件不能直接修改从父组件接收的 props
  • 类型验证:Vue 允许对传递的 props 进行类型验证和默认值设置,从而确保数据的正确性。

b. 基本使用

父组件

<script lang="ts" setup name="App">import Person from './components/Person.vue'import {reactive} from 'vue'import {type Persons} from './types'let persons = reactive<Persons>([{id:'e98219e12', name:'张三', age:18},{id:'e98219e13', name:'李四', age:19},{id:'e98219e14', name:'王五', age:20}])
</script>

子组件

<script lang="ts" setup name="Person">import {defineProps} from 'vue'// types中包含了Persons类型import {type Persons} from '@/types'// 第一种写法:仅接收// const props = defineProps(['list'])// 第二种写法:接收 + 限制类型// defineProps<{list:Persons}>()// 第三种写法:接收 + 限制类型 + 指定默认值 + 限制必要性// list后如果加?表示可传可不传,不加则必须传let props = withDefaults(defineProps<{list?:Persons}>(),{list:()=>[{id:'asdasg01',name:'小猪佩奇',age:18}]})console.log(props)
</script>

通过 props,Vue 提供了一种简单而高效的组件通信方式,非常适合用于父子组件之间的数据传递和状态共享。


4. Hooks

  • 什么是hook?—— 本质是一个函数,把setup函数中使用的Composition API进行了封装,类似于vue2.x中的mixin。
  • 自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。

示例代码:
useSum.ts

import {ref,onMounted} from 'vue'export default function(){let sum = ref(0)const increment = ()=>{sum.value += 1}const decrement = ()=>{sum.value -= 1}onMounted(()=>{increment()})//向外部暴露数据return {sum,increment,decrement}
}		

useDog.ts

import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'export default function(){let dogList = reactive<string[]>([])// 方法async function getDog(){try {// 发请求let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')// 维护数据dogList.push(data.message)} catch (error) {// 处理错误const err = <AxiosError>errorconsole.log(err.message)}}// 挂载钩子onMounted(()=>{getDog()})//向外部暴露数据return {dogList,getDog}
}

App.vue

<template><h2>当前求和为:{{sum}}</h2><button @click="increment">点我+1</button><button @click="decrement">点我-1</button><hr><img v-for="(u,index) in dogList.urlList" :key="index" :src="(u as string)"> <span v-show="dogList.isLoading">加载中......</span><br><button @click="getDog">再来一只狗</button>
</template><script lang="ts">import {defineComponent} from 'vue'export default defineComponent({name:'App',})
</script><script setup lang="ts">import useSum from './hooks/useSum'import useDog from './hooks/useDog'let {sum,increment,decrement} = useSum()let {dogList,getDog} = useDog()
</script>

是的,hook 可以帮助实现模块化开发,尤其在 Vue 3 中,结合 组合式 API (Composition API) 使用时,它极大地提高了代码的可复用性和模块化程度。

分析:

  • 模块化:通过将数据获取和表单处理的逻辑分别提取到 useSumuseDog hook 中,逻辑更加清晰和模块化。
  • 复用性:这两个 hook 可以在不同的组件中复用,而无需重复编写相同的代码。
  • 解耦:不同的功能模块(如数据请求、表单验证等)被清晰地分离开来,组件只负责调用这些 hook,减少了组件内部的复杂度。

如果你能看到这里给你点个赞,如果对你有帮助的话不妨点赞支持一下~
参考:张天禹老师b站课程

http://www.lryc.cn/news/499840.html

相关文章:

  • 【Linux系统】Ubuntu 缓冲区机制
  • ChatGPT 最新推出的 Pro 订阅计划,具备哪些能力 ?
  • 数据结构理论
  • es 3期 第14节-全文文本分词查询
  • 六安市第二届网络安全大赛复现
  • Sarcomere仿人灵巧手ARTUS,20个自由度拓宽机器人作业边界
  • Django drf 基于serializers 快速使用
  • pycharm集成环境中关于安装sklearn库报错问题分析及解决
  • AI - 浅聊一下基于LangChain的AI Agent
  • 《【Linux】深入理解进程管理与 fork 系统调用的实现原理》
  • docker-compose部署skywalking 8.1.0
  • AI 总结的的 AI 学习路线
  • 离散傅里叶级数(DFS)详解
  • Java 类加载机制详解
  • 1.1 Beginner Level学习之“编写简单的发布服务器和订阅服务器”(第十一节)
  • AIQuora:开启论文写作新篇章
  • 【C语言】库函数常见的陷阱与缺陷(1):字符串处理函数
  • Mysql索引原理及优化——岁月云实战笔记
  • AGCRN论文解读
  • Python机器学习笔记(五、决策树集成)
  • Kafka单机及集群部署及基础命令
  • 如何使用 Python 实现链表的反转?
  • react跳转传参的方法
  • Scala:正则表达式
  • 【数电】常见时序逻辑电路设计和分析
  • Spring IOCAOP
  • Scala中的隐式转换
  • GESP 2024年12月认证 真题 及答案
  • C++多态性
  • PyODBC: Python 与数据库连接的桥梁