element-plus 二次封装遇到的一点疑惑
事情起因很简单,今天看了篇文章 跟着 Vue团队大佬学习在 Vue3 中二次封装组件 ,觉得有趣,遂实践了一下,发现某些情况下
v-model值UI上不同步更新,本想回复原文章,但是由于评论字数限制不放不下 element-plus playground 的链接,所以单开了这篇文章!
🚑场景复现
原文的一些知识就不多做介绍了,有兴趣的移步原文即可。
介绍一下我的场景,当当当当~~~~~
这里有一个二次封装 el-input 的组件 Comp.vue,因为playground 不能使用导入类型使用,所以仅保留了 modalValue 这一个属性。
<template>
<div>
<component :is="h(ElInput, $props, slots)" ref="inputRef"></component>
</div>
</template>
<script lang="ts" setup>
import { type ExtractPublicPropTypes, ref, h, useAttrs, mergeProps, useSlots } from 'vue'
import { ElInput } from 'element-plus';
type InputProps = ExtractPublicPropTypes<{ modelValue: any }> & {};
const props = withDefaults(defineProps<InputProps>(), {})
const slots = useSlots();
const attrs = useAttrs();
// 以下两种方式都是会丢失响应性的,要将右侧值放到模板里面做解构
const $props = mergeProps(attrs, props)
// const $props = { ...attrs, ...props }
const inputRef = ref()
defineExpose({
inputRef,
})
</script>
将 Comp.vue 放在 App.vue 中使用
<template>
<div>
<Comp ref="CompEl" v-model="modelVal" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Comp from './Comp.vue';
const CompEl = ref();
const modelVal = ref('ethan')
setTimeout(() => {
console.log(222222,CompEl.value.inputRef)
CompEl.value.inputRef?.clear()
console.log('after clear: ', modelVal.value)
}, 1000)
</script>
主要的功能就是外部调用 el-input 的清空的方法 clear,以达到一秒后清除输入框内容的效果。结果值是被清空了,但是输入框的值没有变!这你能忍?我反正是忍不了😠!
关键在这🔑
我排查了好一会发现了关键!在下面两种定义 props 的方式中,先定义,之后再拿到模板里去使用,v-model 值变了, 单视图就不会变!!
// 以下两种方式都是会丢失响应性的,要将右侧值放到模板里面做解构
const $props = mergeProps(attrs, props)
// const $props = { ...attrs, ...props }
如果拿赋值右边的值去作为props,一切正常!🎉🎉🎉
<template>
<div>
<component :is="h(ElInput, mergeProps(attrs, props), slots )" ref="inputRef"></component>
</div>
</template>
当然这无关动态组件,el-input 的 v-bind 也是无效的!
<template>
<div>
<el-input v-bind="$props" ref="inputRef"></el-input>
</div>
</template>
不知道为啥掘金跳转有问题!
https://element-plus.run/#eyJBcHAudnVlIjoiPHRlbXBsYXRlPlxuICA8ZGl2PlxuICAgIDxDb21wIHJlZj1cIkNvbXBFbFwiIHYtbW9kZWw9XCJtb2RlbFZhbFwiIC8+XG4gIDwvZGl2PlxuPC90ZW1wbGF0ZT5cblxuPHNjcmlwdCBsYW5nPVwidHNcIiBzZXR1cD5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcbmltcG9ydCBDb21wIGZyb20gJy4vQ29tcC52dWUnO1xuXG5jb25zdCBDb21wRWwgPSByZWYoKTtcbmNvbnN0IG1vZGVsVmFsID0gcmVmKCdldGhhbicpXG5zZXRUaW1lb3V0KCgpID0+IHtcbiAgY29uc29sZS5sb2coMjIyMjIyLENvbXBFbC52YWx1ZS5pbnB1dFJlZilcbiAgQ29tcEVsLnZhbHVlLmlucHV0UmVmPy5jbGVhcigpXG4gIGNvbnNvbGUubG9nKCdhZnRlciBjbGVhcjogJywgbW9kZWxWYWwudmFsdWUpXG59LCAxMDAwKVxuPC9zY3JpcHQ+XG4iLCJlbGVtZW50LXBsdXMuanMiOiJpbXBvcnQgRWxlbWVudFBsdXMgZnJvbSAnZWxlbWVudC1wbHVzJ1xuaW1wb3J0IHsgZ2V0Q3VycmVudEluc3RhbmNlIH0gZnJvbSAndnVlJ1xuXG5sZXQgaW5zdGFsbGVkID0gZmFsc2VcbmF3YWl0IGxvYWRTdHlsZSgpXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cEVsZW1lbnRQbHVzKCkge1xuICBpZiAoaW5zdGFsbGVkKSByZXR1cm5cbiAgY29uc3QgaW5zdGFuY2UgPSBnZXRDdXJyZW50SW5zdGFuY2UoKVxuICBpbnN0YW5jZS5hcHBDb250ZXh0LmFwcC51c2UoRWxlbWVudFBsdXMpXG4gIGluc3RhbGxlZCA9IHRydWVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRTdHlsZSgpIHtcbiAgY29uc3Qgc3R5bGVzID0gWydodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL2VsZW1lbnQtcGx1c0BsYXRlc3QvZGlzdC9pbmRleC5jc3MnLCAnaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9lbGVtZW50LXBsdXNAbGF0ZXN0L3RoZW1lLWNoYWxrL2RhcmsvY3NzLXZhcnMuY3NzJ10ubWFwKChzdHlsZSkgPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGluaycpXG4gICAgICBsaW5rLnJlbCA9ICdzdHlsZXNoZWV0J1xuICAgICAgbGluay5ocmVmID0gc3R5bGVcbiAgICAgIGxpbmsuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIHJlc29sdmUpXG4gICAgICBsaW5rLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgcmVqZWN0KVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQobGluaylcbiAgICB9KVxuICB9KVxuICByZXR1cm4gUHJvbWlzZS5hbGxTZXR0bGVkKHN0eWxlcylcbn1cbiIsInRzY29uZmlnLmpzb24iOiJ7XG4gIFwiY29tcGlsZXJPcHRpb25zXCI6IHtcbiAgICBcInRhcmdldFwiOiBcIkVTTmV4dFwiLFxuICAgIFwianN4XCI6IFwicHJlc2VydmVcIixcbiAgICBcIm1vZHVsZVwiOiBcIkVTTmV4dFwiLFxuICAgIFwibW9kdWxlUmVzb2x1dGlvblwiOiBcIkJ1bmRsZXJcIixcbiAgICBcInR5cGVzXCI6IFtcImVsZW1lbnQtcGx1cy9nbG9iYWwuZC50c1wiXSxcbiAgICBcImFsbG93SW1wb3J0aW5nVHNFeHRlbnNpb25zXCI6IHRydWUsXG4gICAgXCJhbGxvd0pzXCI6IHRydWUsXG4gICAgXCJjaGVja0pzXCI6IHRydWVcbiAgfSxcbiAgXCJ2dWVDb21waWxlck9wdGlvbnNcIjoge1xuICAgIFwidGFyZ2V0XCI6IDMuM1xuICB9XG59XG4iLCJQbGF5Z3JvdW5kTWFpbi52dWUiOiI8c2NyaXB0IHNldHVwPlxuaW1wb3J0IEFwcCBmcm9tICcuL0FwcC52dWUnXG5pbXBvcnQgeyBzZXR1cEVsZW1lbnRQbHVzIH0gZnJvbSAnLi9lbGVtZW50LXBsdXMuanMnXG5zZXR1cEVsZW1lbnRQbHVzKClcbjwvc2NyaXB0PlxuXG48dGVtcGxhdGU+XG4gIDxBcHAgLz5cbjwvdGVtcGxhdGU+XG4iLCJpbXBvcnQtbWFwLmpzb24iOiJ7XG4gIFwiaW1wb3J0c1wiOiB7XG4gICAgXCJ2dWVcIjogXCJodHRwczovL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL0B2dWUvcnVudGltZS1kb21AbGF0ZXN0L2Rpc3QvcnVudGltZS1kb20uZXNtLWJyb3dzZXIuanNcIixcbiAgICBcIkB2dWUvc2hhcmVkXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AdnVlL3NoYXJlZEBsYXRlc3QvZGlzdC9zaGFyZWQuZXNtLWJ1bmRsZXIuanNcIixcbiAgICBcImVsZW1lbnQtcGx1c1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQGxhdGVzdC9kaXN0L2luZGV4LmZ1bGwubWluLm1qc1wiLFxuICAgIFwiZWxlbWVudC1wbHVzL1wiOiBcImh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vZWxlbWVudC1wbHVzQGxhdGVzdC9cIixcbiAgICBcIkBlbGVtZW50LXBsdXMvaWNvbnMtdnVlXCI6IFwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AZWxlbWVudC1wbHVzL2ljb25zLXZ1ZUAyL2Rpc3QvaW5kZXgubWluLmpzXCJcbiAgfSxcbiAgXCJzY29wZXNcIjoge31cbn0iLCJDb21wLnZ1ZSI6Ijx0ZW1wbGF0ZT5cbiAgPGRpdj5cbiAgICA8Y29tcG9uZW50IDppcz1cImgoRWxJbnB1dCwgeyAuLi4kcHJvcHMgfSwgc2xvdHMgKVwiIHJlZj1cImlucHV0UmVmXCI+PC9jb21wb25lbnQ+XG4gIDwvZGl2PlxuPC90ZW1wbGF0ZT5cblxuPHNjcmlwdCBsYW5nPVwidHNcIiBzZXR1cD5cbmltcG9ydCB7IHR5cGUgRXh0cmFjdFB1YmxpY1Byb3BUeXBlcywgcmVmLCBoLCB1c2VBdHRycywgbWVyZ2VQcm9wcywgdXNlU2xvdHMgfSBmcm9tICd2dWUnXG5pbXBvcnQgeyBFbElucHV0IH0gZnJvbSAnZWxlbWVudC1wbHVzJztcbmltcG9ydCB0eXBlIHsgSW5wdXRQcm9wcyBhcyBFbElucHV0UHJvcHMsIElucHV0SW5zdGFuY2UgYXMgRWxJbnB1dEluc3RhbmNlIH0gZnJvbSAnZWxlbWVudC1wbHVzJztcblxudHlwZSBJbnB1dFByb3BzID0gRXh0cmFjdFB1YmxpY1Byb3BUeXBlczx7IG1vZGVsVmFsdWU6IGFueSB9PiAmIHt9O1xuY29uc3QgcHJvcHMgPSB3aXRoRGVmYXVsdHMoZGVmaW5lUHJvcHM8SW5wdXRQcm9wcz4oKSwge30pXG5jb25zdCBzbG90cyA9IHVzZVNsb3RzKCk7XG5jb25zdCBhdHRycyA9IHVzZUF0dHJzKCk7XG4vLyDku6XkuIvkuKTnp43mlrnlvI/pg73mmK/kvJrkuKLlpLHlk43lupTmgKfnmoTvvIzopoHlsIblj7PkvqflgLzmlL7liLDmqKHmnb/ph4zpnaLlgZrop6PmnoRcbmNvbnN0ICRwcm9wcyA9IG1lcmdlUHJvcHMoYXR0cnMsIHByb3BzKVxuLy8gY29uc3QgJHByb3BzID0geyAuLi5hdHRycywgLi4ucHJvcHMgfVxuXG5jb25zdCBpbnB1dFJlZiA9IHJlZigpXG5cbmRlZmluZUV4cG9zZSh7XG4gIGlucHV0UmVmLFxufSlcbjwvc2NyaXB0PlxuIiwiQ29tcDEudnVlIjoiPHRlbXBsYXRlPlxyXG4gIDxkaXY+XHJcbiAgICA8ZWwtaW5wdXQgdi1iaW5kPVwiJHByb3BzXCIgcmVmPVwiaW5wdXRSZWZcIj48L2VsLWlucHV0PlxyXG4gIDwvZGl2PlxyXG48L3RlbXBsYXRlPlxyXG5cclxuPHNjcmlwdCBsYW5nPVwidHNcIiBzZXR1cD5cclxuaW1wb3J0IHsgdHlwZSBFeHRyYWN0UHVibGljUHJvcFR5cGVzLCByZWYsIGgsIHVzZUF0dHJzLCBtZXJnZVByb3BzLCB1c2VTbG90cyB9IGZyb20gJ3Z1ZSdcclxuaW1wb3J0IHR5cGUgeyBJbnB1dFByb3BzIGFzIEVsSW5wdXRQcm9wcywgSW5wdXRJbnN0YW5jZSBhcyBFbElucHV0SW5zdGFuY2UgfSBmcm9tICdlbGVtZW50LXBsdXMnO1xyXG5cclxudHlwZSBJbnB1dFByb3BzID0gRXh0cmFjdFB1YmxpY1Byb3BUeXBlczx7IG1vZGVsVmFsdWU6IGFueSB9PiAmIHt9O1xyXG5jb25zdCBwcm9wcyA9IHdpdGhEZWZhdWx0cyhkZWZpbmVQcm9wczxJbnB1dFByb3BzPigpLCB7fSlcclxuY29uc3Qgc2xvdHMgPSB1c2VTbG90cygpO1xyXG5jb25zdCBhdHRycyA9IHVzZUF0dHJzKCk7XHJcbi8vIOS7peS4i+S4pOenjeaWueW8j+mDveaYr+S8muS4ouWkseWTjeW6lOaAp+eahO+8jOimgeWwhuWPs+S+p+WAvOaUvuWIsOaooeadv+mHjOmdouWBmuino+aehFxyXG5jb25zdCAkcHJvcHMgPSBtZXJnZVByb3BzKGF0dHJzLCBwcm9wcylcclxuLy8gY29uc3QgJHByb3BzID0geyAuLi5hdHRycywgLi4ucHJvcHMgfVxyXG5cclxuY29uc3QgaW5wdXRSZWYgPSByZWYoKVxyXG5cclxuZGVmaW5lRXhwb3NlKHtcclxuICBpbnB1dFJlZixcclxufSlcclxuPC9zY3JpcHQ+IiwiX28iOnt9fQ==
睡了睡了😪
原因暂时没去深究,看有没有同僚给我解惑😁😁😁
夜已深,我欲入眠!文章就写到这,后面找到原因了再续上。
此时呵欠一连串涌上来🥱,睫毛粘成一片,没等撑住,粗重的呼噜已经断断续续撞进耳朵~~zz~~ZZZ😪