vue3 element plus 自定义组件封装,多层双向绑定v-model

日常,我们可能对element plus的组件进行进一步封装,而且可能是多层,那么要想实现双向绑定:

  1. 显式

:绑定属性,@绑定事件,事件中修改属性

  1. 隐式

v-model

第一种无需多说,第二种简单示例,以Dialog组件示例

  • 直接使用
    Dialog.vue
<template>
  <el-button @click="handleClick">切换</el-button>
  <el-dialog v-model="visible"></el-dialog>
</template>
<script setup lang="ts">
const visible=ref(false)

const handleClick=()=>{
  visible.value=!visible.value;
}
</script>
<style scoped></style>
  • 一层封装
    Dialog.vue
<template>
  <el-dialog v-model="visible"></el-dialog>
</template>
<script setup lang="ts">
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
});
const visible = computed({
  get: () => props.modelValue,
  set: val => {
    emit("update:modelValue", val);
  },
});
const emit = defineEmits(["update:modelValue"]);
</script>
<style scoped></style>

BaseDialog.vue

<template>
  <el-button @click="handleClick">切换</el-button>
  <Dialog v-model="visible"></Dialog>
</template>
<script setup lang="ts">
import Dialog from './Dialog.vue'
const visible=ref(false)

const handleClick=()=>{
  visible.value=!visible.value;
}
</script>
<style scoped></style>
  • 两层封装
    Dialog.vue
<template>
  <el-dialog v-model="visible"></el-dialog>
</template>
<script setup lang="ts">
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
});
const visible = computed({
  get: () => props.modelValue,
  set: val => {
    emit("update:modelValue", val);
  },
});
const emit = defineEmits(["update:modelValue"]);
</script>
<style scoped></style>

BaseDialog.vue

<template>
  <Dialog v-model="visible"></Dialog>
</template>
<script setup lang="ts">
import Dialog from './Dialog.vue'
const props = defineProps({
  modelValue: {
    type: Boolean,
    default: false,
  },
});
const visible = computed({
  get: () => props.modelValue,
  set: val => {
    emit("update:modelValue", val);
  },
});
const emit = defineEmits(["update:modelValue"]);
</script>
<style scoped></style>

CustomDialog.vue

<template>
  <el-button @click="handleClick">切换</el-button>
  <BaseDialog v-model="visible"></BaseDialog>
</template>
<script setup lang="ts">
import BaseDialog from './BaseDialog.vue'
const visible=ref(false)

const handleClick=()=>{
  visible.value=!visible.value;
}
</script>
<style scoped></style>

总结:多层双向绑定时,除了最上层v-model绑定ref变量,其他层都绑定计算属性,并且计算属性实现getter和setter(当然也可以不用计算属性,依然绑定ref变量,然后通过事件进行变化值传递)

### 关于 Element-UI 的面试题目 #### 表单验证机制 Element-UI 提供了一种简单而强大的方式来处理表单验证。`model`用于绑定表单的数据源,`prop`用来获取特定输入框的内容,而`ref`则可以指向具体的DOM节点以便执行自定义操作或者调用内置方法来进行前后端交互验证[^2]。 对于复杂的场景下,例如在一个列表中动态生成多个相同的输入项时,可以通过遍历这些元素并应用各自的校验规则实现逐个检验的功能。这通常涉及到利用Vue的计算属性或侦听器监听变化,并结合`v-for`指令完成循环渲染的同时设置唯一的键名确保每个实例都能被独立识别和管理。 #### 组件二次封装经验 当面对项目中的通用需求或是为了简化开发流程提高效率的时候,可能会考虑对官方提供的基础组件进行扩展定制——即所谓的“二次封装”。这种做法不仅能够减少重复代码量而且有助于统一风格保持一致性。比如创建一个带有默认配置参数的新版本按钮控件,在其内部隐藏了原始Button的所有复杂选项只暴露必要的几个给外部使用者;或者是增强Select的选择逻辑加入记忆上次选中值等功能特性。 #### Dialog 属性 `append-to-body` 在某些情况下,特别是存在多层弹窗叠加显示的需求时,正确理解并运用`append-to-body`这个布尔类型的属性就显得尤为重要了。如果将其设为true,则意味着当前对话框将会附加到页面最外层而非父级容器之下,从而避免样式冲突问题同时也更有利于布局调整。值得注意的是,任何子级别的模态窗口都应当显式声明此标记以保证正常工作[^3]。 #### 按需加载实践 考虑到大型应用程序可能只需要其中一小部分功能模块的情况,采用按需导入策略无疑是一种优化性能的有效手段之一。具体来说就是在项目的入口文件(main.js)里面仅注册那些真正要用到的小部件而不是整个库全部引入进来造成不必要的资源浪费。下面是一个简单的例子展示了如何单独挑选出Button和Select两个常用组件: ```javascript import { createApp } from &#39;vue&#39;; import App from &#39;./App.vue&#39;; // 只引入所需的组件 import { ElButton, ElSelect } from &#39;element-plus&#39;; const app = createApp(App); app.component(&#39;el-button&#39;, ElButton); app.component(&#39;el-select&#39;, ElSelect); app.mount(&#39;#app&#39;); ``` 上述代码片段说明了怎样通过解构赋值的方式精确选取所需的部分,进而达到减小打包体积的目的[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值