Catalyst

Vue3 的组合式 API

笔记,免得每次都去翻文档

vue3 的组合式 API(Composition API) 表示 vue 也开始 fp 了,好(鼓掌 👏)。

基础用法

写在setup 中:

const App = {
  data() {
    return {
      message: "Hello!",
    };
  },
  setup() {
    //写入 setup
  },
};

Vue.createApp(App).mount("#app");
  • setup里可以有变量和函数,但需要在外使用的都要靠return返回。
  • 创建setup时组件实例还未创建,所以无法使用this。(这很 fp)
  • 但是可以访问:props,attrs,slots,emit

参数

setup接受两个参数:

  • props:组件的props。(响应式)
  • context:组件的属性{attrs,slots,emit}
app.component("MyMessage", {
  props: {
    msg: String,
  },
  setup(props) {
    const msg = props.msg;
    return { msg };
  },
  template: `<h1>{{msg}}</h1>`,
});

响应式变量

对于响应式变量(需要双向绑定的变量),使用ref函数包裹:

import { ref } from "vue"; //要单独导入!
//非模板下使用 Vue.ref
const message = ref("Hello");

ref针对的是一般变量,如果包裹对象使用reactive

如果想在setup里对ref变量进行修改,则需要使用<变量>.value的形式访问值(在模板中/reactive中不需要)。

使用两种方式改变变量:

<div id="app">
  <p>{{message}}</p>
  <p>method: <input type="text" @input="onMethod" /></p>
  <p>setup : <input type="text" @input="onSetup" /></p>
</div>
const App = {
  setup() {
    const message = Vue.ref("Hello!");
    const group = Vue.reactive({ num: 0 });

    function onSetup(event) {
      message.value = event.target.value;
      group.num++;
    }
    return { message, onSetup };
  },
  methods: {
    onMethod: function (event) {
      this.message = event.target.value;
      this.group.num++;
    },
  },
};

Vue.createApp(App).mount("#app");

生命周期钩子

生命周期钩子也可以写在setup中,基本处理方法是在前面加上 on

选项式 APIHook inside setup
beforeCreateNot needed*
createdNot needed*
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
errorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered

比如再修改一下上面的代码:

const App = {
  setup() {
    const message = Vue.ref("Hello!");

    //模板中不需要 `Vue`
    Vue.onMounted(() => {
      message.value = "Mounted!";
    });

    return { message };
  },
};

Vue.createApp(App).mount("#app");

Watch 和 Computed

Watch 和 Computed 也可以写在setup中。

const App = {
  setup() {
    const message = Vue.ref("Hello!");
    const info = Vue.ref("");
    const computed_message = Vue.computed(() => `🥳${message.value}🥳`);

    Vue.watch(message, (newValue, oldValue) => {
      info.value = "上次 Message 的值是:" + oldValue;
    });

    //中略

    return { message, info, computed_message, onSetup };
  },
};

Vue.createApp(App).mount("#app");

使用watch时发现要求第一个参数要是对象。如果想要监听 props 的话,则传入一个返回 prop 值的函数(()=>props.value)。

script setup

一个新的 SFC 下的语法糖。使用方法:

<script setup>
  ...
</script>

代码会在每次组件实例被创建的时候执行。

  • <script setup> 中的顶层绑定(变量、函数等)和导入的 import 都会暴露给模板,不用写长长的 return 了。
  • 导入的组件也可以直接在模板中使用。
  • 使用 definePropsdefineEmits 声明propsemits
  • 使用 defineExpose 明确暴露给外界(其它组件)的变量。
  • 使用 useSlotsuseAttrs 辅助函数调用 slotsattrs
  • 可以和普通的<script>一起使用。

返回渲染函数

模板不要,完全 fp 化()

app.component("MyMessage2", {
  props: {
    msg: String,
  },
  setup(props) {
    const msg = props.msg;
    return () => Vue.h("h1", [msg]);
  },
});

同理也能返回 jsx,但对于仅返回渲染用内容官方推荐使用render()函数返回。