# setup

vue3的 setup的组合式API,从我个人习惯来说 <script setup lang="ts"> 这种方式也是一种可选的方式, 但是需要涉及到比如render函数这种, 感觉还是作为options api的setup函数, 更加合适, 所以也来看一下这种方式的typescript写法。

# 定义Props

<template>
  <div>
    <p>props: {{title}}</p>
  </div>
</template>
<script lang="ts">
// import { ref } from 'vue'
interface Props {
  title: string;
}
export default {
  name: 'Child',
  props: {
    title: String
  },
  setup(props: Props) {
    return {};
  }
};
</script>
<style lang='stylus' scoped></style>

# SetupContext

import { ref, SetupContext } from 'vue';
setup(props: Props, context: SetupContext) {
  /* 
  // Attribute (非响应式对象,等同于 $attrs)
  console.log(context.attrs)
  // 插槽 (非响应式对象,等同于 $slots)
  console.log(context.slots)
  // 触发事件 (方法,等同于 $emit)
  console.log(context.emit)
  // 暴露公共 property (函数)
  console.log(context.expose)
    */
  return {  };
}

# 使用渲染函数

<script lang="ts">
import { h, reactive, ref } from 'vue';
export default {
  name: 'Render',
  setup() {
    const number = ref(0);
    const book = reactive<{ title: string }>({ title: 'Hello' });
    const list = reactive<number[]>([1, 2, 3]);
    return () =>
      h(
        'div',
        {
          class: 'bg-gray-100',
          style: { color: 'red' }
        },
        [
          h('span', [number.value, book.title]),
          h(
            'ul',
            {},
            list.map((num) => h('li', num))
          )
        ]
      );
  }
};
</script>

这样子的话就不用写模板了,注意返回的是一个渲染函数, 而不是一个VNode。

关于h函数的第二个参数, 配置项也是蛮多的, 想要实现各种东西, 还是需要再深入学习一下

# expose

使用expose可以给父组件暴露方法

// 父组件可以通过ref获取子组件
<Child ref="childRef"
           title="child component"></Child>
           
import Child, { ChildExpose } from './components/Child.vue';
           
setup() {
	const childRef = ref<ChildExpose>({});
	onMounted(() => {
  	console.log(childRef.value);
	  childRef.value.addTwo && childRef.value.addTwo();
	});
}

子组件expose














 









export interface ChildExpose {
  addTwo?(): void;
}
export default {
  name: 'Child',
  props: {
    title: String
  },
  setup(props: Props, context: SetupContext) {
    const count = ref(0);
    const addTwo = () => {
      count.value += 2;
    };
    context.expose({
      addTwo
    });
    return {
      count,
      addTwo
    };
  }
};

# 关于this

setup() 内部,this 不是该活跃实例的引用,因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这使得 setup() 在和其它选项式 API 一起使用时可能会导致混淆。

# 生命周期

选项式 API Hook inside setup
beforeCreate Not needed*
created Not needed*
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered
activated onActivated
deactivated onDeactivated
<script lang="ts">
import {
  onBeforeMount,
  onBeforeUnmount,
  onMounted,
  onErrorCaptured,
  ref
} from 'vue';
interface Props {}
export default {
  name: 'LiftCycle',
  // props: {},
  // components: {},
  setup(props: Props) {
    const lifeCycleHandler = (cycleName: string) => () => {
      console.log(`%c${cycleName}`, 'color: red;');
    };
    onBeforeMount(lifeCycleHandler('onBeforeMount'));
    onMounted(lifeCycleHandler('onMounted'));
    onBeforeUnmount(lifeCycleHandler('onBeforeUnmount'));
    onErrorCaptured(lifeCycleHandler('onErrorCaptured'));

    return {};
  }
};
</script>

TIP

因为 setup 是围绕 beforeCreatecreated 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写

需要前置的请求可以再setup直接发起, 或者也可以在 onMounted钩子里面获取.

其他的其实都差不多

上次更新: 1/22/2025, 9:39:13 AM