前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue 3 响应式基础

Vue 3 响应式基础

作者头像
公众号---人生代码
发布2020-11-11 12:32:12
6380
发布2020-11-11 12:32:12
举报
文章被收录于专栏:人生代码人生代码

响应式基础

声明响应式状态

reactive 相当于 Vue 2.x 中的 Vue.observable() API ,为避免与 RxJS 中的 observables 混淆因此对其重命名。该 API 返回一个响应式的对象状态。该响应式转换是“深度转换”——它会影响嵌套对象传递的所有 property。

Vue 中响应式状态的基本用例是我们可以在渲染期间使用它。因为依赖跟踪的关系,当响应式状态改变时视图会自动更新。

这就是 Vue 响应性系统的本质。当从组件中的 data() 返回一个对象时,它在内部交由 reactive() 使其成为响应式对象。模板会被编译成能够使用这些响应式 property 的渲染函数

我们同样按照之前的项目,在 src/TemplateM.vue 写下如下代码:

书写一个计数器,通过在 vue 中导出 reactivedefineComponent两个方法,

defineComponent 用于定义组件,reactive 用于创建响应式数据。

最后在 setup 函数中返回一个对象,对象中有 add 方法,state 响应式数据。

代码语言:javascript
复制
<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 :

同样我们在上面的代码中,加下如下代码:

代码语言:javascript
复制
<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 进行访问:

代码语言:javascript
复制
<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>
代码语言:javascript
复制
const map = reactive(new Map([['count', ref(0)]]))
console.log(map.get('count').value)

响应式状态解构

当我们想使用大型响应式对象的一些 property 时,可能很想使用 ES6 解构来获取我们想要的 property:

代码语言:javascript
复制
<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 防止更改响应式对象

有时我们想跟踪响应式对象 (refreactive) 的变化,但我们也希望防止在应用程序的某个位置更改它。例如,当我们有一个被 provide 的响应式对象时,我们不想让它在注入的时候被改变。为此,我们可以基于原始对象创建一个只读的 Proxy 对象:

代码语言:javascript
复制
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."
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CryptoCode 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 响应式基础
    • 声明响应式状态
      • 创建独立的响应式值作为 refs
        • 访问响应式对象
          • 响应式状态解构
            • 使用 readonly 防止更改响应式对象
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档