Vue3.0 setup语法糖

913 阅读1分钟

setup 语法糖

setup 是 Vue3 中的最重要特性之一,是在组件创建之前, props 被解析之后执行,是组合式 API 的入口。

目前 setup sugar 已经进行了定稿,vue3 + setup sugar + TS 的写法看起来很香,要求版本在 Vue3.2 以上

setup 和 setup 语法糖的区别

起初 Vue3.0 暴露变量必须 return 出来,template 中才能使用; 现在只需在 script 标签中添加 setup,组件只需引入不用注册,属性和方法也不用返回, 也不用写 setup 函数,也不用写 export default,甚至是自定义指令也可以在我们的 template 中自动获得。

<template>
  <my-component :num="num" @click="addNum" />
</template>
<script setup>
  import { ref } from 'vue';
  /*   
    在script setup中,引入的组件可以直接使用,无需再通过components进行注册,
    并且无法指定当前组件的名字,它会自动以文件名为主,也就是不用再写name属性了
   */
  import MyComponent from './MyComponent .vue';

  /* 
    像在平常的setup中一样的写,但是不需要返回任何变量
    在此处定义的num可以直接使用 
  */
  const num = ref(0);
  // 函数也可以直接引用,不用在return中返回
  const addNum = () => {
    num.value++;
  };
</script>

使用 setup 语法糖后新增 api

在没有使用语法糖时,我们的 props、emit 可以预先定义,然后在 setup 的入参中获取

//子组件

<template>
  <button class="child" @click="foo"></button>
</template>
<script>
  props:{
    msg:{
      type:String,
      required:true
    }
  },
  setup(props, context) {
    const{emit} = context
    const foo = () => {
      emit("myevent", 123);
      printMsg()
    };
    const printMsg = ()=>{
      console.log(props.msg)
    }
    return {
      foo,
    };
   },
</script>

//父组件
<template>
  <Child @myevent="chuanCan" :msg="msg" />
</template>
<script>
  setup() {
    const msg = 'i am msg'
    const chuanCan = (a: number) => {
      console.log(a);
    };
    return {
      chuanCan,
      msg
    };
  },
</script>

在使用语法糖后,要怎么获取到 emit 和 props?

这时候 我们就要用到 Vue 为了使用 setup 语法糖出的新 Api

defineProps

用来接收父组件传来的 props。

示例: 父组件代码
<template>
  <div class="die">
    <h3>我是父组件</h3>
    <yyx-hello :name="name"></yyx-hello>
  </div>
</template>
<script setup>
  import yyxHello from './yyxHello';
  import { ref } from 'vue';
  let name = ref('小杨');
</script>

子组件代码
<template>
  <div>我是子组件{{name}} //小杨</div>
</template>
<script setup>
  import { defineProps } from 'vue';
  defineProps({
    name: {
      type: String,
      default: '我是默认值',
    },
  });
</script>

defineEmit

子组件向父组件事件传递。示例:

//子组件
<template>
  <div>我是子组件{name}}<button @click="ziupdata">按钮</button></div>
</template>

<script setup>
  import { defineEmits } from 'vue';
  //自定义函数,父组件可以触发
  const em = defineEmits(['updata']);
  const ziupdata = () => {
    em('updata', '我是子组件的值');
  };
</script>

//父组件
<template>
  <div class="die">
    <h3>我是父组件</h3>
    <zi-hello @updata="updata"></zi-hello>
  </div>
</template>
<script setup>
  import ziHello from './ziHello'
  const updata = (data) => {
  console.log(data); /我是子组件的值
  }
</script>

defineExpose

//子组件
<template>
  <div>我是子组件</div>
</template>
<script setup>
  import { defineExpose, reactive, ref } from 'vue';
  let ziage = ref(18);
  let ziname = reactive({
    name: '小杨',
  });
  //暴露出去的变量
  defineExpose({
    ziage,
    ziname,
  });
</script>
父组件
<template>
  <div class="die">
    <h3 @click="isclick">我是父组件</h3>
    <zi-hello ref="zihello"></zi-hello>
  </div>
</template>
<script setup>
  import ziHello from './ziHello';
  import { ref } from 'vue';
  const zihello = ref();
  //父组件拿到的结果
  const isclick = () => {
    console.log('接收ref暴漏出来的值', zihello.value.ziage);
    console.log('接收reactive暴漏出来的值', zihello.value.ziname.name);
  };
</script>

defineExpose 不是唯一获取子组件数据的方法,也可以用 ref 实现

父组件
<script setup>
  import { ref } from 'vue';
  import Comp from './Comp.vue';
  const showComp = ref(null); //这个时候获取了子组件Comp
  const childShow = () => {
    showComp.value.show(); //调用子组件的show方法
  };
</script>
<template>
  <button @click="childShow">点击调用子组件方法</button>
  <Comp ref="showComp"></Comp>
</template>

子组件Comp.vue
<script setup>
  import { ref } from 'vue';
  const show = () => {
    alert('我是子组件,我的show方法被调用了');
  };
  // 主动暴露childMethod方法
  defineExpose({ show });
</script>
<template>
  <div>我是子组件</div>
</template>