美文网首页js css html
vue3 组合API的入口 setup 函数

vue3 组合API的入口 setup 函数

作者: 暴躁程序员 | 来源:发表于2023-04-10 14:54 被阅读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>
    

    相关文章

      网友评论

        本文标题:vue3 组合API的入口 setup 函数

        本文链接:https://www.haomeiwen.com/subject/tvfwddtx.html