vue3.2 setup syntax sugar

0. Preface
The data function in vue2 has been deleted in vue3. Therefore, if vue3.0 wants to use certain variables in the template, it must be returned at the end, multiple times Declaring variables is not convenient or friendly. After vue3.2 version, we only need to add the setup attribute to the script tag, and can use it directly in the template without writing return. Writing code is very smooth. Hey, this is great!
Sample code for writing vue3.0.

<template>
  <div>
    <p>{
   
   { `${state.name}发布于${state.age},${msg}` }}</p>

    <button @click="onClick">点击</button>

    <ChildComp />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, reactive } from "vue"
import ChildComp from './ChildComp.vue'

export default defineComponent({
  // 注册组件
  components: {
    ChildComp
  },
  props: {
    show: {
      type: Boolean,
      default: false
    }
  },
  emits: ['on-confirm'],

  setup(props, { emit }) {
    console.log(props.show) // false

    const msg = ref('');
    msg.value = '哎,这就很不棒!';

    const state = reactive({
      name: 'vue3.0',
      age: '2020年9月18日'
    })
    // 点击事件
    const onClick = () => {
      emit('on-confirm')
    }
    // 必须return出来
    return {
      msg,
      state,
      onClick
    }
  }
})
</script>

When you first start using script setup syntax sugar, the editor will prompt that this is an experimental property. To use it, you need to fix the vue version. At the end of June 2021, the proposal was officially finalized. In the vue3.1.3 version, it will continue to be used but there will still be prompts for experimental proposals. In vue3.2, the prompts will be removed and some abandoned APIs will be removed.

Script setup is the new syntactic sugar of vue3.2. It is not a new functional module. The main benefits are: (1) less template content, concise code, no need to write return; (2) better declarations can be used with ts props, and throwing events; (3) Better runtime performance.


1. Variables and methods do not require renturn

Variables, methods and imported content do not need to be exposed in return. There is no need to write export default and setup functions. You only need to add the setup attribute to the script tag and directly declare the variables, methods and imported content to use, so that the template code can be used. More concise.

<template>
  <div>
    <!-- 使用变量 -->
    <p>{
   
   { `${state.name}发布于${state.age},${msg}` }}</p>
    <!-- import导入 -->
    <ul>
      <li v-for="item in subjectList" :key="item.value">
        {
   
   {item.label}}
      </li>
    </ul>
    <!-- 使用方法 -->
    <button @click="onClick">点击</button>
  </div>
</template>

<!-- 在script标签上添加setup属性 -->
<script setup lang="ts">
import { ref, reactive } from "vue"
import { subjectList } from './utils.js'

const msg = ref('');
msg.value = '哎,这就很棒!';

const state = reactive({
  name: 'vue3',
  age: '2020年9月18日'
})

// 点击事件
const onClick = ():void => {
  console.log('点击了')
}
</script>

2. Introduce automatic component registration

Introduce components in script setup syntax sugar. Components do not need to be registered in components. The imported components will be automatically registered, and components cannot specify the name attribute. The name of the file is mainly used, and the name attribute is omitted.

<template>
  <div>
    <Child />
  </div>
</template>

<!-- 在script标签上添加setup属性 -->
<script setup lang="ts">
import Child from './Child.vue'
</script>

3、defineProps和defineEmits


Props and emits must be declared in script setup using the defineProps and defineEmits APIs. They have complete type inference and are directly available in script setup without import. Options passed to defineProps and defineEmits are promoted from setup to the scope of the module, so options passed in cannot reference local variables declared in setup scope, which will cause a compilation error.

(1)defineProps
 

//父组件
<template>
  <div>
    <Child :name="name" />
  </div>
</template>

<!-- 在script标签上添加setup属性 -->
<script setup lang="ts">
import { ref } from 'vue';
import Child from './Child.vue';

const name = ref('张三')
</script>
//子组件
<template>
  <div>
    <p>{
   
   { `${props.name}在学习JavaScript` }}</p>
  </div>
</template>

<script setup lang="ts">
// defineProps不需要从vue中导入
const props = defineProps({
  name: {
    type: String,
    default: '张三'
  }
})
// 或者
const props = defineProps(['name'])
</script>

(2)defineEmits

// 父组件
<template>
  <div>
    <Child @on-confirm="onConfirm" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Child from './Child.vue';

const show = ref(false)
// 点击确定关闭弹框等操作
const onConfirm = (val: boolean) => {
  show.value = val
} 
</script>
// 子组件
<template>
  <button type="button" @click="handleConfirm">确定</button>
</template>

<script setup lang="ts">
const emit = defineEmits(['on-confirm'])

const handleConfirm = () => {
  // 此处也可以传入参数
  emit('on-confirm', false)
}
</script>

4、defineExpose

defineExpose can actively expose component properties and methods.

// 子组件示例代码
// 子组件
<template>
  <div v-if="show">
    <p>{
   
   { count }}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0)
const show = ref(false)

const onShow = () => {
  show.value = true
}
// defineExpose暴露出count属性和onShow方法
defineExpose({
  count,
  onShow
})
</script>
// 父组件示例代码
// 父组件
<template>
  <div>
    <button type="button" @click="onClick">父组件点击</button>
    <Child ref="childRef" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import Child from './Child.vue';
// Child组件的ref
const childRef = ref(null)

// 在父组件操作子组件的暴露出的属性或方法
const onClick = () => {
  childRef.value.count += 1;
  childRef.value.onShow();
}
</script>

5. useSlots and useAttrs


It should be very rare to use slots and attrs in script setup. Most people develop in (SFC) mode. In <template/>, slots can be rendered through the <slot/> tag. They are accessed via $slots and $attrs. Mainly used in JSX/TSX.

(1) useSlots
slots can obtain the virtual Dom object passed by the slot in the parent component.
 

// 父组件
<template>
  <Child>
    <span>默认插槽</span>
    <template v-slot:footer>
      <div>具名插槽footer</div>
    </template>
  </Child>
</template>

<script setup>
import Child from './Child.vue'
</script>
// 子组件
<template>
  <div>
    <!-- 在模板中使用插槽 -->
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script setup lang="ts">
import { useSlots } from 'vue'
 
const slots = useSlots()
// 访问插槽默认插槽default、具名插槽footer
console.log(slots.default)
console.log(slots.footer)
</script>

(2)useAttrs

attrs is used to obtain the non-props attributes passed to the child component in the parent component, including class and style attributes.

// 父组件
<template>
  <Child class="child-class" title="子组件title" />
</template>

<script setup>
import Child from './Child.vue'
</script>
// 子组件
<template>
  <!-- 在模板中使用 $attrs 访问属性 -->
  <div>{
   
   { $attrs.title }}</div>
</template>

<script setup lang="ts">
import { useAttrs } from 'vue'
 
const attrs = useAttrs()
// 使用
console.log(attrs.class)  // child-class
console.log(attrs.title)  // 子组件title
</script>

Used in jsx/tsx

<script lang="tsx">
import { defineComponent, ref, useSlots } from 'vue';
export default defineComponent({
  setup(){
    const slots = useSlots();
    const str = ref<string>('tsx的使用');

    return () => (
      <>
        <div class='async'>{str.value}</div>
        <div>{ slots.default ? slots.default() : 'foo' }</div>
        <div>{ slots.bar?.() }</div>
      </>
    );
  }
})
</script>

6. Top-level await

<script setup> Top-level await can be used in . The resulting code will be compiled into async setup(), and the await expression will be automatically compiled into a format that retains the context of the current component instance after await.

// api/system
export const getUserInfo = async () => {
  const res: any = await request.get(`/api/user/info`)
  return res
}

7. With ordinary


<script setup> can be used with regular <script>. Ordinary <script> may be used in situations where these are needed:

Options that cannot be declared in <script setup>, such as inheritAttrs or custom options enabled through plugins.
declares a named export.
Run side effects or create objects that only need to be executed once
 

<script>
// 普通 <script>, 在模块范围下执行(只执行一次)
runSideEffectOnce()

// 声明额外的选项
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script setup>
// 在 setup() 作用域中执行 (对每个实例皆如此)
</script>

Note: This article is reproduced

Original text:vue3.2 setup syntax sugar, you deserve it_vue setup_front-end nonsense blog-CSDN blog

Guess you like

Origin blog.csdn.net/weixin_48091030/article/details/134788690