Vue3使用setup语法糖

大祥子
2022-02-10 / 0 评论 / 415 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年06月15日,已超过701天没有更新,若内容或图片失效,请留言反馈。

1、语法糖与非语法糖代码写法对比

<script lang="ts">
import { toRefs, reactive } from 'vue'
import navBar from '@/components/public/navBar.vue'
import foot from '@/components/public/foot.vue'
import productList from './components/product-list.vue'
/**
 * 普通写法非语法糖
 */
export default {
  name: '',
  props: {},
  components: { navBar, foot, productList },
  setup() {
    // 传参
    const state = reactive({
      navTitle: [{ name: '题目' }, { name: '题目' }, { name: '题目' }, { name: '题目' }, { name: '题目' }],
      mousee: '',
      mouseeIndex: 0,
    })
    const mouseenter = (data: any, index: number) => {
      state.mousee = data
      state.mouseeIndex = index
      console.log("? ~ file: index.vue ~ line 102 ~ mouseenter ~ state.mousee", state.mousee, index)
    }
    const mouseleave = () => {
      state.mousee = ''
    }
    return {
      ...toRefs(state),
      mouseenter,
      mouseleave
    }
  }
}
</script>

/**
 * setup语法糖写法
 */
<script lang="ts" setup>
import { toRefs, reactive } from 'vue'
import navBar from '@/components/public/navBar.vue'
import foot from '@/components/public/foot.vue'
import productList from './components/product-list.vue'

const state = reactive({
  navTitle: [{ name: '题目' }, { name: '题目' }, { name: '题目' }, { name: '题目' }, { name: '题目' }],
  mousee: '',
  mouseeIndex: 0,
})
const mouseenter = (data: any, index: number) => {
  state.mousee = data
  state.mouseeIndex = index
  console.log("? ~ file: index.vue ~ line 102 ~ mouseenter ~ state.mousee", state.mousee, index)
}
const mouseleave = () => {
  state.mousee = ''
}
let { navTitle, mousee, mouseeIndex } = toRefs(state) // 使用toRefs
</script>

2、如何在setup语法糖中使用props和配置TS使用(首先需要在<script setup>中使用defineProps来声明props,它具备完整的类型推断并且在<script setup>中是直接可用的)

/**
 *非setup语法糖使用props
 */
<script>
export default {
  props: ['more'],
}
</script>

/**
 *setup语法糖使用props
 */
<script lang="ts" setup>
import { reactive } from 'vue'
/**
 * 普通获取props数据
 */
const props = defineProps({
  more: {
    type: Object,
    default: {
      title: '',
      subhead: '',
      isMore: '',
      isMoreUrl: ''
    }
  }
  //或者:more: Object,more: {},虽然能正常使用但是页面使用的时候ts会报错未定义或者unknow
})

/**
 * TS获取props数据
 */
const props = defineProps<{
  more: Object
}>()

/**
 * TS获取props数据(默认值)
 * 引用:https://www.jianshu.com/p/102906089ab9
 * withDefaults 用于defineProps绑定默认值的api
 * defineProps 只能是要么使用运行时声明,要么使用typescript类型声明。同时使用两种声明方式会导致编译报错。
 * defineProps、withDefaults 是只在 <script setup> 语法糖中才能使用的编译器宏。他不需要导入且会随着 <script setup> 处理过程一同被编译掉。
 * 运行时声明 的方式只能设置参数类型、默认值、是否必传、自定义验证。
 * 若想设置[ 编辑器报错、编辑器语法提示 ]则需要使用类型声明的方式。
 */
interface Props {
  more?: {// 设置好类型定义
    title: string,
    subhead: string,
    isMore: string,
    isMoreUrl: string
  }
}
/**
 * 可以给定默认值
 */
const props = withDefaults(defineProps<Props>(), {
  more: () => {
    return {
      title: '',
      subhead: '',
      isMore: '',
      isMoreUrl: ''
    }
  }
})

</script>

3、如何在setup语法糖中使用emit和配置TS使用(首先需要在<script setup>中使用defineEmits来声明emits,它具备完整的类型推断并且在<script setup>中是直接可用的)

// 父组件调用子组件
<subheading @testEmits="testEmits"/>
// 父组件方法测试emits
const testEmits = (type: String) => {
  console.log('我是测试emits:', type)
}

/**
 * 子组件调用在非setup语法糖下
 */
<script>
export default {
  emits: ['testEmits'],
    emit('testEmits', '我是子组件调用的')
  }
}
</script>

/**
 * 子组件调用在setup语法糖下
 */
<script setup lang='ts'>
  import { defineEmits } from 'vue'
  const emit = defineEmits(['testEmit']) // 可以接收多个
  emit('testEmit', '我是子组件调用')
  // 在ts下使用
  const emit = defineEmits<{ // 类型声明
    (e: 'testEmit', value: String): void
  }>()
  emit('testEmit', 'test')
</script>

3、使用defineExpose(使用<script setup>的组件是默认关闭的,也即通过模板ref或者$parent链获取到的组件的公开实例,不会暴露任何在<script setup>中声明的绑定)

<script setup lang="ts">
  import { ref } from 'vue'
  const count = ref('我是子组件传递的值')
  defineExpose({
    count
  })
</script>
<template>
  <div @click="childClick">⽗组件</div>
  <child ref="child" />
</template>
<script setup lang="ts">
  import { ref } from 'vue'
  import child from './components/child.vue'
  const child = ref(null)
  const childClick = () => {
    console.log(child.value.count) // 我是子组件传递的值
  }
</script>
55

评论 (0)

取消