一文了解——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中

就只有一小片

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

点过去就可以看见这些了

相关推荐
理想不理想v6 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我7 分钟前
浏览器交互事件汇总
前端·交互
小阮的学习笔记20 分钟前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图
YBN娜20 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=21 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
杨荧23 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
minDuck25 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。1 小时前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼1 小时前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui