Vue3的其他组和API—— toRaw与markRaw、customRef、 provide 与inject

toRaw与markRaw

toRaw

  • 作用:将一个由reactive生成的响应式对象转为普通对象。
    (不适用于ref)
  • 使用场景∶用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。

markRaw

  • 作用:标记一个对象,使其永远不会再成为响应式对象
    即数据可以改变,但是会在渲染到页面了。
  • 应用场景:
    (1)有些值不应被设置为响应式的,例如复杂的第三方类库等。
    (2)当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

例子

<template>
    <h2>姓名:{
   
   {name }}</h2>
    <h2>年龄:{
   
   {age }}</h2>
    <h2>薪资:{
   
   {job.j1.salary }}</h2>
    <h2 v-show="person.student">同学:{
   
   { person.student }}</h2>
    <br />
    <button @click="showRawPerson">输出最原始的person</button>
    <button @click="addStudent">添加同学</button>
    <button @click="person.student.name += '~'">修改同学姓名</button>
    <button @click="person.student.age += 1">增长同学年龄</button>

</template>

<script>
import {
      
       reactive, toRefs, ref, toRaw, markRaw } from 'vue'
export default {
      
      
    name: 'DemoVue',
    setup() {
      
      
        // let person = shallowReactive({
      
      
        let person = reactive({
      
      
            name: 'yang',
            age: 18,
            job: {
      
      
                j1: {
      
      
                    salary: 20
                }
            }
        })

        function showRawPerson() {
      
      
            const p = toRaw(person)
           console.log(p)
        }
        function addStudent() {
      
      
            const student = {
      
      
                name: 'cheng',
                age:20
            }
            person.student = markRaw(student)
        }
        
        return {
      
      
            ...toRefs(person),
            showRawPerson,
            addStudent,
            person
        }
    }
}
</script>

输出效果:
在这里插入图片描述

customRef(自定义Ref)

  • 作用:customRef用于创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
    eg:
<template>
   <input type="text" v-model="keyWord"/>
   <h3>{
   
   {keyWord}}</h3>
</template>

<script>
import {
      
      ref,customRef} from 'vue'
export default {
      
      
    name: 'DemoVue',
    setup() {
      
      
        // 自定义Ref——myRef
        function myRef(value) {
      
      
            console.log('---myRef---', value)
            return customRef((track,trigger) => {
      
       
                return {
      
      
                    // 有人读取该属性时调用
                    get() {
      
      
                        track()//追踪set修改value的变化
                        return value
                    },
                    // 有人修改该属性时调用
                    set(newValue) {
      
      
                        value = newValue
                        trigger()//通知Vue去重新解析模板(重新调用get)
                    }
                }
            })
        }

        // let keyWord = ref("hello")//vue提供的ref
        let keyWord = myRef("hello")//自己定义的ref

        return {
      
      keyWord}
    }
}
</script>

效果:
在这里插入图片描述

实现防抖效果

需求:修改数据后1s中再触发页面重新解析模板
实现:

<template>
   <input type="text" v-model="keyWord"/>
   <h3>{
   
   {keyWord}}</h3>
</template>

<script>
import {
      
      ref,customRef} from 'vue'
export default {
      
      
    name: 'DemoVue',
    setup() {
      
      
        // 自定义Ref——myRef
        function myRef(value,delay) {
      
      
            let timer 
            console.log('---myRef---', value)
            return customRef((track,trigger) => {
      
       
                return {
      
      
                    // 有人读取该属性时调用
                    get() {
      
      
                        track()//追踪set修改value的变化
                        return value
                    },
                    // 有人修改该属性时调用
                    set(newValue) {
      
      
                        clearTimeout(timer)
                        timer = setTimeout(() => {
      
      
                            value = newValue
                            trigger()//通知Vue去重新解析模板(重新调用get)
                        }, delay)
                    }
                }
            })
        }

        // let keyWord = ref("hello")//vue提供的ref
        let keyWord = myRef("hello",1000)//自己定义的ref

        return {
      
      keyWord}
    }
}
</script>

效果:
在这里插入图片描述
一个要注意的问题是,在开启定时器之前先关闭所有的其他定时器,以实现”防抖“效果。
”防抖“效果:即连续输入的时候等待输入完成最终才将结果显示在页面上。
如果不关闭定时器会出现如下抖动效果:(连续输入的时候会出现抖动效果)
在这里插入图片描述

provide 与inject

  • 作用:实现父组件与后代组件间的通信
    在这里插入图片描述

  • 方法:父组件有一个 provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据
    语法格式: provide('给传递的变量命名',变量名)
    语法格式: inject('给传递的变量命名')

provide 与inject案例

父组件:

<template>
  <div class="app">
    <h2>我是app组件(父组件)</h2>
    <h3>{
   
   {name}}--{
   
   {age}}</h3>
    <Child/>
  </div>
</template>

<script>
import Child from './components/Child.vue'
import {
      
      provide, reactive, toRefs} from 'vue'
export default {
      
      
  name: 'AppVue',
  components: {
      
       Child },
  setup() {
      
      
    const student = reactive({
      
      
      name: 'yang',
      age:18
    })
    provide('student',student)//给自己的后代组件传递数据
    return {
      
      
      ...toRefs(student)
    }
  }
}
</script>

<style>
.app {
      
      
  background: #333;
  padding: 10px;
}
</style>

孙组件:

<template>
    <div class="son">
        <h2>我是son组件(孙组件)</h2>
        <h3>{
   
   {student.name}}--{
   
   { student.age}}</h3>
    </div>
</template>

<script>
import {
      
       inject } from '@vue/runtime-core'
export default {
      
      
    name: 'SonVue',
    setup() {
      
      
        let student = inject('student')
        return {
      
      
            student
        }
    }
}
</script>

<style>
.son {
      
      
    background: rgb(95, 24, 24);
    padding: 10px;
}
</style>

效果:
在这里插入图片描述

响应式数据的判断

  • isRef:检查一个值是否为一个ref 对象
  • isReactive:检查一个对象是否是由reactive创建的响应式代理
  • isReadonly:检查一个对象是否是由readonly创建的只读代理
  • isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理

eg:

<template>
  <div class="app">
    <h2>我是app组件</h2>
  </div>
</template>

<script>
import {
      
      ref, reactive, readonly, toRefs,isRef,isReactive,isReadonly,isProxy} from 'vue'
export default {
      
      
  name: 'AppVue',
  setup() {
      
      
    const student = reactive({
      
      
      name: 'yang',
      age:18
    })
    let sum = ref(0)
    let student2 = readonly(student)

    console.log(isRef(sum))
    console.log(isReactive(student))
    console.log(isReadonly(student2))
    console.log(isProxy(student))
    console.log(isProxy(student2))


    
    return {
      
      
      ...toRefs(student)
    }
  }
}
</script>

<style>
.app {
      
      
  background: #333;
  padding: 10px;
}
</style>

输出:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/mantou_riji/article/details/125976391