1. toRef

:::success

  • 作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性
  • 语法:const name = toRef(person,’name’)
  • 应用: 要将响应式对象中的某个属性单独提供给外部使用时。
  • 扩展:toRefstoRef功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person) ::: toRef toRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用,也就是你从 reactive 复制过来的属性进行修改后,除了视图会更新,原有 ractive 里面对应的值也会跟着更新。
    1. <script>
    2. import { reactive } from 'vue'
    3. export default {
    4. setup() {
    5. const person = reactive({
    6. name:'IRIC',
    7. age:12,
    8. sex:'女',
    9. job:{
    10. salery:20
    11. }
    12. })
    13. console.log(person.name) //'IRIC'
    14. console.log(person) //Proxy {name: 'IRIC', age: 12, sex: '女', job: {…}}
    15. console.log(toRef(person, 'name')) //ObjectRefImpl {_object: Proxy, _key: 'name', _defaultValue: undefined, __v_isRef: true}
    16. return {
    17. name:person.name,
    18. age:person.age,
    19. salery:person.job.salery,
    20. }
    21. },
    22. }
    23. </script>
    这样写初次展示并没有问题, 但是点击修改的时候并不会生效, 因此name:的属性值person.name其实是他的值IRIC, 他不是一个响应式的值。所以点击的时候并不会生效, 因为此时的name已经不是响应式数据了。
    如果不使用toRef: ```javascript

  1. 使用toRef:
  2. ```javascript
  3. <template>
  4. <h2>姓名:{{name}}</h2>
  5. <h2>年龄:{{age}}</h2>
  6. <h2>性别:{{sex}}</h2>
  7. <h2>薪资:{{salery}}</h2>
  8. <hr>
  9. <button @click="name += '@'">修改姓名</button>
  10. <button @click="age ++">修改年龄</button>
  11. <button @click="salery ++">修改薪资</button>
  12. </template>
  13. <script>
  14. import { reactive, toRef } from 'vue'
  15. export default {
  16. setup() {
  17. const person = reactive({
  18. name:'IRIC',
  19. age:12,
  20. sex:'女',
  21. job:{
  22. salery:20
  23. }
  24. })
  25. const name = toRef(person, 'name');
  26. const age = toRef(person, 'age');
  27. const sex = toRef(person, 'sex');
  28. const salery = toRef(person.job, 'salery');
  29. return {
  30. name,
  31. age,
  32. sex,
  33. salery
  34. }
  35. },
  36. }
  37. </script>

如果改成这样:

  1. <template>
  2. <h2>姓名:{{name}}</h2>
  3. <h2>年龄:{{age}}</h2>
  4. <h2>性别:{{sex}}</h2>
  5. <h2>薪资:{{job.salery}}</h2>
  6. <hr>
  7. <button @click="name += '@'">修改姓名</button>
  8. <button @click="age ++">修改年龄</button>
  9. <button @click="job.salery ++">修改薪资</button>
  10. </template>
  11. <script>
  12. import { reactive, toRef } from 'vue'
  13. export default {
  14. setup() {
  15. const person = reactive({
  16. name:'IRIC',
  17. age:12,
  18. sex:'女',
  19. job:{
  20. salery:20
  21. }
  22. })
  23. const name = toRef(person, 'name');
  24. const age = toRef(person, 'age');
  25. const sex = toRef(person, 'sex');
  26. const job = toRef(person, 'job');
  27. console.log(name)
  28. console.log(job)
  29. return {
  30. name,
  31. age,
  32. sex,
  33. job
  34. }
  35. },
  36. }
  37. </script>

name的value值是:
image.png
job依然是响应式的:
image.png
如果直接ref, 则出现数据分离问题;下面的数据和person不是同一个数据。造成原始数据不会发生变化。 被修改的是用ref重新定义的变量。

  1. <template>
  2. <h2>{{person}}</h2>
  3. <h2>姓名:{{name}}</h2>
  4. <h2>年龄:{{age}}</h2>
  5. <h2>性别:{{sex}}</h2>
  6. <h2>薪资:{{job.salery}}</h2>
  7. <hr>
  8. <button @click="name += '@'">修改姓名</button>
  9. <button @click="age ++">修改年龄</button>
  10. <button @click="job.salery ++">修改薪资</button>
  11. </template>
  12. <script>
  13. import { reactive, toRefs,ref } from 'vue'
  14. export default {
  15. setup() {
  16. const person = reactive({
  17. name:'IRIC',
  18. age:12,
  19. sex:'女',
  20. job:{
  21. salery:20
  22. },
  23. address:''
  24. })
  25. return {
  26. person,
  27. name: ref(person.name),
  28. age: ref(person.age),
  29. sex: ref(person.sex),
  30. job: ref(person.job)
  31. }
  32. },
  33. }
  34. </script>

image.png

2. toRefs:

  1. <template>
  2. <h2>姓名:{{name}}</h2>
  3. <h2>年龄:{{age}}</h2>
  4. <h2>性别:{{sex}}</h2>
  5. <h2>薪资:{{job.salery}}</h2>
  6. <hr>
  7. <button @click="name += '@'">修改姓名</button>
  8. <button @click="age ++">修改年龄</button>
  9. <button @click="job.salery ++">修改薪资</button>
  10. </template>
  11. <script>
  12. import { reactive, toRefs } from 'vue'
  13. export default {
  14. setup() {
  15. const person = reactive({
  16. name:'IRIC',
  17. age:12,
  18. sex:'女',
  19. job:{
  20. salery:20
  21. }
  22. })
  23. return { ...toRefs(person) }
  24. },
  25. }
  26. </script>

3. ref和toRef的区别

(1). ref本质是拷贝,修改响应式数据不会影响原始数据;toRef的本质是引用关系,修改响应式数据会影响原始数据
(2). ref数据发生改变,界面会自动更新;toRef当数据发生改变是,界面不会自动更新
(3). toRef传参与ref不同;toRef接收两个参数,第一个参数是哪个对象,第二个参数是对象的哪个属性
toRef: 复制 reactive 里的单个属性并转成 ref
toRefs: 复制 reactive 里的所有属性并转成 ref