Vue3 之<script setup> 语法糖的超爽体验

918 阅读2分钟

setup函数在组件创建前执行,位于beforeCreated之前,用于代替created 和beforeCreated。 为vue3.0的Composition API提供了统一的入口。

那么什么是composition Api(组合式api)?

组合式API其实就是把之前Vue2分散在data、生命周期、watch、computed、methods中的部分现在全部整合到一起放到了setup中,这样的好处就是我们可以把一些业务或者逻辑抽离出来,然后那个地方需要就直接引入,比vue2中的方便了一些

期初vue3.0刚出来的时候,定义的变量都需要我们手动return出来,在加上了setup语法糖之后,就不需要return出去就可以直接再template内调用,组件也可以直接导入,无需注册就能掉用

基本语法

<template>
    <div @clikc="onBtn">{{data}}</div>
</template>
<script lang="ts" setup>
// 1. 从 vue 中引入 ref 函数
import { ref } from 'vue'
export default ({
    // 2.定义一个单值,响应式变量
    const data = ref('这是一个标题')
    // 3.方法也不需要return出去
    const onBtn = () => {
        console.log('事件')
    }
})
</script>

组件使用

script-setup 无法指定当前组件的名字,所以使用的时候以文件名为主

<template>
  <MyComponent />
</template>

<script lang="ts" setup>
    import MyComponent from './MyComponent.vue'
</script>

组件传值

defineProps函数 ==> 父传子

父组件

<template>
  <div class="die">
    <h3>我是父组件</h3>
    <zi-hello :name="name"></zi-hello>
  </div>
</template>

<script lang="ts" setup>
  import ziHello from './ziHello'
  import {ref} from 'vue'
  
  let name = ref('传给父组件的')
</script>

子组件

<template>
  <div class="die">
    <h3>我是子组件</h3>
    {{ name }}
  </div>
</template>

<script lang="ts" setup>
import { defineProps } from 'vue'
  // 通过defineProps指定当前props类型的同时,获得上下文的props对象
  defineProps({
      name: {
          type: String,
          default: ''
      }
  })
}
</script>

defineEmits函数 ==> 子传父

子组件

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

<script lang="ts" 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 lang="ts" setup>
  import ziHello from './ziHello'
  
  const updata = (data) => {
    console.log(data); //我是子组件的值
  }
</script>

defineEpose函数 (组件暴露自己的属性) ==> 子传多

子组件

<template>
  <div>
    我是子组件
  </div>
</template>

<script lang="ts" setup>
  import {defineExpose,reactive,ref} from 'vue'
  // ref声明响应式数据,用于声明非引用类型
  let ziage=ref(18)
  // reactive声明响应式数据,用于声明引用数据类型
  let ziname=reactive({
    name:'你的名字'
  })
  //暴露出去的变量
  defineExpose({
    ziage,
    ziname
  })
</script>

父组件

<template>
  <div class="die">
    <h3 @click="isclick">我是父组件</h3>
    <zi-hello ref="hello"></zi-hello>
  </div>
</template>

<script lang="ts" setup>
  import {ref} from 'vue'
  const zihello = ref()

  const isclick = () => {
    console.log('接收ref暴漏出来的值',hello.value.ziage)
    console.log('接收reactive暴漏出来的值',hello.value.ziname.name)
  }
</script>

defineEpose函数 (组件暴露自己的属性) ==> 子传多

子组件暴露自己的属性

<template>
  <div>子组件helloword.vue</div>
</template>

<script lang="ts" setup>
    import { ref } from 'vue'
    const count = ref(123456)
    defineExpose({
      count
    })
</script>

父组件获取属性

<template>
  <div @click="helloClick">父组件</div>
  <helloword ref="hello"></helloword>
</template>

<script lang="ts" setup>
    import { ref } from 'vue'
    import helloword from './components/HelloWorld.vue'
    const hello = ref(null)
    const helloClick = () => {
      console.log(hello.value.count) // 123456
    }
</script>

style v-bind

除了以上基本的Api外,在vue3.2中还新增了一个style v-bind的特性,在官网中被称为状态驱动的动态 CSS

<template>
    <div>123</div>
</template>
<script lang="ts" setup>
  import { reactive } from 'vue';

  const state = reactive({
        color'red'
  })
</script>

<style>
div {
/* 使用v-bind绑定state中的变量 */
  color: v-bind(state.color);
}
</style>

实际的值会被编译成 hash 的 CSS 自定义 property,CSS 本身仍然是静态的。自定义 property 会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式更新。

computed API 在Vue3.0中的应用

<template>
    <div>{{`${person.name}今年${person.age}岁, 明年${nextYearAge}岁`}}</div>
</template>
 
<script lang="ts" setup>
import { computed, reactive } from 'vue'
const person = reactive({
    name: '你的名字',
    age: 18
})
 
// 声明methods方法
const nextYearAge = computed(() => {
    return person.age + 1
})
</script>

watch API 在Vue3.0中的应用

<template>
    <div>{{`${person.name}今年${person.age}岁, 明年${nextYearAge}岁`}}</div>
    <button @click="changeAge">加1岁</button>
</template>
 
<script lang="ts" setup>
import { computed, reactive, watch } from 'vue'
const person = reactive({
    name: '小明',
    age: 18
})
 
// 声明methods
const changeAge = () => {
    person.age += 1
}
 
// 声明methods方法
const nextYearAge = computed(() => {
    return person.age + 1
})
 
watch(
    () => person.age,
    // change函数,监听值的变化
    (newV, oldV) => {
        console.log("当前值:" + person.age)
        console.log("变化前:" + oldV)
        console.log("变化后:" + newV)
    },
    {
      immediate: true, // 立即执行
      deep: true // 深度监听
    }
)
</script>

监听多个值

watch([() => data.count, () => data.name], 
     ([newcount, newname], [oldcount, oldname]) => {
        console.log(newcount) // 新的count值
        console.log(newname) // 新的name值
        console.log(oldcount) // 旧的count值
        console.log(oldname) // 旧的name值
    }
)