reactive
至關於 Vue 2.x 中的 Vue.observable()
API ,爲避免與 RxJS 中的 observables 混淆所以對其重命名。該 API 返回一個響應式的對象狀態。該響應式轉換是「深度轉換」——它會影響嵌套對象傳遞的全部 property。vue
Vue 中響應式狀態的基本用例是咱們能夠在渲染期間使用它。由於依賴跟蹤的關係,當響應式狀態改變時視圖會自動更新。react
這就是 Vue 響應性系統的本質。當從組件中的 data()
返回一個對象時,它在內部交由 reactive()
使其成爲響應式對象。模板會被編譯成可以使用這些響應式 property 的渲染函數ide
咱們一樣按照以前的項目,在 src/TemplateM.vue
寫下以下代碼:函數
書寫一個計數器,經過在 vue
中導出 reactive
,defineComponent
兩個方法,ui
defineComponent
用於定義組件,reactive
用於建立響應式數據。this
最後在 setup
函數中返回一個對象,對象中有 add
方法,state
響應式數據。url
<template>
<div class="template-m-wrap">
<button @click="add">{{state.count}}</button>
</div>
</template>
<script>
import { defineComponent, reactive } from "vue";
export default defineComponent({
name: 'TemplateM',
setup() {
const state = reactive({
count: 0
})
const add = () => {
state.count++
console.log("state.count", state.count)
}
return {
state,
add
}
}
})
</script>
refs
想象一下,咱們有一個獨立的原始值 (例如,一個字符串),咱們想讓它變成響應式的。固然,咱們能夠建立一個擁有相同字符串 property 的對象,並將其傳遞給 reactive
。Vue 爲咱們提供了一個能夠作相同事情的方法 ——ref
:spa
ref
會返回一個可變的響應式對象,該對象做爲它的內部值——一個響應式的引用,這就是名稱的來源。此對象只包含一個名爲 value
的 property :code
一樣咱們在上面的代碼中,加下以下代碼:orm
<template>
<div class="template-m-wrap">
singleCount - {{singleCount}}
<button @click="add">{{state.count}}</button>
</div>
</template>
<script>
import { ref, defineComponent, reactive } from "vue";
export default defineComponent({
name: 'TemplateM',
setup() {
const state = reactive({
count: 0
})
let singleCount = ref(0)
const add = () => {
state.count++
singleCount++
console.log("state.count", state.count, singleCount)
}
return {
state,
singleCount,
add
}
}
})
</script>
其實咱們注意到,在模板中,當 ref 做爲渲染上下文 (從 setup() 中返回的對象) 上的 property 返回並能夠在模板中被訪問時,它將自動展開爲內部值。不須要在模板中追加 .value
。
Ref 展開僅發生在被響應式 Object
嵌套的時候。當從 Array
或原生集合類型如 Map
訪問 ref 時,不會進行展開:
下面代碼咱們能夠看到,將一個 reactive([ref('Vue 3 Guide')])
,而後根據 books[0].value
進行訪問:
<template>
<div class="template-m-wrap">
singleCount - {{singleCount}}
<button @click="add">{{state.count}}</button>
books {{books[0].value}}
</div>
</template>
<script>
import { ref, defineComponent, reactive } from "vue";
export default defineComponent({
name: 'TemplateM',
setup() {
const state = reactive({
count: 0
})
let singleCount = ref(0)
const books = reactive([ref('Vue 3 Guide')])
const add = () => {
state.count++
singleCount.value++
console.log("state.count", state.count, singleCount)
}
return {
state,
singleCount,
books,
add
}
}
})
</script>
const map = reactive(new Map([['count', ref(0)]]))
console.log(map.get('count').value)
當咱們想使用大型響應式對象的一些 property 時,可能很想使用 ES6 解構來獲取咱們想要的 property:
<template>
<div class="template-m-wrap">
singleCount - {{singleCount}}
<button @click="add">{{state.count}}</button>
books {{books[0].value}}
<br>
{{author}} - {{title}} - from - {{book}}
</div>
</template>
<script>
import { ref, defineComponent, reactive } from "vue";
export default defineComponent({
name: 'TemplateM',
setup() {
const state = reactive({
count: 0
})
let singleCount = ref(0)
const books = reactive([ref('Vue 3 Guide')])
const book = reactive({
author: 'Vue Team',
year: '2020',
title: 'Vue 3 Guide',
description: 'You are reading this book right now ;)',
price: 'free'
})
let { author, title } = book
const add = () => {
state.count++
singleCount.value++
console.log("state.count", state.count, singleCount)
}
return {
state,
singleCount,
books,
add,
author,
title,
book
}
}
})
</script>
readonly
防止更改響應式對象有時咱們想跟蹤響應式對象 (ref
或 reactive
) 的變化,但咱們也但願防止在應用程序的某個位置更改它。例如,當咱們有一個被 provide 的響應式對象時,咱們不想讓它在注入的時候被改變。爲此,咱們能夠基於原始對象建立一個只讀的 Proxy 對象:
import { reactive, readonly } from 'vue'
const original = reactive({ count: 0 })
const copy = readonly(original)
// 在copy上轉換original 會觸發偵聽器依賴
original.count++
// 轉換copy 將導失敗並致使警告
copy.count++ // 警告: "Set operation on key 'count' failed: target is rea