preface

What does toRef do? You can use toRef to create a new REF for a property on a source responsive object. The REF can then be passed, maintaining a reactive connection to its source property.

What does toRef do?

As before, test the vue3 source code

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src=".. /vue/dist/vue.global.js"></script>
  <script>
    let { ref, effect, toRef, reactive }  = Vue
    let state = reactive({
      name: 'vvv'
    })
    let name = toRef(state, 'name')
    console.log(name);
    effect(() = > {
      app.innerHTML =  name.value
    })
    setTimeout(() = > {
      name.value = 'vvv2'
    }, 2000)
  </script>
</body>
</html>
Copy the code

Open your browser and see the results of the test

And you can see that through toRef it returns oneObjectRefImplExample, you can see thattoRefThe role of such asThe nameAgain, convert the value to zeroref

The realization of the toRef

The definition of toRef

export const toRef = (object, key, defaultValue?) = > {
  // Convert the value of an object to ref form
  const val = object[key]
  return isRef(val) ? val : new ObjectRefImpl(object, key, defaultValue)
}
Copy the code

IsRef in the previous vue3 source code – ref article has been explained, its role is to determine whether it has been ref

Core ObjectRefImpl class

/ / toRef core
class ObjectRefImpl {
  public readonly __v_isRef = true
  constructor(private readonly _object, private readonly _key, private readonly _defaultValue?) {}
  get value() {
    const val = this._object[this._key] / / value
    return val === undefined ? this._defaultValue : val // Whether to go to the default value
  }
  set value(newVal) {
    this._object[this._key] = newVal / / set the value}}Copy the code

One might ask why track and trigger are not used here. This is because toRef is mainly used for objects that have already been responded. For details, please refer to the official document toRef

Test toRef

Create a new toref.html file

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src=".. /node_modules/@vue/reactivity/dist/reactivity.global.js"></script>
  <script>
    let { ref, effect, toRef, reactive }  = VueReactivity
    let state = reactive({
      name: 'vvv'
    })
    let name = toRef(state, 'name')
    console.log(name);
    effect(() = > {
      app.innerHTML =  name.value
    })
    setTimeout(() = > {
      name.value = 'vvv2'
    }, 2000)
  </script>
</body>
</html>
Copy the code

Open up a browser and see how we’re doing

In order to be recognizable, I’m inObjectRefImplAdd a prefixMy

The realization of the toRefs

ToRefs is the one you use most in your project, because toRef can only convert one layer, so it is relatively rare. So let’s implement toRefs

export const toRefs = (object) = > {
  // loop over gradual toRef
  let ret = isArray(object)?new Array(Object.length) : {}
  for (let key in object) {
    ret[key] = toRef(object, key)
  }
  return ret
}
Copy the code

ToRefs is relatively simple to implement, looping over gradually toRef

Test toRefs

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src=".. /node_modules/@vue/reactivity/dist/reactivity.global.js"></script>
  <script>
    let { ref, effect, toRef, reactive, toRefs }  = VueReactivity
    let state = reactive({
      name: 'vvv'.age: 18
    })
    let my = toRefs(state)
    console.log(my.name);
    console.log(my.age);

    effect(() = > {
      app.innerHTML =  my.name.value + '= = = = =' + my.age.value
    })
    setTimeout(() = > {
      my.name.value = 'vvv2'
      my.age.value = 'the'
    }, 2000)
  </script>
</body>
</html>
Copy the code

May nowtoRefsUse is also relatively less, after all, now outsetupGrammar sugar, not inreturnOut, but I believe,Better to have learned than not to have learnedTrust yourself to use it

ToRef and toRefs are already implemented, vuE3 source code and other related implementations wait for the next article

The last

If you find this article helpful, please like 👍🏻, add ⭐️ and follow 🏻

Vue3 source code implementation series

Vue3 source code – Reactive data Reactive

Vue3 source-effect relies on collecting triggered updates

Vue3 source code – ref article

Vue3 source code – toRef and toRefs