• 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">输出最原始的personbutton>
        <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

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

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

    实现防抖效果

    需求:修改数据后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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

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

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    孙组件:

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

    响应式数据的判断

    • 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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

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

  • 相关阅读:
    使用 C# 创造 ASCII 艺术
    C# I/O 文件和目录一 : Path
    【 Vue 路由 跳转 路由守卫 】
    vue3组件封装系列-表格及分页
    20世纪最佳12部学术专著
    2415. 反转二叉树的奇数层-层次遍历
    【无标题】
    分析设备树文件
    JVM:JIT实时编译器
    vite基础学习笔记:13.Dialog 对话框 (用户注册与登录)
  • 原文地址:https://blog.csdn.net/mantou_riji/article/details/125976391