vue3 响应式

477 阅读3分钟

vue3 响应式

学会ref, reactive, toRef, toRefs彻底掌握vue3响应式应用。

1. ref

ref函数一般用于基本数据类型,包括(string,number,boolean等),也可以用于对象,但是该对象仅仅包含一属性,例如({age:20});

1.1 ref 基本数据类型

<div class="home">
    <h1>员工姓名原始值:{{ name }}</h1>
    <h1>员工姓名:{{ ref_name }}</h1>
    <h1>年龄:{{ age }}</h1>
    <button @click="change">修改</button>
  </div>
  
  setup() {
    let name = "zha san";
    let ref_name = ref(name);
    console.log(ref_name);
    }
    
    return {
      name,
      ref_name,
      age,
      change,
    };

打印输出的ref返回的是一个RefIml对象,响应值存在这个对象的value属性中。

所以如果我们想修改响应数据的值,必须修改ref_namevalue值,界面的值才会发生刷新。

   function change() {
      ref_name.value = "li si";
      console.log("name:", name);
      console.log(ref_name);
    }

此处我们需要注意,原始值name的值并没有改变,依旧是“zha san”。

修改后页面展示如下:

另外我们可以改变原始值,但是原始值{{ name }}的绑定并不会更新成“wang wu”.

 function change() {
      name = "wang wu";
   }

1.2 Ref 单属性对象

 <div class="home">
    <h1>员工姓名原始值:{{ data.name }}</h1>
    <h1>员工姓名:{{ ref_data.name }}</h1>
    <button @click="change">修改</button>
  </div>
  
setup() {
  let data = { name: "zha san" };
  let ref_data = ref(data);
  console.log(data.name);
  console.log(ref_data);

  function change() {
    ref_data.value.name = "li si";
    console.log("原始name值依旧是:", data.name);
    console.log(ref_data);
  }
  return {
    data,
    ref_data,
    change,
  };

点击修改后:

可见用对象作为Ref参数,原始值也受到了影响,因为对象传递的是引用值。

1.3 Ref对象属性

与1.2的代码改动如下:

<h1>员工姓名:{{ ref_data }}</h1>

let ref_data = ref(data.name);

修改后:

发现原始值并没有改变,因为这是值拷贝。

2. reactive

reactive函数的参数一般为引用类型,如(Object, Array),如果我们直接传入基本数据类型,vue会给我们一个警告,并且直接返回基本数据类型的值。

通过以上的示例我们发现,用Ref变量,当我们需要修改绑定数据的时候需要修改value属性(template里不需要加value是因为编译时已经处理过了),那么我们能不能优化一下上面的代码,不使用value呢? 答案是肯定的,就是用reactive。

  <div class="home">
    <h1>员工姓名原始值:{{ name }}</h1>
    <h1>员工姓名:{{ reactive_data.name }}</h1>
    <h1>年龄:{{ reactive_data.age }}</h1>
    <button @click="change">修改</button>
  </div>
   setup() {
    let data = {
      name: "zha san",
      age: 18,
    };
    let reactive_data = reactive(data);
    console.log(reactive_data);

    function change() {
      reactive_data.name = "li si2";
      console.log("原始name值改变为:", data.name);
      console.log(reactive_data);
    }
    return {
      data,
      reactive_data,
      change,
    };
  },

我们来看一下reactive长什么样子:

点击修改后:

我们发现原始值和响应值都改变了,这也是引用传递的结果。

这里我们顺便解构一下reacitvie对象,已不是响应式对象:

 console.log({ ...reactive_data });

3. toRefs

细心的读者可能已经发现了,我们上面teplate绑定的时候还是需要加一个data前缀,我们改如何去掉它呢?对了,就是用toRefs函数。toRefs对象接受一个reactive对象,代码如下:

  <div class="home">
    <h1>员工姓名原始值:{{ data.name }}</h1>
    <h1>员工姓名:{{ name }}</h1>
    <h1>年龄:{{ age }}</h1>
    <button @click="change">修改</button>
  </div>
  
  setup() {
    let data = {
      name: "zha san",
      age: 18,
    };
    let reactive_data = reactive(data);
    let refs = toRefs(reactive_data);
    console.log(refs);

    function change() {
      reactive_data.name = "li si2";
      console.log("原始name值改变为:", data.name);
      console.log(refs);
    }
    return {
      data,
      ...refs,
      change,
    };
  },

refs对象如下:

点击修改后toRefs的值为:

4 toRef

此函数接收两个参数,第一个参数为原对象,第二个参数为对象中的某一个属性名。

 <div class="home">
    <h1>员工姓名原始值:{{ data.name }}</h1>
    <h1>员工姓名:{{ ref }}</h1>
    <button @click="change">修改</button>
  </div>
  setup() {
    let data = {
      name: "zha san",
    };
    let ref = toRef(data, "name");
    console.log(ref);
    function change() {
      ref.value = "li si2";
      console.log("原始name值改变为:", data.name);
      console.log(ref);
    }
    return {
      data,
      ref,
      change,
    };
  },

toRef返回对象格式如下:

点击修改后:

发现原始值也改变了,证明这里跟Ref比,传递的是引用值,实际上是就是同一个对象。

但是修改数据后界面并不会刷新!!!

只要大家掌握了这几种响应式的区别,明白响应式的核心是proxy。开发中可以根据实际情况灵活运用,并不拘泥用哪一个~~~

最后如有疑问,欢迎各位提出宝贵意见~~