响应式根底
欢送订阅我的公众号 <人生代码>,或者 CSDN 专栏
Vue 3 入门到实战系列教程
申明响应式状态
reactive
相当于 Vue 2.x 中的 Vue.observable()
API ,为防止与 RxJS 中的 observables 混同因而对其重命名。该 API 返回一个响应式的对象状态。该响应式转换是“深度转换”——它会影响嵌套对象传递的所有 property。
Vue 中响应式状态的根本用例是咱们能够在渲染期间应用它。因为依赖跟踪的关系,当响应式状态扭转时视图会自动更新。
这就是 Vue 响应性零碎的实质。当从组件中的 data()
返回一个对象时,它在外部交由 reactive()
使其成为响应式对象。模板会被编译成可能应用这些响应式 property 的渲染函数
咱们同样依照之前的我的项目,在 src/TemplateM.vue
写下如下代码:
书写一个计数器,通过在 vue
中导出 reactive
,defineComponent
两个办法,
defineComponent
用于定义组件,reactive
用于创立响应式数据。
最初在 setup
函数中返回一个对象,对象中有 add
办法,state
响应式数据。
<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
:
ref
会返回一个可变的响应式对象,该对象作为它的外部值——一个响应式的援用,这就是名称的起源。此对象只蕴含一个名为 value
的 property :
同样咱们在下面的代码中,加下如下代码:
<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 readonly."