手撕Vue源码之——ref

前言

上一篇文章给大家介绍了reactive的原理及实现一个简单的reactive(手撕Vue源码之------reactive),这篇文章就给大家介绍一下refref也是实现响应式的一种方法,但是它一般用于让原始类型的数据变成响应式,当然也可以是引用类型,但是一般不用,至于为什么之后会给大家说明的

思路

从vue打造好的ref来看,它接收一个参数,可以是简单类型也可以是引用类型,然后返回的是一个对象,从获取值需要使用.value就可以看出来,ref返回的结果是一个对象。

js 复制代码
import { track, trigger } from './effect.js'
import { reactive } from './reactive.js'


export function ref(val) {      // 将原始类型数据变成响应式  引用类型也可以
    return createRef(val)
}

function createRef(val) {
    // 判断val是否已经是响应式
    if (val.__v_isRef) {
        return val
    }
    
    // 将val变为响应式
    return new RefIpml(val)
}

class RefIpml {
    constructor(val) {
        this.__v_isRef = true    // 给每一个被ref操作过的属性值都添加标记
        this._value = convert(val)       // 一种人为约定俗成的写法,加了_的属性都默认为私有属性,不会直接拿到外面去用
    }
    get value() {
        // 为this对象做依赖收集
        track(this, 'value')    // key可以随便写,就统一用value,track和trigger里的key要统一
        return this._value
    }
    set value(newVal) {
        if (newVal !== this._value) {
            this._value = convert(newVal)
            trigger(this, 'value')      // 触发掉'value'上的所有副作用函数
        }
    }
}

function convert(val) {
    if (typeof val !== 'object' || val === null) {      // 不是对象
        return val
    } else {
        return reactive(val)
    }
}

因为Proxy只接受对象作为参数,而ref可以把简单数据类型变成响应式,所以我们就自己打造一个RefIpml类,这里先补充一个知识点,js中的对象天生拥有getset的能力。

js 复制代码
let obj = {
    name: 'Tom',
    get age() {
        return 18
    },
    set age(newVal) {
        console.log(newVal);
    }
}

obj.age = 18
console.log(obj.age);    // 相当于obj.age()

在函数前面加上get就可以直接使用对象名.函数名获取函数的返回结果,同理set也是,这样就不用每次都要去调用这个函数进行触发。

这里面还用到了我们上次在reactive中使用到的track方法和trigger方法,既然是响应式,那么ref自然也需要进行依赖收集和触发,代码片段里都有注释,相信大家也能看的懂,接下来我就讲讲为什么ref一般不用于引用类型而常用于简单数据类型。

从上面的代码也能看到,当ref如果接受的是一个对象的话,它是直接调用了reactive方法,把reactive的结果返回了出来,实际上vue的源码里也是这么写的,当给ref的参数是对象时,相当于就是在ref里面调用reactive,然后使用reactive返回的结果作为.value的值,这看着就有一点点多此一举。

结语

实际上变成响应式的核心就是Proxy方法,但是Proxy只能接受对象作为参数,所以才不得已再多打造一个ref用来使简单数据类型也能变成响应式数据,所以一般数据源比较多的时候就用reactive,数据源比较少的时候就用ref

假如您也和我一样,在准备春招。欢迎加我微信shunwuyu,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
u***u68514 小时前
React环境
前端·react.js·前端框架
X***E46314 小时前
前端数据分析应用
前端·数据挖掘·数据分析
4***149014 小时前
React社区
前端·react.js·前端框架
LFly_ice14 小时前
学习React-24-路由传参
前端·学习·react.js
Lhuu(重开版15 小时前
CSS:动效布局动画
前端·css
Q***K5515 小时前
前端构建工具
前端
laocooon52385788615 小时前
创建了一个带悬停效果的“我的个人主页“按钮
前端
2013编程爱好者16 小时前
Vue工程结构分析
前端·javascript·vue.js·typescript·前端框架
小满zs17 小时前
Next.js第十一章(渲染基础概念)
前端
不羁的fang少年18 小时前
前端常见问题(vue,css,html,js等)
前端·javascript·css