一文了解——to系全家桶并带讲解源码(Vue.js)

To系全家桶并带源码

1.toRef

1.1toRef的例子

举一个例子

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">修改</button>
</template>

<script setup lang="ts">
const who = {
  name:'kun',
  age:'2.5',
  like:'sing',
}
const change = () => {
  who.like='jump'
  console.log(who.like)
}
</script>

在这个例子中打印出来的是 jump

而在其中的视图 {{who}} 的打印值不会改变 因为其不是响应式的 展示如下

而在此时我们需要加入这小节的核心 也就是 toRef

首先我们需要来讲一下 toRef 的参数 第一个传入的是 对象 第二个传入的是 那个对象的key

在这一点 可以具体的看 vue官网的 类型示例

了解了这个之后 我们改变在上面的例子 加入了 toRef

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">修改</button>
</template>

<script setup lang="ts">
import {toRef} from 'vue'
const who = {
  name:'kun',
  age:'2.5',
  like:'sing',
}
const like = toRef(who,'like') 

const change = () => {
  like.value = 'jump'
  console.log(like)
  console.log(who)
}
</script>

打印出来的值 分别是

可以看到 其中的数值发生了改变 但是 视图依旧没有发生变化

接下来 我们需要将who这个对象加入响应式

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {toRef,reactive} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const like = toRef(who,'like') 

const change = () => {
  like.value = 'jump'
  console.log(like)
  console.log(who)
}


</script>

在这里打印出来的是

并且可以看到 视图也同时发生了变化

直白点说就是 toRef 假设非响应式对象 它可以将对象中的值 变成响应式 也可以修改 但是修改不会影响视图的效果

toRef 假设为响应式对象 它可以将对象中的值修改 且会影响视图的效果

1.2toRef的源码

路径如下

在这里映入眼帘的是一个重载函数

重点其实在这里

在这里可以看到 他两个参数都放在这里 并且做了一个判断是否为ref对象

如果不是的话 就会进入到 ObjectRefImpl 中

这里面 如果看过ref的源码就会发现 很是相像

但是又有不一样的地方 在这里和ref对象不一样的地方就在于 他没有做收集依赖 也没有触发依赖的操作 所以说他对于非响应式对象是不会去改变视图的

2.toRefs

2.1toRefs的例子

单看名字就可以了解到多了一个s 简单的来说就是它可以将对象内的参数 多个传入 并且将其变成响应式的过程

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {toRef,reactive,toRefs} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const like = toRefs(who) 

const change = () => {
  console.log(like)
}

</script>

在这里直接上图

懂得了他的原理后 我们甚至可以手写他的过程 基本可以做到和源码大差不差

2.2手写toRefs的源码

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {toRef,reactive,toRaw} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const toRefs =<T extends object> (object:T)=>{
  const result = {} as any
  for (let key in object) {
    result[key] = toRef(object,key)
  }
  return result
}

const change = () => {
  console.log(toRefs(who))
}

</script>

上图

在这里获得效果基本与直接引用效果相同

toRefs的隐藏问题

假使 你想要直接解构它 通过

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {toRef,reactive,toRaw} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const toRefs =<T extends object> (object:T)=>{
  const result = {} as any
  for (let key in object) {
    result[key] = toRef(object,key)
  }
  return result
}
const {name,age,like} = who
const change = () => {
   who.name = '坤' 
  console.log(name,age,like)
}

</script>

打印出来的结果 值会变化 但是视图依旧是不会的

所以你需要在解构的时候加上 toRefs

const {name,age,like} = who

就可以解决这个问题啦

toRefs的源码

路径也是在ref.ts里面

基本和上面手写的一致

toRaw

toRaw的例子

这个首先我们不讲解 先通过代码先来了解一下这个是干什么的

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {reactive,toRaw} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const change = () => {
  console.log(who,toRaw(who))
}
</script>

打印出来如下

是不是很好理解 它将其的响应式干掉了 脱离了proxy

通过这样子的操作就可以让他不更新视图的展示了

toRaw手写源码

其实也就是一行的事情 大家可以去试试

vue-sfc 复制代码
<template>
  <div>
     <div>{{ who}}</div>
  </div>
  <hr>
  <button @click="change">+</button>
</template>

<script setup lang="ts">
import {reactive,toRaw} from 'vue'

const who = reactive({
  name:'kun',
  age:'2.5',
  like:'sing',
})

const change = () => {
  console.log(who,who['__v_raw'])
}
</script>

这个方法是看不到的 因为vue没有暴露出来

toRaw的源码

路径在reactive.ts中

就只有一小片

可以看到 他从对象中去获取了一个属性

点过去就可以看见这些了

相关推荐
u0111026752 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
jerrywus2 小时前
让 AI 写完代码后交一份报告:我改造了 answer-me-with-html
前端·claude·cursor
派小心.3 小时前
小程序分享链路中来源参数的传递校验
大数据·前端·数据库·人工智能·小程序·数据分析
hhb_6183 小时前
一键生成数据看板,ECharts实战演示
前端·javascript·echarts
Java后端的Ai之路3 小时前
08_React组件API
前端·react.js·前端框架
小马不起床3 小时前
零基础玩转 FastAPI_09:前端基础工程构建
前端·状态模式·fastapi
风骏时光牛马4 小时前
用户管理模块接口开发
前端
彭亚川Allen5 小时前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒5 小时前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端
软件技术NINI5 小时前
圣罗兰彩妆html+css 4页
前端·css·html