vue3中defineExpose的用法

一:默认情况下在<script setup>语法糖下组件内部的属性和方法是不开放给父组件访问的,可以通过definExpose()编译宏指定那些属性和方法允许访问。
需要注意的两点情况是

  1. 仅在vue 3.3+ 中支持
  2. definExpose编译宏的作用是显示暴露组件内部的属性和方法
  3. 子组件可以通过ref获取父组件的DOM,通过调用子组件暴露的属性和方法实现组件通信

二:这里我用definExpose写了一个关于弹框的demo,基于vue+Element Plus完成了组件通信,通过这种方式使得vue3的组件编写更加直观和简单。

  1. 在父组件ArticalChannel.vue中
<template>
  <div class="main-box">
      <el-card style="width:1000px;height:780px;">
        <template #header>
          <div class="card-header">
            <span>文章分类</span>
            <el-button @click="AddSort">添加分类</el-button>
          </div>
        </template>
          <el-table :data="tableData" border style="width: 100%">
            <el-table-column type="index" label="序号" width="180" />
            <el-table-column prop="classificationName" label="分类名称" />
            <el-table-column prop="classAlias" label="分类别名" />
            <el-table-column align="right">
              <template #default="scope">
                <el-button size="small" @click="handleEdit(scope.row)">
                  编辑
                </el-button>
                <el-button
                  size="small"
                  type="danger"
                  @click="handleDelete(scope.$index, scope.row)"
                >
                  删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
    </el-card>
    <add-dialog ref="childRef"></add-dialog>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import addDialog from './componts/add.vue'

const tableData = [
  {
    id:'1',
    classificationName: '记者',
    classAlias: 'journalist',
  },
  {
    id:'2',
    classificationName: '主持人',
    classAlias: 'emcee',
  },
]
const childRef = ref();
const handleEdit = (row)=>{
  childRef.value.open(row)
}
const AddSort = ()=>{
  childRef.value.open({})
}
</script>
<style scoped>
.main-box{
  margin-left: 50px;
}
.card-header{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
</style>

父组件中使用ref="childRef"访问子组件实例并调用暴露的属性和方法,下面子组件使用defineExpose暴露子组件内部的open方法。点击添加分类和编辑分类,实现弹框的一个简易封装。

  1. 在子组件add.vue中
<template>
    <el-dialog
        v-model="dialogVisible"
        :title="form.id?'编辑分类':'添加分类'"
        width="500"
    >
        <el-form :model="form" :rules="rules" ref="formRef">
            <el-form-item prop="classificationName" label="分类名称:">
                <el-input v-model="form.classificationName"></el-input>
            </el-form-item>
            <el-form-item prop="classAlias" label="分类别名:">
                <el-input  v-model="form.classAlias"></el-input>
            </el-form-item>
            <div class="dialog-footer">
                <el-button @click="dialogVisible = false">取消</el-button>
                <el-button type="primary" @click="submitForm">确认 </el-button>
            </div>
        </el-form>
    </el-dialog>
</template>
<script setup>
import { ref } from 'vue'
const dialogVisible = ref(false)
const form = ref({
    classificationName: '',
    classAlias: '',
})
const rules = {
    classificationName: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
    classAlias: [
        { required: true, message: '请输入分类别名', trigger: 'blur' },
    ],

}
//组件向外暴露一个open方法
//1:表单无渲染 添加
//2:表单需要渲染  编辑
//3:open打开弹窗
const open = (row)=>{
    dialogVisible.value = true
    form.value = {...row} //添加重置了表单内容  编辑存储了回显数据
}
defineExpose({
    open
})
const formRef = ref(null)
const submitForm = ()=>{
    formRef.value.validate( async (valid) => {
    if (valid) {
        //确认添加  确认修改
        console.log('submit!')
    } else {
        return false
    }
    })
}
</script>

三:效果展示如下

vue3中defineExpose的使用展示

### Vue3 中 `defineExpose` 的用法及其目的 在 Vue 3 Composition API 中引入了 `<script setup>` 语法糖,它简化了许多开发流程并提升了开发者体验。然而,在某些场景下,父组件可能需要访问子组件内部的状态或方法。为了实现这一需求,Vue 提供了一个名为 `defineExpose` 的宏工具。 #### 宏定义 `defineExpose` `defineExpose` 是用于显式声明哪些属性或方法可以从当前组件暴露给其父组件的一个工具[^1]。通过这种方式,可以控制哪些部分能够被外部访问,从而增强封装性和安全性。 以下是关于如何使用以及为什么要在脚本设置模式中使用它的具体说明: #### 使用示例 下面是一个简单的例子来展示 `defineExpose` 如何工作: ```vue <template> <button @click="increment">Increment</button> </template> <script setup> import { ref } from &#39;vue&#39; const count = ref(0) function increment() { count.value++ } // 显式地向外界暴露特定的内容 defineExpose({ count, increment }) </script> ``` 在这个例子中, 子组件中的 `count` 和 `increment()` 方法都被明确地标记为可对外部可见的部分。这意味着如果这个组件作为另一个更大应用的一部分存在的话,则可以通过模板引用的方式获取到这些公开的数据和行为。 #### 父级调用方式 假设我们有一个包含上述自定义按钮逻辑的小部件 (即上面创建的那个),那么可以在父级这样操作它们: ```vue <template> <child-component ref="myChildComponent"></child-component> <p>Count is {{ myChildComponent?.count }}</p> <button @click="handleClick">Call Increment From Parent</button> </template> <script setup> import ChildComponent from &#39;./path/to/ChildComponent.vue&#39; import { onMounted } from &#39;vue&#39; onMounted(() => { console.log(&#39;Exposed properties:&#39;, this.$refs.myChildComponent) }) function handleClick() { const childCompInstance = $refs.myChildComponent; if(childCompInstance && typeof childCompInstance.increment === &#39;function&#39;) { childCompInstance.increment(); } } </script> ``` 这里展示了当页面加载完成后会打印出由子组件所暴露出的对象;另外还提供了一种机制允许点击事件触发来自子组件的功能函数。 #### 设计意图 采用这种做法的主要原因是遵循最小权限原则——只让必要的东西变得可用而不是全部开放出去。这有助于保持良好的软件工程实践,减少不必要的耦合度,并使维护更加容易管理。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值