一、响应式基础

前提:你会使用 setup 函数或 <script setup>语法

1.reactive

我们可以使用 reactive() 函数创建一个响应式对象数组

import { reactive } from 'vue'

const state = reactive({ count: 0 })
  • 当我们使用 reactive 函数处理我们的数据之后,数据被使用时就会进行依赖收集;
  • 当数据发生改变时,所有收集到的依赖都是进行对应的响应式操作(比如更新界面);
  • 事实上,在使用Options API时编写的 data 选项,也是在内部交给了 reactive 函数将其变成响应式对象的

注意:

reactive 函数只能包裹对象或数组,包裹基本数据类型会丧失响应式,并且控制会打印出警告

2. ref

reactive() 的种种限制归根结底是因为 JavaScript 没有可以作用于所有值类型的 “引用” 机制。为此,Vue 提供了一个 ref()方法来允许我们创建可以使用任何值类型的响应式 ref

import { ref } from 'vue'

const countRef = ref(0)
// 使用
console.log(countRef.value)

使用ref()函数定义的响应式数据,是一个带有.value的Ref对象,在<script>中使用该值时,需要.value赋值或取值。

而在template模板中,则会自动解包,取出.value的值。

实例代码:

<template>
  <h2>composition API</h2>
  <p>ref-simple: {{ simple }}</p>
  <p>ref-obj: {{ obj }}</p>
  <div>
    <p><button @click="simple++">更改simple</button></p>
    <p><button @click="obj.name += '1'">更改obj.name</button></p>
    <p><button @click="editObjName">更改obj.name</button></p>
  </div>
  <hr />
  <p>reactive-state: {{ state }}</p>
  <p>reactive-count: {{ count }}</p>
  <div>
    <p><button @click="state.firstName += '1'">更改reactive-state</button></p>
    <p><button @click="count++">更改reactive-count</button></p>
  </div>
</template>

<script>
import { reactive, ref } from 'vue';
export default {
  name: 'App',
  setup() {
    const simple = ref(0);
    const obj = ref({ name: 'fct' });
    // reactive
    const state = reactive({ firstName: 'Steven', secordName: 'Diff' });
    const count = reactive(0);	// 报警告
    function editObjName() {
      obj.value.name += '1';
    }
    return {
      simple,
      obj,
      state,
      count,
      editObjName
    };
  }
};
</script>

2.1 获取HTML元素或组件实例

使用ref()函数,要声明一个同名的 ref。

<template>
  <input ref="inputRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue'

// 声明一个 ref 来存放该元素的引用
// 必须和模板里的 ref 同名
const inputRef = ref(null)

onMounted(() => {
  inputRef.value.focus()
})
// 如果不使用 <script setup>,需确保从 setup() 返回 ref:
// export default {
//   setup() {
//     const inputRef = ref(null)
//     // ...
//     return {
//       inputRef
//     }
//   }
// }
</script>

3. readonly

我们通过reactive()或者ref()可以获取到一个响应式的对象,但是某些情况下,我们传入响应式对象给其他地方(组件),希望在另外一个地方(组件)被使用,但是不能被修改,这个时候可以使用readonly()

  • readonly()接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。

实例代码:

const original = reactive({ count: 0 })

const copy = readonly(original)

watchEffect(() => {
  // 用来做响应性追踪
  console.log(copy.count)  // 1.打印 0
})

// 更改源属性会触发其依赖的侦听器
original.count++    // 2. 侦听器打印 1

// 更改该只读副本将会失败,并会得到一个警告
copy.count++ // warning!

二、reactive、ref、readonly相关API

1. reactive判断的API

1.1 isProxy

检查对象是否是由 reactive 或 readonly创建的 proxy

1.2 isReactive

  • 检查对象是否是由 reactive 创建的响应式代理
  • 如果该代理是 readonly 建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true。

1.3 isReadonly

检查对象是否是由 readonly 创建的只读代理

1.4 toRaw

返回 reactive 或 readonly 代理的原始对象建议保留对原始对象的持久引用。请谨慎使用)。

1.5 shallowReactive

创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (深层还是原生对象)。

1.6 shallowReadonly

创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换(深层还是可读、可写的)。

2.toRefs

如果我们使用ES6的解构语法,对reactive返回的对象进行解构获取值,那么之后无论是修改结构后的变量,还是修改reactive 返回的state对象数据都不再是响应式的:

import { reactive } from 'vue';
const state = reactive({
  msg: 'fct',
  tips: 'vue3'
});
const { msg, tips } = state;
// msg 为非响应式的
  • Vue为我们提供了一个toRefs的函数,可以将reactive返回的对象中的属性都转成ref

  • 那么我们再次进行结构出来的 msg 本身都是 ref的;

import { reactive, toRefs } from 'vue';

const state = reactive({
  msg: 'fct',
  tips: 'vue3'
});
const { msg, tips } = toRefs(state);

这种做法相当于已经在state.msgref.value之间建立了链接,任何一个修改都会引起另外一个变化;

3. toRef

如果我们只希望转换一个reactive对象中的属性为ref, 那么可以使用toRef的方法

import { reactive, toRef } from 'vue';

const state = reactive({
  msg: 'fct',
  tips: 'vue3'
});
const tips = toRef(state, 'tips');
// tips 为响应式数据

4. ref其他的API

4.1 unref

如果我们想要获取一个ref引用中的value,那么也可以通过unref方法

  • 如果参数是一个 ref,则返回内部值,否则返回参数本身

  • 这是 val = isRef(val) ? val.value : val 的语法糖函数;

    import { ref, unref } from 'vue';
    
    const fct = ref(999);
    console.log(fct.value, unref(fct));
    

4.2 isRef

判断值是否是一个ref对象

4.3 shallowRef

创建一个浅层的ref对象

// 不能监听 info.name 发生的改变,因为是浅层Ref对象
const info = shallowRef({ name: 'fct' });

// 能监听 num 发生的改变
const num = shallowRef(32);

4.4 triggerRef

手动触发和 shallowRef 相关联的副作用

<template>
  <div>
    <p>info: {{ info }}</p>
    <p>num: {{ num }}</p>
    <button @click="info.name += '1'">更改shallowRef-info中的name</button>
    <button @click="editInfoName">triggerRef-更改shallowRef-info中的name</button>
    <button @click="num++">shallowRef-num++</button>
  </div>
</template>

<script setup>
import { shallowRef, triggerRef } from 'vue';

const info = shallowRef({ name: 'fct' });
const num = shallowRef(32);

function editInfoName(params) {
  info.value.name += '1';
  // 手动触发更新
  triggerRef(info);
}
</script>

原文地址:http://www.cnblogs.com/fuct/p/16828697.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性