Skip to content

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,slotscontext.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("解绑了");
  });
});