# Vue 2 中的响应式
在 Vue 2 中,我们通常使用如下的方式声明一个响应性的数据。如果希望在 view 层跟踪数据的变化,需要在 data
函数中,将变量作为对象的属性返回。
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
data() {
return {
title: "Hello, Vue!"
};
}
};
</script>
在 Vue 2 内部,为了追踪每个数据的变化,Vue 会解析每个属性,并使用 Object.defineProperty()
方法创建 getters
和 setters
。
# Vue 3 中的响应式
由于 Composition API 的提出,我们定义数据的方式也随之发生改变。在下面的例子中,我们定义了一个 title
变量,但改变 title
的值,并不会引起视图层的变化。
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
setup() {
let title = "Hello, Vue 3!";
setTimeout(() => {
title = "THIS IS A NEW TITLE";
}, 5000);
return { title };
}
};
</script>
这是因为 Composition API 要求我们在 setup
完成程序的全部逻辑,在 setup
中既有需在在视图层使用的变量,又有为逻辑代码服务的变量,而后者并不需要被 Vue 时刻监听。所以,在 setup
中直接声明变量不会自动被标记为响应性数据。
# reactive
要为 JavaScript 对象创建响应式状态,可以使用 reactive
方法:
<template>
<h1>{{ data.title }}</h1>
</template>
<script>
export default {
setup() {
const data = reactive({
title: "Hello, Vue 3!"
})
setTimeout(() => {
data.title = "THIS IS A NEW TITLE";
}, 5000);
return { data };
}
};
</script>
# ref
如果只想为一个 JavaScript 的基本变量创建响应式状态,可以使用 ref
方法。但使用 ref
方法创建的变量,在 JavaScript
代码部分被调用时,需要使用 .value
来访问变量的值。
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
setup() {
const title = ref("Hello, Vue 3!");
setTimeout(() => {
title.value = "THIS IS A NEW TITLE";
}, 5000);
return { title };
}
};
</script>
# 对象解构问题
当我们想使用某个大型响应式对象的一些属性时,或者想要在视图层中直接使用属性的名字而非data.property
,可以使用 ES6 的解构特性来满足我们的需要:
<template>
<h1>{{ title }}</h1>
<h2>{{ subTitle }}</h2>
</template>
<script>
export default {
setup() {
const data = reactive({
title: "This is Title.",
subTitle: "This is Subtitle."
})
let { title, subTitle } = data;
return { title, subTitle };
}
};
</script>
但是此时,解构得到的两个 property 的响应性都会丢失。对于这种情况,我们需要将响应式对象转换为一组 ref,再将这组 ref 进行解构,即可得到具有响应性的 property。
<template>
<h1>{{ title }}</h1>
<h2>{{ subTitle }}</h2>
</template>
<script>
export default {
setup() {
const data = reactive({
title: "This is Title.",
subTitle: "This is Subtitle."
})
let { title, subTitle } = toRefs(data);
return { title, subTitle };
}
};
</script>
当一个对象中的 property 太多时,我们可以使用 ES6 中的 ...
运算符进行结构:
<script>
export default {
setup() {
const data = reactive({
title: "This is Title.",
subTitle: "This is Subtitle.",
time: "2000-01-01",
name: "vue"
})
const refData = toRefs(data);
return { ...refData };
}
};
</script>