js css html

vue3 组合API的入口 setup 函数

2023-04-10  本文已影响0人  暴躁程序员

一、setup() 函数使用和注意事项

  1. setup 函数的执行时机在 beforCreate 之前
<template>
  <div></div>
</template>

<script>
export default {
  setup() {
    console.log("setup");
  },
  beforeCreate() {
    console.log("beforeCreate");
  },
};
</script>
  1. 在 setup() 中访问 this 的结果是 undefined,return 对象中的属性和方法会暴露给模板使用
<template>
  <h1>main</h1>
  <div>{{ count }}</div>
  <button @click="countAdd">count Add</button>
</template>
<script>
import { ref } from 'vue'

export default {
  setup() {
    console.log(this)
      
    const count = ref(1)
    function countAdd() {
      count.value++
    }
      
    return {
      count,
      countAdd
    }
  }
}
</script>
  1. 在vue3中也可使用vue2中的选项式API
    如果选项API和组合API定义的属性或方法的名称重复则以组合API为主,并且在选项式API中可以通过 this 来获取 setup() 暴露的属性和方法,但setup中无法获取选项API的属性或方法(无法通过this访问)
<template>
  <h1>main</h1>
  <h2>{{ a }}</h2>
  <h3>{{ optionB }}</h3>
</template>
<script>
import { ref } from 'vue'

export default {
  data() {
    return {
      a: 'a',
      optionB: this.b
    }
  },
  setup() {
    const a = ref('测试:当v3的组合API和v2的选项API定义属性重复时页面怎么展示')
    const b = ref('测试:选项API是否可以访问组合api定义的属性')

    // eslint-disable-next-line vue/no-dupe-keys
    return { a, b }
  }
}
</script>

4 setup函数的参数

第一个参数props响应式对象:

1. 等价于vue2中的 this.$props, 包含父组件透传的响应式参数,为响应式数据,必须在 props 中显示声明(用来区分props和attrs)
2. 注意:props参数在模板中直接使用是响应式数据,但是解构之后使用则不是响应式数据,需要使用 toRef 或者 toRefs 包装才能实现响应式解构

使用 toRef 或者 toRefs 实现 props 响应式解构

const count = toRef(props, 'count')
// 或者
const { count } = toRefs(props)

第二个参数context上下文对象:

1. attrs:等价于 this.$attrs,包含父组件所有透传的属性(不包含props定义的属性)。
2. slots:等价于 this.$slots 包含父组件所有透传的插槽对象,一般用来检测父组件是否使用了插槽
3. emit:等价于:this.$emit, 向父组件发布事件
4. expose:vue3新特性,有选择的向父组件暴露属性,默认不暴露(父组件可以通过ref使用子组件的属性和方法,我们可以通过 expose 开放父组件可以操作哪些子组件的属性和方法)

示例:

<template>
  <div>
    <h1>main</h1>
  </div>
</template>
<script>
export default {
  props: ['username', 'password'],
  setup(props, { attrs, slots, emit, expose }) {
    console.log('props', props)
    console.log('attrs', attrs) 
    console.log('slots', slots) 
    console.log('emit', emit)
    console.log('expose', expose) 
    // expose({username: props.username}) // 父组件可以使用props.username属性
  }
}
</script>

二、setup 语法糖

参考官网

在 script 标签中添加 setup 属性才可使用setup语法糖,这样就可以省略 setup 函数

1. 在<script setup></script> 中无法使用选项式 API,如果一定要使用选项式 API,可以再创建个 script 脚本

<template>
  <div></div>
</template>

<script setup>
console.log("setup");
</script>
<script>
export default {
  beforeCreate() {
    console.log("beforeCreate");
  },
};
</script>

2. 变量、函数和import导入的内容 ,不需要 return 暴露,就可直接在模板中使用

<template>
  <div>{{ count }}</div>
  <div>{{ msg }}</div>
  <button @click="countAdd()">count add</button>
</template>

<script setup>
import { ref } from 'vue'
import { msg } from './index.js'
const count = ref(1)
function countAdd() {
  count.value++
}
</script>

3. 组件可以直接引入并再模板中使用,不需要在 components 中进行注册

<template>
  <h1>main</h1>
  <Header></Header>
</template>

<script setup>
import Header from './Header.vue'
</script>

4. 原 setup 函数的参数:defineProps() 、defineEmits() 、defineExpose() 、useSlots()、useAttrs()

  1. defineProps() 只能在 <script setup> 标签中使用,且不需要 import 导入
<template>
  <h1>main</h1>
  <div>{{ props.count }}</div>
</template>

<script setup>
const props = defineProps({
  count: {
    type: Number,
    default: 0,
    required: false
  }
})
</script>
  1. defineEmits() 只能在 <script setup> 标签中使用,且不需要 import 导入
<template>
  <h1>main</h1>
  <button @click="changeParentMsg">changeParentMsg</button>
</template>

<script setup>
// 创建 emit
const emit = defineEmits(['changeMsgFromChild'])

// 调用 emit 并传参
function changeParentMsg() {
  emit('changeMsgFromChild', 'hello world')
}
</script>
  1. defineExpose() 只能在 <script setup> 标签中使用,且不需要 import 导入

在子组件中通过 defineExpose() 暴露属性给父组件

<template>
  <h1>main</h1>
  <div>{{ username }}</div>
  <div>{{ password }}</div>
</template>

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

const username = ref('tangsan')
const password = ref('123456')
defineExpose({
  username,
  password
})
</script>

在父组件中获取子组件暴露的属性

<template>
  <h1>APP</h1>
  <HomeView ref="child"></HomeView>
</template>
<script setup>
import HomeView from '@/views/HomeView.vue'
import { ref, onMounted } from 'vue'
const child = ref(null)
onMounted(() => {
  console.log(child.value.username)
})
</script>
  1. useSlots()、useAttrs() 只能在 <script setup> 标签中使用,需要以组合API的方式通过 import 导入后再使用
<template>
  <h1>main</h1>
</template>

<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
console.log(slots)
console.log(attrs)
</script>
上一篇下一篇

猜你喜欢

热点阅读