setup script有什么用
看到这里很多小伙伴就不理解了,我在script后面加上一个setup有什么用呢?接着看!

1、自动注册子组件

直接看例子

vue3语法

<template>
  <div>
    <h2>我是父组件!</h2>
    <Child />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import Child from './Child.vue'

export default defineComponent({
  components: {
      Child
  },
  setup() {

    return {
      
    }
  }
});
</script>

vue3语法在引入Child组件后,需要在components中注册对应的组件才可使用。

setup script写法

<template>
  <div>
    <h2>我是父组件!-setup script</h2>
    <Child />
  </div>
</template>

<script setup>
import Child from './Child.vue'
</script>
2、属性和方法无需返回

composition API写起来有点繁琐的原因在于需要手动返回模板需要使用的属性和方法。
而在setup script中可以省略这一步。看看下面的例子。

vue3语法

<template>
  <div>
    <h2 @click="ageInc">{{ name }} is {{ age }}</h2>
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
  setup() {
    const name = ref('lieo')
    const age = ref(18)

    const ageInc = () => {
      age.value++
    }

    return {
      name,
      age,
      ageInc
    }
  }
})
</script>

setup script写法

<template>
  <div>
    <h2 @click="ageInc">{{ name }} is {{ age }}</h2>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const name = ref('CoCoyY1')
const age = ref(18)

const ageInc = () => {
  age.value++
}
</script>
3、支持props、emit

vue3语法

//Father.vue
<template>
  <div >
    <h2 >我是父组件!</h2>
    <Child msg="hello" @child-click="childCtx" />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import Child from './Child.vue';

export default defineComponent({
  components: {
    Child
  },
  setup(props, context) {
    const childCtx = (ctx) => {
      console.log(ctx);
    }

    return {
      childCtx
    }
  }
})
</script>


//Child.vue
<template>
  <span @click="handleClick">我是子组件! -- msg: {{ props.msg }}</span>
</template>

<script>
import { defineComponent, ref } from 'vue'

export default defineComponent({
  emits: [
    'child-click'
  ],
  props: {
    msg: String
  },
  setup(props, context) {
    const handleClick = () => {
      context.emit('child-click', context)
    }

    return {
      props,
      handleClick
    }
  },
})
</script>

setup script写法

//Father.vue
<template>
  <div >
    <h2 >我是父组件!</h2>
    <Child msg="hello" @child-click="childCtx" />
  </div>
</template>

<script setup>
import Child from './Child.vue';

const childCtx = (ctx) => {
  console.log(ctx);
}
</script>


//Child.vue
<template>
  <span @click="handleClick">我是子组件! -- msg: {{ props.msg }}</span>
</template>

<script setup>
import { defineProps, defineEmit } from 'vue'
const emit = defineEmit(['child-click'])
const props = defineProps({
  msg: String
})

const handleClick = () => {
  emit('child-click', "点击了")
}
</script>
4.父子组件访问方法及属性的方式
<template>
   <Nav ref="Nav" @mouseover="mouseCollapseMenu()"></Nav>
</template>
<script lang="ts" setup>
import Nav from "./components/nav.vue";
import { nextTick, ref } from "vue";
const Nav = ref(null);
const handleMenu = () => {
  nextTick(() => {
    Nav.value.handleMenu(false);
  });
};
</script>

子组件里面暴露

<script setup>
import {defineExpose, ref } from 'vue'
//子组件暴露出去 用于父组件调用
defineExpose({
  handleMenu(value: boolean) {
    handleMenu(value);
  },
});
</script>

在setup 语法糖中 目前没有拿到context的导出方法
但其中的attrs、emit、props、slots、expose属性和方法依然可以使用。

5.useSlots 和 useAttrs

<script setup> 使用 slots 和 attrs 的情况应该是很罕见的,因为可以在模板中通过 $slots 和 $attrs 来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlots 和 useAttrs 两个辅助函数:

<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用

仅限 TypeScript 的功能
1. 仅限类型的 props/emit 声明
props 和 emits 都可以使用传递字面量类型的纯类型语法做为参数给 defineProps 和 defineEmits 来声明:

const props = defineProps<{
  foo: string
  bar?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()
  • defineProps 或 defineEmits 只能是要么使用运行时声明,要么使用类型声明。同时使用两种声明方式会导致编译报错。
  • 使用类型声明的时候,静态分析会自动生成等效的运行时声明,以消除双重声明的需要并仍然确保正确的运行时行为。
  1. 在开发环境下,编译器会试着从类型来推断对应的运行时验证。例如这里从 foo: string 类型中推断出 foo:String。如果类型是对导入类型的引用,这里的推断结果会是 foo: null (与 any 类型相等),因为编译器没有外部文件的信息。
  2. 在生产模式下,编译器会生成数组格式的声明来减少打包体积 (这里的 props 会被编译成 [‘foo’, ‘bar’])。
  3. 生成的代码仍然是有着类型的 Typescript 代码,它会在后续的流程中被其它工具处理。
  • 截至目前,类型声明参数必须是以下内容之一,以确保正确的静态分析:
  1. 类型字面量
  2. 在同一文件中的接口或类型字面量的引用
  • 现在还不支持复杂的类型和从其它文件进行类型导入。理论上来说,将来是可能实现类型导入的

2. 使用类型声明时的默认 props 值
仅限类型的 defineProps 声明的不足之处在于,它没有可以给 props 提供默认值的方式。为了解决这个问题,提供了 withDefaults 编译器宏:

interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

上面代码会被编译为等价的运行时 props 的 default 选项。此外,withDefaults 辅助函数提供了对默认值的类型检查,并确保返回的 props 的类型删除了已声明默认值的属性的可选标志

Logo

前往低代码交流专区

更多推荐