Vue3 toRef、toRefs

toRef

作用:创建一个 ref 对象,其 value 值指向另一个对象中的某个属性。
语法:const name = toRef(person, ' name ')
应用:要将响应式对象中的某个属性单独提供给外部使用时
扩展:toRefstoRef 功能一致,但可以批量创建多个 ref 对象
语法:toRefs(person)

在 Vue3的响应式 中,我们写了一段 js 来模拟 vue3 的响应式

<script>
        //源数据
        let person = {
            name:"张三",
            age:18
        }
        const p = new Proxy(person,{
            //有人读取p的某个属性时调用
            get(target, p, receiver) {
                console.log(`有人读取了p身上的${p}属性`);
                //return target[p]
                return Reflect.get(target,p)
            },
            //有人修改、增加p的某个属性时调用
            set(target, p, value, receiver) {
                console.log(`有人修改了p身上的${p},我要去更新界面了`);
                //target[p] = value
                Reflect.set(target,p,value)
            },
            //有人删除p的某个属性时调用
            deleteProperty(target, p) {
                console.log(`有人删除了p身上的${p},我要去更新界面了`);
                //return delete target[p]
                return Reflect.deleteProperty(target,p)
            }
        })
    </script>

Vue3 toRef、toRefs_第1张图片
当修改 p 的属性时,会检测到然后打印相应信息,现在在刚才这段 js 最后增加一句以下代码,然后我们尝试修改 name 属性

let name = p.name

先输出 person 、 p 、name 看下结构,然后修改 name,发现只是修改了 name,p 中的值并未受到影响
Vue3 toRef、toRefs_第2张图片
然后我们来看下面一段代码,也是我们之前写过的例子,一个人的信息,然后点击按钮进行修改
Vue3 toRef、toRefs_第3张图片

<template>
  <h2>{{ person }}h2>
  <h2>姓名:{{ name }}h2>
  <h2>年龄:{{ age }}h2>
  <h2>薪资:{{ salary }}Kh2>
  <button @click="name+='~'">修改姓名button>
  <button @click="age++">修改年龄button>
  <button @click="salary++">涨薪button>
template>

<script>
import {reactive, toRef} from 'vue'

export default {
  name: 'Demo',
  setup() {
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

    const name1 = person.name;
    console.log("name1", name1);

    const name2 = toRef(person.name);
    console.log("name2", name2);

    return {
      person,
      name: toRef(person, "name"),
      age: toRef(person, "age"),
      salary: toRef(person.job.j1, "salary"),
    }
  }
}
script>

之前我们 return 中只返回 person,然后取值时使用 person.name、person.age等,如果我们想返回它的某些字段,就需要使用 toRef,例如返回 name 属性 name:toRef(person, "name")这样才能让数据依然是响应式的,在模板中可以直接使用 {{name}} 就可以取到值。如果在 return 中直接像以下代码这样写是不行的,因为返回的 name 不是响应式的

	错误代码:
	return {
      name: person.name,
      age: person.age,
      salary: person.job.j1.salary,
    }
	错误代码:
	return {
      ...person
    }

上边代码中我们输出了 name1 和 name2,可以看到 name1 仅仅是一个字符串,而 name2 是一个 ObjectRefImpl 。这就解释了为什么直接返回 person.name 不是响应式的了
Vue3 toRef、toRefs_第4张图片

toRefs

还是上边的代码,我们使用 toRefs,把 person 的第一层拆出来形成了一个对象,我们打印看看

	const x = toRefs(person);
    console.log(x);

在这里插入图片描述
所以刚才的代码可以改为:

<template>
  <h2>{{ person }}h2>
  <h2>姓名:{{ name }}h2>
  <h2>年龄:{{ age }}h2>
  <h2>薪资:{{ job.j1.salary }}Kh2>
  <button @click="name+='~'">修改姓名button>
  <button @click="age++">修改年龄button>
  <button @click="job.j1.salary++">涨薪button>

template>

<script>
import {reactive,toRefs} from 'vue'

export default {
  name: 'Demo',
  setup() {
    let person = reactive({
      name: "张三",
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

    const x = toRefs(person);
    console.log(x);

    return {
      person,
      ...toRefs(person)
    }
  }
}
script>

或者

const {name,age,job} =  toRefs(person);
    return {
      person,
      name,
      age,
      job
    }

ref

在 vue2 中我们可以通过给元素添加ref=‘xxx’,然后在代码中通过refs.xxx的方式来获取元素。在 vue3 中也可以通过 ref 来获取元素,但不是像刚才说的方式,因为在 vue3 中没有$refs这些东西,我们可以通过一个例子来说明下,添加一个 input,让它自动获取焦点功能:

<template>
  <input type="text" ref="inputRef"/>
</template>

<script lang="ts">
import {defineComponent, ref,onMounted} from 'vue';

export default defineComponent({
  setup() {
    const inputRef = ref<HTMLElement|null>(null);
    //页面加载后的生命周期
    onMounted(()=>{
      inputRef.value && inputRef.value.focus()
    })

    return{
      inputRef
    }
  }
});
</script>

在这里插入图片描述

你可能感兴趣的:(Vue学习笔记,vue)