Vue中ref()函数的作用解析:为何创建状态需用ref而非直接赋值?
我无法理解在创建状态时使用ref()函数的必要性。例如VueJS文档中给出了如下示例代码:
import { ref } from 'vue' // global state, created in module scope const globalCount = ref(1) export function useCount() { // local state, created per-component const localCount = ref(1) return { globalCount, localCount } }为何不直接使用
const globalCount = 1的写法呢?
核心原因就是Vue的响应式系统需要能追踪数据的变化,而普通基本类型变量做不到这一点,具体拆解为这几个关键点:
响应式追踪的本质:Vue的响应式是基于「对象属性的读写拦截」实现的。基本类型(数字、字符串、布尔值等)不是对象,直接赋值的话Vue没法监控到你什么时候修改了值。ref会把基本类型包装成一个带
.value属性的响应式对象,当你读写.value时,Vue就能自动收集依赖、触发组件更新。普通变量的局限性:如果直接写
const globalCount = 1,首先const声明的变量不能被重新赋值;就算改成let,你修改globalCount = 2后,用到这个变量的组件完全不会感知到变化——因为Vue根本没在监控这个变量的修改,自然不会触发组件重新渲染。跨组件/模块的状态同步:例子里的
globalCount是模块级的全局状态,用ref包装后,所有导入useCount的组件拿到的都是同一个响应式对象。只要其中一个组件修改globalCount.value,所有依赖这个状态的组件都会自动更新视图。如果用普通变量,修改后其他组件拿到的还是旧值,完全做不到状态同步。
举个直观的对比:
// 用普通变量的情况,完全无响应式 let globalCount = 1; export function useCount() { function increment() { globalCount++; console.log(globalCount); // 控制台数值会变,但组件视图毫无反应 } return { globalCount, increment }; }
// 用ref的情况,响应式正常工作 import { ref } from 'vue'; const globalCount = ref(1); export function useCount() { function increment() { globalCount.value++; // 所有用到globalCount的组件都会自动更新视图 } return { globalCount, increment }; }
另外,ref不光能处理基本类型,也能处理引用类型(对象、数组),虽然引用类型我们常用reactive,但ref的优势是可以保持引用的一致性,而且在模板里使用时Vue会自动解包.value,写法更简洁。
内容的提问来源于stack exchange,提问作者FindL

