Vue3.0 - Composition API的使用

Vue3.0 中Composition API的使用

  • 一. Composition API 和 Options API
  • 二. setup()
  • 三. reactive
  • 四. ref
  • 五. toRefs
  • 六. readonly
  • 七. computed
  • 八. watch
  • 九. 生命周期钩子函数
  • 十. 模板refs
  • 十一. 依赖注入(组件之间数据传递)

一. Composition API 和 Options API

  1. Options API选项api
    (1)Options API 的优点是容易学习和使用,代码有明确的书写位置。
    (2)Options API 的缺点是相似逻辑不容易复用,在大项目中尤为明显。
    (3)Options API 可以通过mixins提取相同的逻辑,但是容易发生命名冲突且来源不清晰。
  2. Composition API 组合API
    (1)Composition API 是根据逻辑功能来组织代码的,一个功能所有的api放到一期。
    (2)即便项目很大,功能很多,都能够快速的定位到该功能的所有API。
    (3)Composition API 提供了代码可读性和可维护性。
  3. Vue3.0 中推荐使用 Composition API,也保留了 Options API

二. setup()

  1. setup() 函数是一个新的组件选项,作为组件中 Composition API 的起点。
  2. 从生命周期钩子的角度来看,setup() 会在 beforeCreate 钩子函数之前执行。
  3. setup() 中不能执行 thisthis 指向 undefined
<template>
  <div>app</div>
</template>

<script>
export default {
  setup() {
    console.log("setup执行了");
  },
  beforeCreate() {
    console.log("beforeCreate执行了");
  },
};
</script>

三. reactive

reactive 函数接受一个普通对象,返回该对象的响应式代理。

<template>
  <div>{{ arr.title }}{{ arr.num }}</div>
  <button @click="arr.num++">修改</button>
</template>

<script>
import { reactive } from "vue";
export default {
  setup() {
    let arr = reactive({
      title: "名称",
      num: 100,
    });
    return {
      arr,
    };
  },
};
</script>

四. ref

  1. ref 函数接受一个简单类型的值,返回一个可改变的 ref 对象,返回的对象有唯一的属性 value
  2. setup() 函数中,通过 ref 对象的 value 属性可以访问到值。
  3. 在模板中,ref 属性会自动解套,不需要额外的 .value
  4. 如果 ref 接受的是一个对象,会自动调用 reactive
<template>
  <div>{{ title }}</div>
  <button @click="title = '名称2'">修改</button>
</template>

<script>
import {ref} from 'vue'
export default {
  setup() {
    let title = ref("名称1");
    return {
      title,
    };
  },
};
</script>

五. toRefs

  1. 把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref
  2. reactive 的响应式功能都是赋予给对象的,但是如果给对象结构或者展开的时候,会让数丢失响应式的能力。
  3. 使用 toRefs 可以保证该对象展开的每一个属性都是响应式的。
<template>
  <div>{{ mame }}</div>
  <div>{{ arr.title }}{{ arr.num }}</div>
  <button @click="mame = 'ls'">修改</button>
  <button @click="arr.num++">修改</button>
</template>

<script>
import { reactive, toRefs } from "vue";
export default {
  setup() {
    let state = reactive({
      mame: "zs",
      arr: {
        title: "名称",
        num: 100,
      },
    });
    return {
      ...toRefs(state),
    };
  },
};
</script>

六. readonly

  1. 传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理。
  2. 一个只读的代理是“深度的”,对象内部任何嵌套的属性也都是只读的。
  3. 可以防止对象被修改。
<template>
  <div>{{ num }}</div>
  <button @click="num++">修改</button>
</template>

<script>
import { ref, readonly } from "vue";
export default {
  setup() {
    let num = ref(100);
    return {
      num: readonly(num),
    };
  },
};
</script>

七. computed

  1. computed 函数用于创建一个计算属性。
  2. 如果传入的是一个 getter 函数,会返回一个不允许修改的计算属性。
  3. 如果传入的是一个带有 gettersetter 函数的对象,会返回一个允许修改的计算属性。
<template>
  <div>今年年龄:<input v-model="age" /></div>
  <div>明年年龄:<input v-model="nextAge" /></div>
  <div>后年年龄:<input v-model="nextAge2" /></div>
</template>

<script>
import { ref, computed } from "vue";
export default {
  setup() {
    let age = ref(19);
    // 计算属性
    // 1.传入一个函数 getter ,返回一个不允许修改的计算属性
    let nextAge = computed(() => {
      return parseInt(age.value) + 1;
    });
    // 2.传入一个对象,包括get和set,可以创建一个可以被修改的计算属性
    let nextAge2 = computed({
      get() {
        return parseInt(age.value) + 2;
      },
      //   接收一个参数,当前的值
      set(value) {
        age.value = value - 2;
      },
    });
    return {
      age,
      nextAge,
      nextAge2,
    };
  },
};
</script>

八. watch

  1. watch 函数接收3个参数:
    (1)参数1:数据源,可以是 ref 或者 getter 函数。
    (2)参数2:回调函数。
    (3)参数3:额外选项,是一个对象。immediatedeep
    {deep:true} 深度监听
    {immediate:true} 立即监听
  2. watch 可以监听一个 ref 或者一个带有返回值的 getter 函数。
  3. watch 可以监听单个数据源,也可以监听多个数据源。
  4. watch 函数会有返回值,用于停止监听。
<template>
  <div>数据1:{{ num1 }}</div>
  <button @click="num1++">按钮1</button>
  <br />
  <div>数据2:{{ num2 }}</div>
  <button @click="num2++">按钮2</button>
  <br />
  <div>数据3:{{ arr.title }}</div>
  <button @click="arr.title = '奔驰'">按钮3</button>
</template>

<script>
import { reactive, ref, toRefs, watch } from "vue";
export default {
  setup() {
    let state = reactive({
      num1: 100,
      arr: {
        title: "宝马",
      },
    });
    let num2 = ref(100);
    // 监听一个state中的值
    watch(
      () => state.num1,
      (newValue, oldValue) => {
        console.log("数据1发生变化", newValue, oldValue);
      }
    );
    // 监听一个单独的数据
    watch(num2, (newValue, oldValue) => {
      console.log("数据2发生变化", newValue, oldValue);
    });
    // 监听一个state中的对象
    watch(
      () => state.arr,
      (newValue) => {
        console.log("数据3发生变化", newValue);
      },
      {
        deep: true,
        immediate: false,
      }
    );
    // 监听多个值
    watch(
      [() => state.arr, num2],
      ([newArr, newNum]) => {
        console.log("数据4发生变化", newArr, newNum);
      },
      {
        deep: true,
      }
    );
    // 监听整个state
    watch(
      state,
      (newValue) => {
        console.log("state变化了", newValue);
      },
      { deep: true }
    );
    return {
      ...toRefs(state),
      num2,
    };
  },
};
</script>

九. 生命周期钩子函数

  1. Vue3 提供的生命周期钩子注册函数只能在 setup() 期间同步使用。
  2. Vue3 生命周期钩子函数与 Vue2 对比:
    (1)beforCreate > 使用 setup()
    (2)created > 使用setup()
    (3)beforeMount > onBeforeMount
    (4)mounted > onMounted
    (5)beforeUpdate > onBeforeUpdate
    (6)update > onUpdate
    (7)beforeDestroy> onBeforeUnmount
    (8)destroyed > onUnmounted
    (9)errorCaptured > onErrorCaptured

十. 模板refs

为了获得对模板内元素和组件实例的引用,我们可以像往常一样在 setup() 中声明一个 ref 并返回它。

<template>
  <div ref="hRef">模板ref</div>
</template>

<script>
import { ref, onMounted } from "vue";
export default {
  setup() {
    let hRef = ref(null);
    onMounted(() => {
      console.log(hRef.value.innerHTML);
    });
    return {
      hRef,
    };
  },
};
</script>

十一. 依赖注入(组件之间数据传递)

https://v3.cn.vuejs.org/guide/component-provide-inject.html

  1. Vue3中提供了 provideinject 提供依赖注入,用于实现组件之间的通讯。类似于Vue2中的 provideinject
  2. Vue3提供的 provideinject 可以用于跨多级组件进行通讯。

祖级组件:

<template>
  <div>这是祖级组件:{{ num }}</div>
  <button @click="num++">修改</button>
  <br /><br />
  <Child></Child>
</template>

<script>
import { ref, provide } from "vue";
import Child from "./Child.vue";
export default {
  components: {
    Child,
  },
  setup() {
    let num = ref(100);
    // 后代组件调用的方法
    let changeNum = (v) => {
      // v : 后代组件传递过来的值
      num.value = v;
    };
    // 向后代级组件提供属性
    provide("num", num);
    provide("changeNum", changeNum);
    return {
      num,
    };
  },
};
</script>

子组件

<template>
  <div>这是子组件:{{ num }}</div>
  <br /><br />
  <Grand></Grand>
</template>

<script>
import { inject } from "vue";
import Grand from "./Grand.vue";
export default {
  components: {
    Grand,
  },
  setup() {
  	// 接受父组件传过来的值
    let num = inject("num");
    return {
      num,
    };
  },
};
</script>

孙子组件:

<template>
  <div>这是孙子组件:{{ num }}</div>
  <button @click="fn">修改</button>
</template>

<script>
import { inject } from "vue";
export default {
  setup() {
  	// 接受祖级组件传过来的值
    let num = inject("num");
    // 修改祖级组件中的数据
    let changeNum = inject("changeNum");
    let fn = () => {
      // 传参改变祖级组件中的数据
      changeNum(200);
    };
    return {
      num,
      fn,
    };
  },
};
</script>

你可能感兴趣的:(#,Vue__Vue3.0的使用,vue)