Vue3.2 语法糖
setup
- setup 写在最外层,这样里面不用写 return
html
<script setup></script>
导入组件
<script setup>
内导入的组件,可以直接在模板中使用
html
<template>
<my-com />
</template>
<script setup>
// 导入的组件可以直接在template中使用
import MyCom from "@/components/MyCom.vue";
</script>
组件命名
比如说你想给引用的组件七别名,你可以用
js
import { default as Component1 } from "@/components/MyCom.vue";
import { default as Component1 } from "@/components/MyCom2.vue";
定义 props 利用 defineProps
html
<script setup>
// 子组件收到的时候写法如下
const props = defineProps({
proplist: [String, Object],
proplist2: Object,
});
// 子组件模板里面使用的时候,前面加props.属性即可。
// {{props.proplist[0]}}
// {{props.proplist2[1].id}}
// {{props.proplist[2]}}
// {{proplist2.cesi}}
</script>
定义 emit 事件 defineEmits
- 子组件
html
<template>
<div>我是子组件 My-Com : {{ msg }}</div>
<button @click="emit('update-msg', 'hi')">update</button>
<!--或者-->
<button @click="deleteMsg">delete</button>
</template>
<script setup>
defineProps({
msg: String,
});
// 定义发出的事件.第二个参数可以传值或者不传值
const emit = defineEmits(["update-msg", "delete-msg"]);
const deleteMsg = () => {
emit("delete-msg");
};
</script>
- 父组件
html
<template>
<!--父组件接收事件的方式也没区别,就是用 @ 接收-->
<my-com :msg="msg" @update-msg="updateFun" @delete-msg="deleteFun"></my-com>
</template>
<script setup>
import { ref } from "vue";
import MyCom from "@components/MyCom.vue";
// 定义组件状态 和 方法 都和之前没有区别,只是不用 return 出去了
const msg = ref("Hello");
const updateFun = (param) => {
console.log("update", param);
};
const deleteFun = () => {
msg.value = "";
};
</script>
第二种父子方法
bash
- 通过 v-model 实现
- 通过 update:xxx 实现
- 子组件
html
<template>
<span @click="changeflag" class="iconall">
<el-icon-expand v-if="props.isCollapse"></el-icon-expand>
<el-icon-fold v-if="!props.isCollapse"></el-icon-fold>
</span>
</template>
<script setup lang="ts">
const props = defineProps<{
isCollapse: boolean;
}>();
const emits = defineEmits(["update:isCollapse"]);
const changeflag = () => {
emits("update:isCollapse", !props.isCollapse);
};
</script>
<style scoped lang="scss">
.iconall {
margin-top: 20px;
display: inline-block;
}
</style>
- 父组件
html
<template>
<div class="common-layout">
<el-container>
<SideBar :isCollapse="isCollapse"></SideBar>
<el-container>
<el-header>
<NavHeader v-model:isCollapse="isCollapse"></NavHeader>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import SideBar from "@/components/container/SideBar/index.vue";
import NavHeader from "@/components/container/NavHeader/index.vue";
// 收缩开关
const isCollapse = ref(false);
</script>
<style scoped lang="scss">
.el-header {
border-bottom: 1px solid #ccc;
}
</style>
变量和方法
- 声明在
<script setup>
顶层的状态,函数,以及import
引入的变量和方法,都能在模板中直接使用,不用再通过return
暴露出去
html
<script setup>
import { capitalize } from "./helpers";
</script>
<template>
<div>{{ capitalize('hello') }}</div>
</template>
对组件外暴露属性 defineExpose 父元素调用子元素必须暴露出来
bash
对外暴露的属性可以是任意,比如数据比如节点,但是只能通过父元素通过ref来接受
<script setup>
的组件默认不会对外暴露任何内部声明的属性,如果需要暴露出去,可以使用defineExpose
编译宏
html
<script setup>
import { ref } from "vue";
const a = 1;
const b = ref(2);
defineExpose({
a,
b,
});
</script>
- 父组件通过模板 ref 获取到子组件的实例,以此访问 MyCom 暴露出去的属性
html
<script setup>
import { onMounted, ref } from "vue";
import MyCom from "@components/MyCom.vue";
const myComRef = ref(null);
onMounted(() => {
console.log(myComRef, myComRef.value.a);
});
</script>
<template>
<my-com :msg="msg" ref="myComRef" />
</template>
useSlots 和 useAttrs
等价于组合式 APIsetup(props,context)
的context,slots
和context.attrs
也可以解构获取: setup(props,{slots,attrs})
- 父组件
html
<Component2
:propslist="propslist"
:propslist2="propslist2"
@handleclick="changepropslist"
@handleclick2="changepropslist2"
ref="zujian2"
style="background: red"
>
<template v-slot:kacao1>
<p>卡槽数据</p>
</template>
</Component2>
- 子组件
js
import { onMounted, ref, useAttrs, useSlots } from "vue";
const attrs = useAttrs();
const slots = useSlots();
console.log(attrs);
//这里就是显示{style:{background:'red'}} console.log(slots.kacao1());
//这就是显示卡槽里面的所有数据
Vue3 中使用 this
getCurrentInstance
是 Vue 3 提供的一个函数,能够让你在 setup 函数的上下文中获取当前组件的实例。这在许多场景下都非常有用,尤其是在需要访问组件内部的Reactive
数据、Props、Context 或者Lifecycle Hook
等情况下。这样 proxy 就能代替 this
js
const { proxy } = getCurrentInstance();
const openbianqian = () => {
proxy.$tab.openPage("demo2", "/study").then((res) => {
console.log(res);
});
};
Top-level 顶层 await
<script setup>
内可以用顶层的 await 设计,代码会被编译成async setup()
html
<script setup>
const post = await fetch(`@api/post/1`).then((r) => r.json())
</script>
CSS 里面使用 v-bind 自定义变量
- v-bind 能在 css 里面使用
html
<script setup>
const color = ref("green");
const buttonwidth = ref("60px");
</script>
<style lang="less" scoped>
button {
color: v-bind(color);
width: v-bind(buttonwidth);
}
</style>
- 通过 ref 绑定的数据能在 css 里面直接使用
Vue3 里面的总线机制
有的时候我们的组件嵌套的层数太多,我们不希望一直用 props 来传递也不希望用 vuex
所以引入了 mitt
安装 mitt
js
yarn add mitt -S
然后建立 mitt 文件
- 在 src 目录下新建一个 utils 文件夹,然后新建 mitt.js
js
import mitt from "mitt";
export default mitt();
十八代组件像传递出数据了
- 发送事件
js
mitt.emit("自定义事件名", 数据);
最顶部的组件监听
- 监听事件
js
mitt.on("自定义事件名", (value) => {
console.log(value);
console.log("收到了数据");
});
- 监听完了 需要卸载钩子函数里面卸载
js
onUnmounted(() => {
mitt.off("publicdata", () => {
console.log("解绑了");
});
});