Vue3 Day6-toRaw、markRaw

6.1 toRaw以及markRaw

<template>
    <div>
        <h2>{{ reactivePerson }}</h2>
        <button @click="change">改变吧</button>
    </div>
</template>
​
<script setup>
import {
    reactive,
    toRaw,
    markRaw
} from 'vue'
​
let person = {
    age: 12,
    work: {
        job: {
            num: 1
        }
    }
}
​
​
// let reactivePerson = reactive(person) // 拷贝
// // 1.toRaw
// // 作用:将一个由reactive生成的响应式对象转为普通对象。
// // 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
// let pt = toRaw(reactivePerson)
​
// let change = () => {
//  // reactivePerson.age++  //响应式对象形式
//  pt.age++ //普通对象形式,不会响应
​
//  console.log(person); //打印出来的数据是普通对象形式
//  console.log(reactivePerson); //打印出来的数据是proxy响应式对象形式
//  console.log(toRaw(reactivePerson)); //打印出来的数据是普通对象形式
// }
​
​
​
// 2.markRaw
// 作用:标记一个对象,使其永远不会再成为响应式对象。
// 应用场景:
// 有些值不应被设置为响应式的,例如复杂的第三方类库等。
// 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
​
let reactivePerson = reactive(person) // 拷贝
let pt = markRaw({
    reactivePerson: {}
})
let is = reactive({
    reactivePerson: pt.reactivePerson
})
​
let change = () => {
    // pt.age++ //普通对象形式,不会响应
    // is.age++
​
    console.log('111', pt)
    console.log('222', is)
}
</script>
​
<style scoped></style>

6.2 customRef的使用

创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式

详细信息:customRef() 预期接收一个工厂函数作为参数,这个工厂函数接受 tracktrigger 两个函数作为参数,并返回一个带有 getset 方法的对象。一般来说,track() 应该在 get() 方法中调用,而 trigger() 应该在 set() 中调用。然而事实上,你对何时调用、是否应该调用他们有完全的控制权。

App.vue

<template>
    <div>
        <input type="text" v-model="text">
    </div>
</template>
​
<script setup>
import { useDebouncedRef } from './hooks/useDebouncedRef'
const text = useDebouncedRef('hello')
​
</script>
​
<style scoped></style>
​

hooks->useDebouncedRef.js

import { customRef } from 'vue'
​
export function useDebouncedRef(value, delay = 5000) {
  let timeout
  return customRef((track, trigger) => {
    return {
      get() {
        console.log(`get数据为:${value}`);
        // 在这里发送请求
        track()  //追踪
        return value
      },
      set(newValue) {
        console.log(`把容器中的数据改成了:${newValue}`);
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}

6.3 provide和inject

provide和inject是两个非常实用的组合式API,它们主要用于祖先组件与子孙组件之间的数据传递。provide用于提供数据,而inject则用于注入数据

  1. 基本概念

    • provide函数:provide函数用于在祖先组件中提供一个值,该值可以在任何子孙组件中通过inject来接收。

    • inject函数:inject函数用于在任何子孙组件中接收祖先组件通过provide提供的值。

  2. 使用方法

    • 在祖先组件中,通过调用provide函数并传入一个唯一的键(key)和需要传递的数据值,即可提供数据。例如:provide('someKey', someValue)

    • 在子孙组件中,通过调用inject函数并传入相同的键,即可接收到祖先组件提供的数据。例如:const someValue = inject('someKey')

App.vue

<template>
    <div>
        <GrandSon></GrandSon>
    </div>
</template>
​
<script setup>
import { reactive, provide } from 'vue'
import GrandSon from './components/GrandSon.vue'
let info = reactive({
    name: 'haha',
    age: 12
})
let change = () => {
    info.name += '@'
}
provide('info', info)
provide('change', change)
</script>
​
<style scoped></style>
​

GrandSon.vue

<template>
    <div>
        <h2>{{ infoson }}</h2>
        <button @click="changeson">点我</button>
    </div>
</template>
​
<!-- setup取代了export default -->
<script setup>
import { inject } from "vue";
​
let infoson = inject('info')
let changeson = inject('change')
</script>
​
<style scoped></style>

6.3 Teleport

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去

父组件App.vue

<template>
    <div class="app">
        <h2>我是父组件</h2>
        <HelloWorld></HelloWorld>
    </div>
</template>
​
<script setup>
import { reactive, provide } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
​
</script>
​
<style scoped>
.app {
    width: 800px;
    background-color: #ddd;
    padding: 30px;
    margin: 0 auto;
}
</style>
 

子组件HelloWorld.vue

<template>
    <div class="son">
        <h2>我是helloworld</h2>
        <MyDialog></MyDialog>
    </div>
</template>
​
<!-- setup取代了export default -->
<script setup>
import MyDialog from './MyDialog.vue'
</script>
​
<style scoped>
.son {
    position: relative;
    background-color: #666;
    padding: 10px;
}
</style>

孙组件MyDialog.vue

<template>
  <div>
    <button @click="open">打开弹窗</button>
    <Teleport to="body">
      <div v-if="isShow" class="mask">
        <div class="dialog">
          <h3>Teleport</h3>
          <h4>弹窗Teleport是一种能够将我们的组件html结构移动到指定位置的技术</h4>
          <h4>弹窗Teleport是一种能够将我们的组件html结构移动到指定位置的技术</h4>
          <h4>弹窗Teleport是一种能够将我们的组件html结构移动到指定位置的技术</h4>
          <button @click="close">关闭弹窗</button>
        </div>
      </div>
    </Teleport>
  </div>
</template>
​
<script setup>
import { ref, reactive, toRefs, onMounted } from 'vue'
let isShow = ref(false)
const open = () => {
  isShow.value = true
}
const close = () => {
  isShow.value = false
}
</script>
<style scoped>
.mask {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(255, 0, 0, 0.5);
}
​
.dialog {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, 0);
  text-align: center;
  width: 600px;
  height: 400px;
  background-color: #f60;
}
​
.dialog button {
  margin: 100px 0 0 0;
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值