Points to note when using Vue3 responsive core API

1. Comparison with vue2

The responsive principle of vue2 is implemented through defineProperty, and vue3 is implemented through Proxy.

But the principle is not discussed here. What is discussed is the use and points of attention of the new API of vue3. Because vue3 exposes the responsive API, it is an independent data responsive system that has nothing to do with the components, so it can be achieved a>. Single state management

  • The responsive data of vue2 is placed in data(){} and will eventually be injected into the component instance.
  • The responsive data of vue3 is implemented through the exposed responsive API, and is finally returned through setup().

2. Introduction to core API

Responsive data in vue3 has 2 formats:

  1. reactive returns a Proxy object with direct access to properties.
  2. refThe Ref object returned by Attributes. computed needs to be accessed through and .value

1,reactive 和 readonly

Official website reference

Let me talk about a few important points first:

  1. can only be used forobject types.
  2. The returned proxy object is not equal to the original object.
  3. vue3 In order to ensure the consistency of access to the proxy, calling the same original objectreactive() will always return the same proxy object, while calling an existing proxy object (example below). itselfreactive() will return
  4. readonlyThe only difference is that the returned proxy object is read-only, and an error will be reported if the properties are modified.

Look at the example below:

import {
    
     reactive, readonly } from 'vue'

const origin = {
    
     a: 1, b: 2 }
const state = reactive(origin)
console.log(state === reactive(origin)) // true 相同的代理对象
console.log(state === reactive(state)) // true 返回自身

const stateOnly = readonly(state)
console.log(stateOnly === state) // false

state.a++
console.log(stateOnly.a) // 2

While stateOnly is read-only. But because the proxy is state, when state is modified, stateOnly will also be modified.

extra,stateOnly proxy–> state proxy–> { a: 1, b: 2 }, therefore stateOnly !== state

For simple purchase

import {
    
     readonly, reactive } from 'vue'

/**
 * 返回1个对象和2个方法,
 * 对象是是响应式的,不允许直接修改。只能通过提供的方法修改指定属性。
 * @returns Object
 */
function useUser() {
    
    
  const userOrigin = reactive({
    
    })
  const user = readonly(userOrigin)
  const setUserName = (name) => {
    
    
    userOrigin.name = name
  }
  const setUserAge = (age) => {
    
    
    userOrigin.age = age
  }
  return {
    
    
    user,
    setUserName,
    setUserAge
  }
}

const {
    
     user, setUserName, setUserAge } = useUser()

console.log(user)
setUserName('下雪天的夏风')
setUserAge(18)
console.log(user)

2,ref

Official website reference

can proxy any data, because it puts all the data on the .value attribute of an object and returns this object.

Note that this object is not a Proxy object, but a Ref object. The difference has been explained above.

If the parameter of ref() is Proxy object, put it directly into < a i=4> attribute. .value

const state = reactive({
    
     a: 1, b: 2 })
const stateRef = ref(state)

console.log(stateRef.value === state) // true

The reason for using .value is that access or modification of ordinary variables cannot be directly detected. So use the getter and setter methods to intercept the get and set operations of the object properties.

The general principle of ref is as follows:ref principle reference

const myRef = {
    
    
  _value: 0,
  get value() {
    
    
    // 触发依赖收集,重新渲染
    track()
    return this._value
  },
  set value(newValue) {
    
    
    this._value = newValue
    // 通知依赖它的对象更新
    trigger()
  }
}

3. Monitor data

watchEffect

Official website reference

This function willrun immediately whiletracking its dependencies responsively< a i=4>, and re-executed when dependencies change.

In other words, you can monitor multiple ones at the same time. As long as the reactive data used in this function is modified, this function will be re-executed.

In vue3, in most cases it is enough to use watchEffect() to listen to data.

watch

Official website reference

watchThe usage of is not much different from that in vue2. The difference from watchEffect is:

  1. watch The default is lazy listening, that is, the callback function will only be executed when the listening source changes. You can specify the configuration item{ immediate: true } to execute it immediately once.
  2. The old value can be obtained.
  3. You can know more clearly which state modification caused watch to be re-executed.

important point:

watchNormal data cannot be monitored, and the monitoring sources can only be the following 4 types:

  1. A function that returns a value
  2. a ref
  3. a reactive object
  4. An array consisting of values ​​of the above types

Look at the following example:

import {
    
     reactive, watch } from 'vue'

const state = reactive({
    
     a: 1, b: 2 })
watch(state.a, () => {
    
    
  console.log('变化了')
})

state.a++ // watch 函数并不会执行。

state.aIt is ordinary data, not responsive, so it cannot be monitored.

import {
    
     reactive, watch } from 'vue'

const state = reactive({
    
     a: 1, b: 2 })
watch(() => state.a, () => {
    
    
  console.log('变化了')
})

state.a++ // 变化了

If the first parameter of watch is a function, the function will be called to collect the dependencies . In other words, the state used in state.a is responsive data, so it can be monitored.

But if you are monitoring const count = ref(0), you can directly monitor count without using a function to return. Because what is passed is object. So the value of value can be monitored.

4. Judgment and conversion

judgment

API meaning
isProxy Determine whether the data was created byreactive or readonly
isReactive Determine whether the data isreactivecreated
isReadonly Determine whether the data isreadonlycreated
isRef Determine whether the data isrefobject

Convert(toRefs)

More referencesUtility functions

1,unref()

If the argument is a ref, the internal value is returned, otherwise the argument itself is returned.

val = isRef(val) ? val.value : val

2,toRefs

This is more important.

toRefs will convert all properties of a responsive object into ref format, and then wrap them into a normal object and return them.

Look at the following example:

import {
    
     reactive, toRefs } from 'vue'

const state = reactive({
    
     a: 1, b: 2 })
const stateRef = toRefs(state)
console.log(stateRef) // {a: refObj, b:refObj},所以将 stateRef 展开也是响应式的。
console.log(stateRef.a.value) // 1

应用1

When the parent passes a lot of data, but only wants to use one of them, and needs to remain responsive:

<template>
  <h1>{
   
   { msg }}</h1>
  <h1>{
   
   { msg2Alias }}</h1>
</template>

<script setup>
import {
      
       toRef, toRefs, computed } from "vue";
const props = defineProps(["msg", "msg2"]);

// 下面3种方式等价,父级修改 msg2 时,msg2Alias会同步修改。
const {
      
        msg2: msg2Alias } = toRefs(props);
const msg2Alias = toRef(props, "msg2");
const msg2Alias = computed(() => props.msg2);
</script>

应用2

When using a method that returns a proxy object, can be deconstructed without losing responsiveness.

import {
    
     reactive, toRefs } from "vue";

// composition function
function usePos(){
    
    
  const pos = reactive({
    
    x:0, y:0});
  return pos;
}

setup(){
    
    
  const {
    
    x, y} = usePos(); // lost reactivity
  const {
    
    x, y} = toRefs(usePos()); // reactivity
}

that's all.

Guess you like

Origin blog.csdn.net/qq_40147756/article/details/134267664