Vue3新特性Composition API的学习(三)

333 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

今天主要学习toRefs函数的使用,computed的计算属性,watch与watchEffect。

toRefs函数

toRefs函数可以将响应式对象中所有属性包装为ref对象,并返回包含这些ref对象的普通对象,比如在setup函数中返回一个使用扩展运算符对象类型的响应式数据,这时候这个对象类型的属性不再是响应式的,可以使用toRefs将对象中的每个属性都转换为响应式的

在代码中进行演示一下,先定义一个常规的变量state,包含两个属性,先正常引入使用,是可以正常的通过一个方法改变state中的属性值:

<template>
  <div>
    <div>{{ state.title }}:{{ state.price }}</div>
    <button @click="setState">更新数据</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive } from "vue";
export default defineComponent({
  name: "toRefs",
  setup() {
    let state = reactive({
      title: "杯子",
      price: 5,
    });
    let setState = () => {
      state.title = "眼镜";
      state.price = 100;
    };
    return {
      state,
      setState
    };
  },
});
</script>

这时候把setupreturn state的使用扩展运算符,再去修改,state内部属性就不是响应式的了,就需要用到toRefs

    return {
      ...state,
      setState
    };
<template>
  <div>
    <div>{{ title }}:{{ price }}</div>
    <button @click="setState">更新数据</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue"; // 使用前需要先引入toRefs
export default defineComponent({
  name: "toRefs",
  setup() {
    let state = reactive({
      title: "杯子",
      price: 5,
    });
    let setState = () => {
      state.title = "眼镜";
      state.price = 100;
    };
    return {
      ...toRefs(state),
      setState,
    };
  },
});
</script>

computed

vue2中已经使用的很普遍了,vue3是写法上有些不一样:

示例1:

<template>
  <div>
    <div>数量:{{ amount }}</div>
    <div>价格:{{ price }}</div>
    <div>总计:{{ total }}</div>
    <button @click="amount++">新增数量</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from "vue";
export default defineComponent({
  name: "computed",
  setup() {
    let amount = ref(1),
      price = 20,
      total = computed(() => {
        return price * amount.value;
      }),
    return {
      amount,
      price,
      total
    };
  },
});
</script>

示例2:

<template>
  <div>
    <div>用户名:<input v-model="setUsername" /></div>{{username}}
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from "vue";
export default defineComponent({
  name: "computed",
  setup() {
    let username = ref(""),
      setUsername = computed({
        get() {
          return username.value;
        },
        set(val: string) {
          username.value = val;
        },
      });
    return {
      setUsername,
      username
    };
  },
});
</script>

watch与watchEffect

watch

watch可以监听一个或多个响应式数据,一旦数据变化,就自动执行监听回调,如果是监听reactive对象中的属性,必须通过函数来指定如果监听多个数据,需要使用数组来指定,默认初始时不执行回调,但可以通过配置immediate为true,来指定初始化的时候立即执行一次,通过配置deep为true,来指定深度监听。

watchEffect

watchEffect可以不用直接指定要监听的数据,回调函数中使用的哪些响应式数据就监听哪些响应式数据,默认初始化的时候就执行一次。

<template>
  <div>
    {{ name }},<button @click="setName">修改姓名</button><br />
    {{ area.province }},{{ area.city }}
    <button @click="setArea">修改省市</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, watch, reactive, watchEffect } from "vue";
export default defineComponent({
  name: "watch",
  setup() {
    let name = ref("张三");
    let setName = () => {
      name.value = "李四";
    };
    //监听ref
    watch(name, (newVal: string, oldVal: string) => {
      console.log(newVal, oldVal);
    });
    let area = reactive({
      province: "山西",
      city: "大同",
    });
    //监听reactive
    let setArea = () => {
      area.province = "辽宁";
      area.city = "沈阳";
    };
    watch(
      () => area.province,
      (newVal: string, oldVal: string) => {
        console.log(newVal, oldVal);
      }
    );
    // 监听多个数据;
    watch(
      [() => area.province, () => area.city],
      (newVal: string, oldVal: string) => {
        console.log(newVal[0], newVal[1], oldVal[0], oldVal[1]);
      },
      {
        immediate: true, //初始化执行一次
        deep: true, //深度监听
      }
    );
    watchEffect(() => {
      console.log(area.province, area.city, name.value);
    });
    return {
      name,
      setName,
      area,
      setArea,
    };
  },
});
</script>

接下来继续学习Vue3的知识点~