VUE从入门到精通二:ref、reactive、computed计算属性、watch监听、组件之间的通信

目录

一、ref、reactive创建响应式对象

1、ref()

2、reactive()

3、ref和reactive的区别

二、computed计算属性

1、什么是计算属性computed

2、计算属性computed和函数方法的区别

3、计算属性computed的优势

三、watch监听函数

1、什么是watch?

2、基本语法

3、深度监听

4、使用字符串路径监听嵌套属性

5、动态添加watcher

6、立即执行watcher

7、一次性监听

8、停止watcher

9、watch vs watchEffect监听方式对比

10、watch与computed的区别

11、watch vue3与vue2的对比

12、性能优化建议

13、完整示例

四、组件之间的通信

1、Props(父传子)

 2、Emit(子传父)

3、Provide / Inject(祖先传后代)

4、Vuex全局事件总线(状态管理)


一、ref、reactive创建响应式对象

1、ref()

在Vue 3中,ref是一个函数,用于创建一个响应式引用。它可以定义基本数据类型(如字符串、数字、布尔值等)。虽然也可用于创建对象和数组,但更推荐使用reactive。使用ref时,需要通过.value属性来访问和修改数据。

const copy_address_type = ref('')  // 地址同步文案
const exemption_fax = ref(0.00) //消费税
const exemption_no_show = ref(false)

2、reactive()

reactive它更适用于创建对象和数组。reactive会将整个对象或数组转换为响应式的,这意味着对象或数组中的每个属性都会被代理。

const form_data = reactive({id: '', type:'', first_name: '',last_name: '',email: '',phone: '',institution: '',postcode: '',address: '',city: '',state_input: '',state: '',country: '', set_copy_address: ''
})
const country_data = ref([])

3、ref和reactive的区别

a.数据类型:ref适用于基本数据类型及复杂对象,而reactive主要用于复杂对象及嵌套数据结构。

b.访问方式:ref通过.value属性访问,而reactive直接通过属性访问。

c.响应性追踪:ref追踪单个独立的引用,reactive追踪整个对象及其内部属性。

d.可变性:ref的引用值可以重新赋值,而reactive对象本身是不可重新赋值的,只能修改其内部属性。

二、computed计算属性

1、什么是计算属性computed

computed‌是用于基于其他响应式数据动态计算新数据的工具,具有缓存机制,仅在依赖数据变化时重新计算,可显著提升性能,如果依赖的数据不变化,computed永远不会改变。

核心特性

‌依赖缓存‌:仅在依赖数据(如响应式引用)变化时重新计算,避免重复执行。 ‌

‌声明式定义‌:通过computed函数定义,支持复杂逻辑复用。 ‌

‌性能优化‌:减少模板渲染时的计算开销,提升渲染效率。

<template><div>{{ double }}</div><input v-model="count" />
</template><script setup>import { ref, computed } from 'vue';const count = ref(1);const double = computed(() => count.value * 2);
</script>

上面的例子,当文本框的count发生改变时,double数据也会发生变化。

2、计算属性computed和函数方法的区别

function doubleFunc(count) {let double = count * 2return double}

若我们将同样的函数定义为一个方法而不是计算属性,两种方式在结果上确实是完全相同的,然而,不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books 不改变,无论多少次访问 double 都会立即返回先前的计算结果,而不用重复执行doubleFunc函数。

这也很好的解释了下面的计算属性永远不会更新,因为 Date.now() 并不是一个响应式依赖,它不会变化。

const now = computed(() => Date.now())

3、计算属性computed的优势

A.简洁高效:通过计算属性computed可以简洁高效地实现基于其他属性计算的属性,避免了重复计算和代码冗余。

B.响应式更新:计算属性computed会自动响应依赖的变化而更新,保持界面和数据的同步。

C.缓存机制:计算属性computed会缓存计算结果,只有在相关依赖发生改变时才会重新计算,提高了性能和效率。

三、watch监听函数

1、什么是watch?

watch是Vue中用于监听数据的变化并执行相应的操作。

当被监听的数据发生变化时,会触发一个回调函数,我们可以在这个回调函数中执行一些逻辑操作。

watch适用于需要在数据变化时执行异步或较复杂的场景。

2、基本语法

export default {setup() {const count = ref(0);watch(count, (newVal, oldVal) => {console.log(`count changed from ${oldVal} to ${newVal}`);});return { count,};}
};

3、深度监听

对于对象或数组的监视,默认情况下,Vue不会递归地监视对象内部属性的变化。如果你需要深度监视,vue2中可以设置deep选项为true。Vue3中你可以使用watchEffect或者watch函数,并通过提供一个回调函数来访问和监视这些深层属性。

Vue2深度监听

export default {data() {return {user: {name: '张三',age: 25}}},watch: {user: {handler(newValue, oldValue) {console.log('user对象变化了', newValue, oldValue)},deep: true // 开启深度监听}}
}

VUE3深度监听

import { ref, watchEffect } from 'vue';const obj = ref({nested: {prop: 'value'}
});watchEffect(() => {console.log(obj.value.nested.prop); // 访问深层属性
});// 更新深层属性时,控制台将显示新值
obj.value.nested.prop = 'new value';

深度监听原理:

    4、使用字符串路径监听嵌套属性

    const city = computed(() => state.user.address.city);
    watch(city, (newValue, oldValue) => {console.log(`City changed from ${oldValue} to ${newValue}`);
    });

    5、动态添加watcher

    如果你需要在组件的生命周期内动态添加watcher,可以使用Vue实例的$watch方法

    export default {mounted() {this.$watch('message', (newVal, oldVal) => {console.log(`message changed from ${oldVal} to ${newVal}`);});}

    6、立即执行watcher

    默认情况下,watch只会在数据变化时触发回调函数,而不会在初始化时执行。

    如果需要在初始化时就执行一次回调函数,可以设置immediate: true。

    watch(() => obj.value.nested.prop, // 监视深层属性(newValue, oldValue) => {console.log(`Prop changed from ${oldValue} to ${newValue}`);},{ immediate: true } // 立即执行一次回调
    );

    7、一次性监听

    可以使用once: true选项来设置只监听一次变化
    // 使用 once 选项让 watch 只监听一次

    watch(count, (newValue, oldValue) => {console.log(`Count changed from ${oldValue} to ${newValue}`);
    }, { once: true });

    8、停止watcher

    当你使用$watch方法添加watcher时,可以通过返回的取消函数来停止watcher:

    const count = ref(0);
    let stopWatch;
    stopWatch = watch(count, (newVal, oldVal) => {console.log(`Count changed from ${oldVal} to ${newVal}`);
    });
    onUnmounted(() => {stopWatch(); // 确保在组件卸载时停止watcher
    });

    9、watch vs watchEffect监听方式对比

    watch需要明确指定要监听的数据源,而watchEffect会自动收集其内部所使用的所有响应式依赖。
    watch可以访问被监听状态的前一个值和当前值,而watchEffect只能访问当前值。
    watchEffect会在组件初始化时立即执行一次,相当于设置了immediate: true的watch。

    const count = ref(0)
    const message = ref('Hello')// watchEffect会自动监听回调函数中使用的所有响应式数据
    watchEffect(() => {console.log(`count: ${count.value}, message: ${message.value}`)
    })
    // 等价于以下watch写法
    watch([count, message], ([newCount, newMessage]) => {console.log(`count: ${newCount}, message: ${newMessage}`)
    }, { immediate: true })

    10、watch与computed的区别

    特性

    watch

    computed

    用途

    监听数据变化并执行副作用

    计算并返回新值

    缓存

    无缓存机制

    有缓存,只在依赖变化时重新计算

    返回值

    无返回值

    有返回值

    适用场景

    数据变化时执行异步操作或复杂逻辑

    依赖其他数据计算出新值

    执行时机

    数据变化后执行

    依赖变化时立即计算新值

    11、watch vue3与vue2的对比

    // Vue 2 选项式 API
    watch: {user: {handler(newVal) { /*...*/ },deep: true}
    }// Vue 3 组合式 API(更灵活)
    const user = reactive({/*...*/})
    watch(user, (newVal) => {/*...*/}, { deep: true })

    12、性能优化建议

    避免过度深度监听:只对必要对象开启
    使用精确监听路径

    watch(() => user.address.city, (newCity) => {...})及时清理监听
    const stopWatch = watch(...)
    onUnmounted(stopWatch) // 组件卸载时停止监听

    13、完整示例

    const user = reactive({id: 1,info: {name: '张三',address: {city: '北京',street: '朝阳区'}}
    })// 深度监听整个用户对象
    watch(user,(newUser) => {console.log('用户信息已修改,自动保存...')autoSave(newUser)},{ deep: true, immediate: true }
    )// 精确监听城市变化
    watch(() => user.info.address.city,(newCity) => {updateMap(newCity)}
    )

    四、组件之间的通信

    1、Props(父传子)

    父组件通过props向下传递数据给子组件。这是最常见的父子组件通信方式。

    父组件

    <template><ChildComponent :message="parentMessage" />
    </template><script setup>
    import ChildComponent from './ChildComponent.vue';
    import { ref } from 'vue';const parentMessage = ref('Hello from parent');
    </script>

    子组件

    <template><div>{{ message }}</div>
    </template><script setup>
    defineProps({message: String
    });
    </script>

     2、Emit(子传父)

    子组件通过emit向父组件发送事件和数据。

    子组件

    <template><button @click="sendMessage">Send Message</button>
    </template><script setup>
    import { defineEmits } from 'vue';const emit = defineEmits(['updateMessage']);function sendMessage() {emit('updateMessage', 'Hello from child');
    }
    </script>

    父组件

    <template><ChildComponent @updateMessage="handleMessage" />
    </template><script setup>
    import ChildComponent from './ChildComponent.vue';
    import { ref } from 'vue';const childMessage = ref('');
    function handleMessage(msg) {childMessage.value = msg;
    }
    </script>

    3、Provide / Inject(祖先传后代)

    provide和inject可以用于跨多级组件传递数据,非常适合在深层嵌套的组件结构中通信。

    祖先组件

    <template><DescendantComponent />
    </template><script setup>
    import { provide, ref } from 'vue';
    import DescendantComponent from './DescendantComponent.vue';const message = ref('Hello from ancestor');
    provide('message', message); // 提供数据给后代组件使用
    </script>

    后代组件

    <template><div>{{ message }}</div>
    </template><script setup>
    import { inject } from 'vue';
    const message = inject('message'); // 注入数据从祖先组件接收数据
    </script>

    4、Vuex全局事件总线(状态管理)

    对于更复杂的应用,可以使用Vuex进行状态管理,实现任意跨组件的通信。Vuex提供了一个集中存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

    使用:

    第一步:#src/store/index.js 创建vuex模块文件,开始使用vuex

    在一个模块化的打包系统中,您必须显式地通过 `Vue.use()` 来安装 Vuex:

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)

    第二步:#实例化Vuex.store ,并进行相关配置

    export default new Vuex.Store({state: {//存储状态},mutations: {//变更store中的状态},actions: {//类似于mutation,//action提交的是mutation,而不是直接变更状态//action可以包含异步操作},getters:{//state的派生状态  },modules: {//将store分割成模块}
    })

    第三步:#在main.js中,vue实例对象中注册store

    import store from './store'
    new Vue({store,render: h => h(App)
    }).$mount('#app')

    每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)

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

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

    相关文章

    构建AI智能体:十二、给词语绘制地图:Embedding如何构建机器的认知空间

    我们理解“苹果”这个词&#xff0c;能联想到一种水果、一个公司、或者牛顿的故事。但对计算机而言&#xff0c;“苹果”最初只是一个冰冷的符号或一串二进制代码。传统的“One-Hot”编码方式&#xff08;如“苹果”是[1,0,0,...]&#xff0c;“香蕉”是是[0,1,0,...]&#xff…

    突击复习清单(高频核心考点)

    &#x1f512; 锁的作用与使用&#xff08;synchronized vs ReentrantLock&#xff09; 面试官为什么问&#xff1a;考察你对并发编程基础的掌握程度。 速记答案&#xff1a; 作用&#xff1a;保证线程安全&#xff0c;解决多线程环境下对共享资源访问的数据不一致问题。 synch…

    2025年视频大模型汇总、各自优势及视频大模型竞争焦点

    文章目录一、国际主流视频大模型1. OpenAI Sora Turbo2. Google Veo 33. Runway Gen-3 Alpha二、国内主流视频大模型1. 快手可灵AI2. 爱诗科技PixVerse V33. 阿里巴巴通义万相2.14. 生数科技Vidu Q15. 字节跳动即梦AI三、核心趋势与竞争焦点一、国际主流视频大模型 1. OpenAI …

    Android - 用Scrcpy 将手机投屏到Windows电脑上

    工作生活当中&#xff0c;常常需要操作手机&#xff0c;但是用手操作显然不如用键盘快。 再一个&#xff0c;你看视频的时候&#xff0c;想做一些笔记&#xff0c;那你也得截个图啦之类的&#xff0c; 那如果直接在电脑上能看也是非常方便的&#xff0c;这都需要投屏手机到电…

    AlmaLinux 上 Python 3.6 切换到 Python 3.11

    在 AlmaLinux 上将默认的 Python 3.6 升级或切换到 Python 3.11 是一个常见的需求。请注意&#xff0c;直接替换系统自带的 Python 3.6 是非常危险的&#xff0c;因为许多系统工具&#xff08;如 yum/dnf 包管理器&#xff09;都依赖于它&#xff0c;盲目删除或修改可能会导致系…

    基于RBF-GA的铝/镁异材FSLW工艺参数优化研究

    课题&#xff1a;基于RBF-GA的铝/镁异材FSLW工艺参数优化研究 1. 引言 (Introduction) 研究背景与意义&#xff1a; 轻量化需求&#xff1a;铝&#xff08;Al&#xff09;和镁&#xff08;Mg&#xff09;合金是航空航天、新能源汽车等领域实现轻量化的关键材料。实现二者的可靠…

    【Prometheus】Prometheus监控Docker实战

    &#x1f47b;创作者&#xff1a;丶重明 &#x1f47b;创作时间&#xff1a;2025年8月23日 &#x1f47b;擅长领域&#xff1a;运维 目录前言什么是Prometheus和cAdvisorPrometheuscAdvisor部署操作部署cAdvisor部署Prometheus指标说明cpu相关指标内存相关指标磁盘相关指标网络…

    2.7 提示词调优编码实战(二)

    目录 四,提示词模版优化 - 格式化 4.1 代码示例 4.2 任务描述 4.3 模型输出格式化 4.4 用户输入 4.5 输出结果 四,提示词模版优化 - 格式化 在简单提示词的基础上,我们对提示词模版中各部分进行格式化。包括任务描述增加了相应的字段。 同时对输出增加了更多的定义和…

    Kafka如何保证「消息不丢失」,「顺序传输」,「不重复消费」,以及为什么会发生重平衡(reblanace)

    前言 上一篇文章总结了kafka为什么快&#xff0c;下面来总结一下&#xff0c;kafka高频的常见的问题。内容有点多&#xff0c;全部看完需要有一定的耐心。 kafka如何保证消息不丢失 Producer端 要保证消息不丢失&#xff0c;第一点要做的就是要保证消息从producer端发送到了…

    原子操作汇编实现:原理、流程与代码解析

    &#x1f52c; 原子操作汇编实现&#xff1a;原理、流程与代码解析 引用&#xff1a;VC/C Intel x86 内联汇编实现 “Interlocked” 原子变量各种操作 &#x1f31f; 引言&#xff1a;原子操作的重要性 在多线程编程中&#xff0c;原子操作是确保数据一致性的关键机制。本文…

    【WRF理论第十九期】内陆湖泊、水体的处理方式

    目录 WRF 模型中湖泊模拟概述 湖泊模型(Lake Model)集成 新增湖泊数据支持(如 WUDAPT + MODIS) LAKE_DEPTH Noah-MP + 湖泊模型联合使用 namelist.input 配置说明 WRF 代码更新 参考 论坛-WRF 湖泊模型(WRF-Lake model)与 SST 更新 WRF 模型中湖泊模拟概述 湖泊模型(La…

    【渗透测试】SQLmap实战:一键获取MySQL数据库权限

    注&#xff1a;所有技术仅用于合法安全测试与防御研究&#xff0c;未经授权的攻击行为属违法犯罪&#xff0c;将承担法律责任。一、SQLmap常规用法注意存放路径&#xff1a;C:\Users\neo\AppData\Local\sqlmap\output1、列出详细过程和数据库列表sqlmap -u http://192.168.61.2…

    LeetCode 第464场周赛 第三天

    1. 3658 奇数和与偶数和的最大公约数&#xff08;欧几里得&#xff09; 链接&#xff1a;题目链接 题解&#xff1a; 题解时间复杂度O(logmin(a, b))&#xff1a; 获得前n个奇、偶数的总和&#xff0c;由于数列为等差数列&#xff0c;等差数列和公式&#xff1a;(a1 an) * n …

    IntelliJ IDEA 集成 ApiFox 操作与注解规范指南

    一、IDEA装入Apifox 1.安装Apifox Helper 说明:在 IntelliJ IDEA 中安装 ApiFox Helper 插件。 2.打开Apifox 说明:点击 设置,在菜单中选择 API访问令牌。在弹出的窗口中输入任意名称,并选择令牌的有效期(为了方便,我这里选择了 无期限)。生成令牌后,由于 令牌只能复…

    C++---双指针

    在C编程中&#xff0c;双指针算法是一种高效的解题思路&#xff0c;其核心是通过设置两个指针&#xff08;或索引&#xff09;遍历数据结构&#xff08;如数组、链表、字符串等&#xff09;&#xff0c;利用指针的移动规则减少无效操作&#xff0c;从而将时间复杂度从暴力解法的…

    【LLM】GLM-4.5模型架构和原理

    note 文章目录note一、GLM-4.5模型二、Slime RL强化学习训练架构Reference一、GLM-4.5模型 大模型进展&#xff0c;GLM-4.5技术报告,https://arxiv.org/pdf/2508.06471&#xff0c;https://github.com/zai-org/GLM-4.5&#xff0c;包括GLM-4.5&#xff08;355B总参数&#xff…

    LLM 中增量解码与模型推理解读

    在【LLM】LLM 中 token 简介与 bert 实操解读一文中对 LLM 基础定义进行了介绍&#xff0c;本文会对 LLM 中增量解码与模型推理进行解读。 一、LLM 中增量解码定义 增量解码&#xff08;Incremental Decoding&#xff09;是指在自回归文本生成过程中&#xff0c;模型每次只计…

    1.Spring Boot:超越配置地狱,重塑Java开发体验

    目录 一、Spring框架&#xff1a;伟大的基石 历史背景与挑战 Spring的革命性贡献 新的挑战&#xff1a;配置地狱 二、Spring Boot&#xff1a;约定大于配置的革命 四大核心特性 1. 快速创建独立应用 2. 自动配置&#xff1a;智能化的魔法 3. 起步依赖&#xff1a;依赖管…

    assert使用方法

    assert 是 Python 中用来进行 调试 和 验证 的一个关键字&#xff0c;它用于测试一个 条件表达式 是否为真。如果条件为假&#xff0c;assert 会抛出一个 AssertionError 异常&#xff0c;通常带有错误信息。语法&#xff1a;assert condition, "Error message"condi…