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中 组件的名字默认为 文件名
在 浏览器 vue工具插件中显示
那么问题来了 在开发时 怎么让我们可以自定义组件名呢?
其实很简单 我们可以在添加一个script标签 来进行对组件的命名
<template>
<div>我是一个组件</div>
</template>
<script>
export default {
name: "title",
};
</script>
<script setup></script>
vue浏览器插件显示
引入组件
我们传统引入组件的方式 需要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>