Vue.js 的响应式设计是其核心特性之一,它允许在数据发生变化时自动更新相关的UI视图。Vue通过实现数据绑定机制,确保当应用状态(即组件内部的数据)发生变化时,视图会立即反映出这些变化,而不需要手动操作DOM。
Vue实现响应式系统的主要方式如下:
- Vue 2.x: Vue 2使用了
Object.defineProperty()
这个JavaScript原生方法来实现数据劫持。对于每个组件实例中观察到的data对象的所有属性,Vue都会遍历并利用defineProperty
将其转换为getter和setter。这样,每当尝试读取或修改这些属性时,Vue都能在其背后执行一些额外的操作,如依赖收集(Dependant Collection)和派发更新(Change Notification)。 - Vue 3.x: Vue 3则采用了更现代的ECMAScript Proxy API来实现响应式系统。Proxy可以提供更全面、透明的方式来拦截对象的各种操作,包括属性读写、删除、枚举等。Vue 3通过创建一个代理对象来跟踪所有对源对象的访问和修改,并在此过程中进行依赖追踪和通知更新。
要实现一个响应式需要满足以下三点:
- 被监控的函数: render,computed,watchEffect,watch
- 函数运行期间用到了响应式数据
- 响应式数据变化会导致函数重新运行
下面是几个响应式的例子以供联系:
//父组件
<template>
<child :count=count/>
<button onclick='count++'></button>
</template>
<script setup>
let count = ref(0)
</script>
//子组件
<template>
<div>{{count}}</div>
</template>
<script setup>
//子组件设置了一个Props响应式变量
const props = defineProps({
count:Number
})
</script>
const doubleCount = ref(props.count * 2)
//× doubleCount是响应式,但不能根据props.count变动而变动
const doubleCount = ref(0)
watchEffect(()=>{
doubleCount.value = props.count * 2
})
//√
function useDouble(count) {
const doubleCount = ref(count*2)
watchEffect(()=>{
doubleCount.value = count * 2
})
return doubleCount
}
const doubleCount = useDouble(Props.count)
//× 需要watchEffect监视的变量是响应式
const doubleCount = computed(()=>props.count*2)
//√
function useDouble(count) {
const doubleCount = computed(()=>count*2)
return doubleCount
}
const doubleCount = useDouble(Props.count)
//× 同3