Other parts of composition API such as deep response and shallow response in Vue3

1,shallowReactive 与 shallowRef

  • shallowReactive : only handles the responsiveness of the outermost properties in the object (that is, the shallow responsiveness);
  • shallowRef: only handles the response type of value, does not perform reactive processing of objects
<template>
  <h2>App</h2>
  <h3>m1: {
   
   {m1}}</h3>
  <h3>m2: {
   
   {m2}}</h3>
  <h3>m3: {
   
   {m3}}</h3>
  <h3>m4: {
   
   {m4}}</h3>
  <button @click="update">更新</button>
</template>
<script lang="ts">
import {
      
       reactive, ref, shallowReactive, shallowRef } from 'vue'
/* 
shallowReactive与shallowRef
  shallowReactive: 只处理了对象内最外层属性的响应式(也就是浅响应式)
  shallowRef: 只处理了value的响应式, 不进行对象的reactive处理
总结:
  reactive与ref实现的是深度响应式, 而shallowReactive与shallowRef是浅响应式
  什么时候用浅响应式呢?
    一般情况下使用ref和reactive即可,
    如果有一个对象数据, 结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
    如果有一个对象数据, 后面会产生新的对象来替换 ===> shallowRef
*/
export default {
      
      

  setup () {
      
      

    const m1 = reactive({
      
      a: 1, b: {
      
      c: 2}})
    const m2 = shallowReactive({
      
      a: 1, b: {
      
      c: 2}})

    const m3 = ref({
      
      a: 1, b: {
      
      c: 2}})
    const m4 = shallowRef({
      
      a: 1, b: {
      
      c: 2}})

    const update = () => {
      
      
      // m1.b.c += 1
      // m2.b.c += 1

      // m3.value.a += 1
      m4.value.a += 1
    }

    return {
      
      
      m1,
      m2,
      m3,
      m4,
      update,
    }
  }
}
</script>

2,readonly 与 shallowReadonly

  • readonly: deep read-only data, a read-only proxy that takes an object (reactive or plain) or ref and returns the original proxy, read-only proxies are deep: any nested properties accessed are also read-only.
  • shallowReadonly: shallow read-only data, creates a proxy to make its own property read-only, but does not perform deep read-only conversion of nested objects.
  • Application scenario: In some specific cases, we may not want to update the data, so we can wrap and generate a read-only proxy object to read the data, but cannot modify or delete it.
<template>
  <h2>App</h2>
  <h3>{
   
   {state}}</h3>
  <button @click="update">更新</button>
</template>

<script lang="ts">
import {
      
       reactive, readonly, shallowReadonly } from 'vue'
/*
readonly: 深度只读数据
  获取一个对象 (响应式或纯对象) 或 ref 并返回原始代理的只读代理。
  只读代理是深层的:访问的任何嵌套 property 也是只读的。
shallowReadonly: 浅只读数据
  创建一个代理,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 
应用场景: 
  在某些特定情况下, 我们可能不希望对数据进行更新的操作, 那就可以包装生成一个只读代理对象来读取数据, 而不能修改或删除
*/
export default {
      
      
  setup () {
      
      
    const state = reactive({
      
      
      a: 1,
      b: {
      
      
        c: 2
      }
    })
    // const rState1 = readonly(state)
    const rState2 = shallowReadonly(state)
    const update = () => {
      
      
      // rState1.a++ // error
      // rState1.b.c++ // error
      // rState2.a++ // error
      rState2.b.c++
    }
    return {
      
      
      state,
      update
    }
  }
}
</script>

3. toRaw and markRaw

  • toRaw: Turn the proxy object into an ordinary object, and the interface will not change when the data changes.
  • markRaw: Marks an object so that it will never be converted to a proxy and is no longer reactive.
<template>
  <h2>{
   
   {state}}</h2>
  <button @click="testToRaw">测试toRaw</button>
  <button @click="testMarkRaw">测试markRaw</button>
</template>
<script lang="ts">
import {
      
       markRaw, reactive, toRaw } from 'vue'
export default {
      
      
  setup () {
      
      
    const state = reactive<any>({
      
      
      name: 'tom',
      age: 25,
    })
    const testToRaw = () => {
      
      
      const user = toRaw(state)
      user.age++  // 界面不会更新
    }
    const testMarkRaw = () => {
      
      
      const likes = ['a', 'b']
      // state.likes = likes
      state.likes = markRaw(likes) // likes数组就不再是响应式的了
      setTimeout(() => {
      
      
        state.likes[0] += '--'
      }, 1000)
    }
    return {
      
      
      state,
      testToRaw,
      testMarkRaw,
    }
  }
}
</script>

4,toRef

A property on the source responsive object creates a ref object, the two internally operate on the same data value, and the two are synchronized when updated.

Difference ref: Copy a new data value to operate independently, and do not affect each other when updating.
Application:: toRef is useful when you want to pass the ref of a prop to a composite function

<template>
  <h2>App</h2>
  <p>{
   
   {state}}</p>
  <p>{
   
   {foo}}</p>
  <p>{
   
   {foo2}}</p>
  <button @click="update">更新</button>
  <Child :foo="foo"/>
</template>
<script lang="ts">
/*
toRef:
  为源响应式对象上的某个属性创建一个 ref对象, 二者内部操作的是同一个数据值, 更新时二者是同步的
  区别ref: 拷贝了一份新的数据值单独操作, 更新时相互不影响
  应用: 当要将某个 prop 的 ref 传递给复合函数时,toRef 很有用
*/

import {
      
       reactive, toRef, ref } from 'vue'
import Child from './Child.vue'
export default {
      
      
  setup () {
      
      
    const state = reactive({
      
      
      foo: 1,
      bar: 2
    })
    const foo = toRef(state, 'foo')
    const foo2 = ref(state.foo)
    const update = () => {
      
      
      state.foo++
      // foo.value++
      // foo2.value++  // foo和state中的数据不会更新
    }
    return {
      
      
      state,
      foo,
      foo2,
      update,
    }
  },
  components: {
      
      
    Child
  }
}
</script>

5. The principle of customRef -------- ref

Create a custom ref and explicitly control its dependency tracking and update triggering;
there are two callback functions, one is track() to tell Vue to monitor and track data, and the other is trigger() to trigger updates;

<template>
  <h2>App</h2>
  <input v-model="keyword" placeholder="搜索关键字"/>
  <p>{
   
   {keyword}}</p>
</template>

<script lang="ts">
/*
customRef:
  创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制

需求: 
  使用 customRef 实现 debounce 的示例
*/

import {
      
      
  ref,
  customRef
} from 'vue'

export default {
      
      

  setup () {
      
      
    const keyword = useDebouncedRef('', 500)
    console.log(keyword)
    return {
      
      
      keyword
    }
  },
}

/* 
实现函数防抖的自定义ref
*/
function useDebouncedRef<T>(value: T, delay = 200) {
      
      
  let timeout: number
  return customRef((track, trigger) => {
      
      
    return {
      
      
      get() {
      
      
        // 告诉Vue追踪数据
        track()
        return value
      },
      set(newValue: T) {
      
      
        clearTimeout(timeout)
        timeout = setTimeout(() => {
      
      
          value = newValue
          // 告诉Vue去触发界面更新
          trigger()
        }, delay)
      }
    }
  })
}

</script>

6. Provide and inject implement component communication

  • Provide and inject provide dependency injection, which is similar to Vue2's provide/inject ;
  • Realize communication between cross-level components (grandfather and grandchildren, cross-domain parent-child component communication and direct grandparent communication);
<template>
  <h1>父组件</h1>
  <p>当前颜色: {
   
   {color}}</p>
  <button @click="color='red'"></button>
  <button @click="color='yellow'"></button>
  <button @click="color='blue'"></button>
  <hr>
  <Son />
</template>
<script lang="ts">
import {
      
       provide, ref } from 'vue'
/* 
- provide` 和 `inject` 提供依赖注入,功能类似 2.x 的 `provide/inject
- 实现跨层级组件(祖孙)间通信
*/
import Son from './Son.vue'
export default {
      
      
  name: 'ProvideInject',
  components: {
      
      
    Son
  },
  setup() {
      
      
    const color = ref('red')
    provide('color', color)
    return {
      
      
      color
    }
  }
}
</script>
<template>
  <div>
    <h2>子组件</h2>
    <hr>
    <GrandSon />
  </div>
</template>

<script lang="ts">
import GrandSon from './GrandSon.vue'
export default {
      
      
  components: {
      
      
    GrandSon
  },
}
</script>
<template>
  <h3 :style="{color}">孙子组件: {
   
   {color}}</h3>
</template>

<script lang="ts">
import {
      
       inject } from 'vue'
export default {
      
      
  setup() {
      
      
    const color = inject('color')
    return {
      
      
      color
    }
  }
}
</script>

7. Judgment of responsive data

  1. isRef: checks if a value is a ref object;
  2. isReactive: checks if an object is a reactive proxy created by reactive;
  3. isReadonly: checks whether an object is a read-only proxy created by readonly;
  4. isProxy: checks whether an object is a proxy created by a reactive or readonly method;

Guess you like

Origin blog.csdn.net/weixin_44684357/article/details/132478554