Vue3.2 setup语法糖总结

40 篇文章 1 订阅
33 篇文章 0 订阅

Vue3.0 暴露变量必须 return 出来,template中才能使用;
Vue3.2 中 只需要在 script 标签上加上 setup 属性,组件在编译的过程中代码运行的上下文是在 setup() 函数中,无需return,template可直接使用。

文件结构

<template>
  // Vue2中,template标签中只能有一个根元素,在Vue3中没有此限制
  // ...
</template>

<script setup>
  // ...
</script>

<style lang="scss" scoped>
  // 支持CSS变量注入v-bind(color)
</style>

响应式数据

<script setup>
  import { reactive, ref, toRefs } from 'vue'
  
  // ref声明响应式数据,用于声明基本数据类型
  const name = ref('Jerry')
  // 修改
  name.value = 'Tom'

  // reactive声明响应式数据,用于声明引用数据类型
  const state = reactive({
    name: 'Jerry',
    sex: '男'
  })
  
  // 修改
  state.name = 'Tom'
  
  // 使用toRefs解构 template可直接使用{{name}}、{{sex}}
  const {name, sex} = toRefs(state)
</script>

声明method方法

<template>
  // 调用方法
  <button @click='changeName'>按钮</button>  
</template>

<script setup>
  import { reactive } from 'vue'

  const state = reactive({
    name: 'Jery'
  })

  // 声明method方法
  const changeName = () => {
    state.name = 'Tom'
  }  
</script>

computed

<script setup>
  import { computed, ref } from 'vue'

  const count = ref(1)

  // 通过computed获得doubleCount
  const doubleCount = computed(() => {
    return count.value * 2
  })
</script>

watch

<script setup>
  import { watch, reactive } from 'vue'

  const state = reactive({
    count: 1
  })

  // 声明方法
  const changeCount = () => {
    state.count = state.count * 2
  }

  // 监听count
  watch(
    () => state.count,
    (newVal, oldVal) => {
      console.log(state.count)
      console.log(`watch监听变化前的数据:${oldVal}`)
      console.log(`watch监听变化后的数据:${newVal}`)
    },
    {
      immediate: true, // 立即执行
      deep: true // 深度监听
    }
  )
</script>

props父传子 / emit子传父

父组件

<template>
  <child :name='state.name' @updateName='updateName'/>  
</template>

<script setup>
  import { reactive } from 'vue'
  // 引入子组件
  import child from './child.vue'

  const state = reactive({
    name: 'Jerry'
  })
  
  // 接收子组件触发的方法
  const updateName = (name) => {
    state.name = name
  }
</script>

子组件

<template>
  <span>{{props.name}}</span>
  <span>{{name}}</span>
  <button @click='changeName'>更名</button>
</template>

<script setup>
  // import { defineEmits, defineProps } from 'vue'
  // defineEmits和defineProps在<script setup>中自动可用,无需导入
  // 需在.eslintrc.js文件中【globals】下配置【defineEmits: true】、【defineProps: true】
	
  // 声明 props 属性
  const props = defineProps({
    name: {
      type: String,
      default: ''
    }
  }) 
  // 声明 emit 事件
  const emit = defineEmits(['updateName'])
  
  const changeName = () => {
    emit('updateName', 'Tom')
  }
</script>

子组件ref变量和defineExpose

在标准组件写法里,子组件的数据都是默认隐式暴露给父组件的,
但在script-setup 模式下,所有数据只是默认 return 给 template 使用,不会暴露到组件外,所以父组件是无法直接通过挂载 ref 变量获取子组件的数据。
如果要调用子组件的数据,需要先在子组件显示的暴露出来,才能够正确的拿到,这个操作,就是由 defineExpose 来完成。

父组件

<template>
  <child ref='childRef'/>  
</template>

<script setup>
  import { ref, nextTick } from 'vue'
  // 引入子组件
  import child from './child.vue'

  // 子组件ref
  const childRef = ref('childRef')
  
  // nextTick
  nextTick(() => {
    // 获取子组件name
    console.log(childRef.value.name)
    // 执行子组件方法
    childRef.value.changeName()
  })
</script>

子组件

<template>
  <span>{{state.name}}</span>
</template>

<script setup>
  import { reactive, toRefs } from 'vue'
  // defineExpose无需引入
  // import { defineExpose, reactive, toRefs } from 'vue'

  // 声明state
  const state = reactive({
    name: 'Jerry'
  }) 
	
  // 将方法、变量暴露给父组件使用,父组件才可通过ref API拿到子组件暴露的数据
  defineExpose({
    // 解构state
    ...toRefs(state),
    // 声明方法
    changeName () {
      state.name = 'Tom'
    }
  })
</script>

路由useRoute和useRouter

<script setup>
  import { useRoute, useRouter } from 'vue-router'
	
  // 必须先声明调用
  const route = useRoute()
  const router = useRouter()
	
  // 路由信息
  console.log(route.query)

  // 路由跳转
  router.push('/newPage')
</script>

vuex

*Vue3 中的Vuex不再提供辅助函数写法

<script setup>
  import { useStore } from 'vuex'
  import { key } from '../store/index'

  // 必须先声明调用
  const store = useStore(key)
	
  // 获取Vuex的state
  store.state.xxx

  // 触发mutations的方法
  store.commit('fnName')

  // 触发actions的方法
  store.dispatch('fnName')

  // 获取Getters
  store.getters.xxx
</script>

全局事件绑定与组件内使用

main.js

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

// 获取原型
const prototype = app.config.globalProperties

// 绑定参数
prototype.name = 'Jerry'

组件内使用

<script setup>
  import { getCurrentInstance } from 'vue'

  // 获取原型
  const { proxy } = getCurrentInstance()
  
  // 输出
  console.log(proxy.name)
</script>

对 await 的支持

不必再配合 async 就可以直接使用 await 了,这种情况下,组件的 setup 会自动变成 async setup

<script setup>
  const post = await fetch('/api').then(() => {})
</script>

provide和inject

父组件

<script setup>
  import { provide } from 'vue'
  // 声明provide
  provide('provideState',
    changeName: () => {name.value = 'Tom'}
  )
</script>

子组件

子组件
<script setup>
  import { inject } from 'vue'
  // 注入
  const provideState = inject('provideState')
  
  // 子组件触发name改变
  provideState()
</script>
关于Component标签动态渲染组件

在 < script setup> 中要使用动态组件时,需要直接用 :is=“Component” 直接绑定到组件本身,而不是字符串的组件名。

<template>
	<component
      :is="typeComponentMap[currentComp]?.modal"
      :id="asDetailId"
    ></component>
</template>

<script setup lang="ts">
import productValueDetails from '/@/views/economics/project/index/productValueDetails/index.vue'
import collectionDetails from '/@/views/economics/project/index/collectionDetails/index.vue'
import projectDetails from '/@/views/economics/project/details/index.vue'
import balanceDetails from '/@/views/economics/project/index/balanceDetails/index.vue'

const typeComponentMap: any = {
  productValueDetails: {
    title: '项目产值明细',
    modal: productValueDetails
  },
  collectionDetails: {
    title: '项目收款明细',
    modal: collectionDetails
  },
  projectDetails: {
    title: '项目详情',
    modal: projectDetails
  },
  balanceDetails: {
    title: '项目盈亏明细',
    modal: balanceDetails
  }
}

const props = defineProps({
  // 业务名: 对应typeComponentMap的key
  currentComp: {
    type: String,
    default: ''
  },
  // 业务需要的id
  asDetailId: {
    type: String,
    default: ''
  }
})
</script>

<style scoped></style>

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_孤傲_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值