Vue3.2 <script setup> 语法糖

316 阅读2分钟

vue3.2与vue2在写法上最大的区别就是vue3.2把很多内容都移至setup函数中了,但是如果模板要使用setup中的变量或是函数的话,需要return出来,这样写起来又繁琐又别扭。而在vue3.2中就不会有那么麻烦了

<template>
  <h1>setup</h1>
  <h1>
    {{ count }}
  </h1>
  <br />
  <button @click="add">点我自增1</button>
</template>

<script setup>
import { ref } from "vue";
const count = ref(0);
const add = () => {
  count.value += 1;
};
</script>

以上代码可以看出 我们并没有使用return{}来将需要的方法和变量返回 但是页面呈现的效果是一致的

setup-components

在vue3.2中 组件的名字默认为 文件名

NPV{HNOLVPIC)KUIW3XEREO.png

在 浏览器 vue工具插件中显示

M4(]V{[GWP8O0~}P{F)ZI.png

那么问题来了 在开发时 怎么让我们可以自定义组件名呢?

其实很简单 我们可以在添加一个script标签 来进行对组件的命名

<template>
  <div>我是一个组件</div>
</template>

<script>
export default {
  name: "title",
};
</script>
<script setup></script>

vue浏览器插件显示

W79E(XH)Z~EFNPLSLUO{C1Y.png

引入组件

我们传统引入组件的方式 需要import 还需要在相关父组件内进行注册
而在我们的setup语法糖内 则不需要进行组件的一个注册 就可以直接导入组件进行使用
<template>
//可以直接使用
  <home />
</template>

<script setup>
//我没有被注册 
import home from "./components/home.vue";

组件的命名空间

在vue的前几个版本中 我们在components 中定义的组件 想要引入 那就离不开 import 和 注册组件 组件少的话还好 如果项目大 组件多 那我们一个一个引入组件是一个很繁琐的事情 有没有什么好的办法可以解决呢?
在setup语法糖中 我们可以使用组件的命名空间
在components (或者其他的需要命名空间的目录下) 新建一个 index.js文件然后导入在components文件内的组件 并进行暴露
import home from "./home.vue";
import title from "./title.vue";

export { home, title };

使用暴露出去的组件
<template>
  <All.home />
  <All.title />
</template>

<script setup>
import * as All from "./components/index";
</script>
这种方法和传统组件注册结果是一样的

setup props

setup接收props
这个没什么好说的 只是把 props 换成了 defineProps

父组件

<template>
  <All.home :list="list" />
  <All.title />
</template>
......
<script setup>
import * as All from "./components/index";

const list = [
  {
    id: 1,
    content: "1",
  },
  {
    id: 2,
    content: "2",
  },
];
</script>

子组件

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item.id">{{ item.content }}</li>
    </ul>
  </div>
</template>

<script setup>
const props = defineProps({
  list: {
    type: Array,
    required: true,
    default: "默认",
  },
});
</script>

setup defineEmits 自定义事件

vue2的自定义事件就不多说了吧
vue3 setup 的语法糖会更加清晰

父组件

<template>
   <!--绑定自定义事件-->
  <All.title @parentClick="parentClick"/>
</template>
<script setup>
import * as All from "./components/index";
  //子组件触发的回调
const parentClick = (num) => {
  alert("子组件触发了父组件的parentClick事件" + num);
};
</script>

子组件

<template>
  <button @click="handleClick">点击触发父组件的parentClick事件</button>
</template>

<script setup>
const emit = defineEmits(["parentClick"]);

//触发自定义事件
const handleClick = () => {
  emit("parentClick", 2);
};
</script>
在setup语法糖中 使用自定义事件 我们需要在子组件内使用 const emit= defineEmits([父组件传递过来的自定义事件]) 来注册自定义事件,触发自定义事件要用 一个常量来触发.

defineExpose

众所周知 在vue3中已经删除了$children 当我们需要子组件内的方法或者属性时应该如何获取呢?
<template>
  <All.title ref="InfoRef" />
</template>

<script setup>
import * as All from "./components/index";
import { onMounted, ref } from "vue";
//获取dom
const InfoRef = ref(null);

onMounted(() => {
  //获取子组件内的a
  console.log(InfoRef.value.a); //undefined
});
</script>
如上所示 这样是无法获取子组件内部的属性的,假设我们把defineExpose当作一扇门,门关着里面的东西能跑出来吗?那肯定是不行的,所以我们要让里面的属性把这扇"门"打开

子组件

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

const a = ref(666);
const b = ref(777);
const c = ref(888);
//打开‘门’让数据走出来
defineExpose({
  a,
});
</script>
这样 我们就可以获取到子组件中的a了,注意 如果想要b或c我们只需要将其放到defineExpose 即可

useSlots

看到slot就知道是和插槽相关的了

父组件

<template>
  <All.title ref="InfoRef">
    <template #header> 父组件使用具名插槽 </template>
  </All.title>
</template>

子组件

<template>
  <h1>info</h1>
  <slot name="header" />
</template>

<script setup>
import { useSlots, onMounted } from "vue";
const slots = useSlots();

onMounted(() => {
  打印 header具名插槽的信息
  console.log(slots.header());
});

使用 const slots = useSlots(); 可以获取到插槽的相关信息 这个在项目中用的比较少 知道有这个大小就行了

useAttrs

useAttrs 用于 接受父组件传递的属性

被props接收的属性将不会出现在useAttrs身上!!!!!

父组件

<template>
  <All.title style="background-color: pink" class="text" a="1" b="2" :c="c">
  </All.title>
</template>

子组件

c被props接收 打印结果将不会出现c
<template>
  <h1>info</h1>
</template>

<script setup>
import { useAttrs, onMounted } from "vue";
const props = defineProps({
  c: {
    type: Number,
  },
});
const attrs = useAttrs();
onMounted(() => {
  console.log(attrs);
});
</script>
结果

2V0K6P~LV`7DPA@8W@UGFVI.png