本文整理了常见但容易混淆的几个 Vue 3 前端开发问题,包括插槽、原型链、响应式数据处理、v-model 报错、样式阴影控制等,建议收藏学习!
在组件中使用如下代码:
<slot :name="item.prop">
<component
:is="getComponentType(item.type)"
v-model="formModel[item.prop]"
v-bind="getComponentProps(item)"
clearable
style="width: 100%"
/>
slot>
为什么加了
,父组件传了插槽就会生效,没传就自动使用默认内容?
这是 Vue 插槽的 fallback(回退)机制:
插槽,就渲染插槽内容;
标签中的默认内容。子组件
父组件 A(没传插槽)
➡️ 渲染默认
父组件 B(传了插槽)
男
女
➡️ 渲染插槽内容
h()
函数参数说明h(type, props?, children?)
参数 | 含义 |
---|---|
type | 标签名或组件(字符串、对象) |
props | class、style、事件、props |
children | 字符串、VNode数组、插槽函数等 |
h('div', { class: 'box' }, 'Hello') // Hello
h(MyComponent, { propA: 1 }, { default: () => h('span', '插槽内容') })
unref()
不能去掉 Proxy?function handleSearch() {
emit('search', unref(props.queryParams))
}
打印结果为什么还是 Proxy?
unref()
只能解包 ref()
类型reactive()
返回的是 Proxy,不会被 unref()
解包unref(reactiveObj)
仍然是 ProxytoRaw()
(浅解包)import { toRaw } from 'vue'
emit('search', toRaw(props.queryParams))
cloneDeep()
(推荐,深拷贝)import cloneDeep from 'lodash-es/cloneDeep'
emit('search', cloneDeep(props.queryParams))
toRaw
vs unref
的区别方法 | 用途 | 解包对象 | 是否保留响应式 |
---|---|---|---|
unref() |
取出 ref 的 .value |
只能 ref | 是(ref.value 仍可能是 reactive) |
toRaw() |
获取原始对象(去 Proxy) | 只能 reactive | 否 |
null
为止。const obj = {}
Object.getPrototypeOf(obj) // → Object.prototype
Object.getPrototypeOf(Object.prototype) // → null ✅
类型 | 原型链结构 |
---|---|
对象 {} |
obj → Object.prototype → null |
数组 [] |
→ Array.prototype → Object.prototype → null |
函数 function () {} |
→ Function.prototype → Object.prototype → null |
v-model cannot be used on a prop
在组件中这样写:
而 modelValue
是 defineProps()
得到的 prop
,Vue 提示该属性是只读的!
v-model
) emit('update:modelValue', val)"
/>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
box-shadow: 0 0 0 1px var(--el-input-border-color) inset;
box-shadow:
inset 1px 0 0 var(--el-input-border-color), /* 左 */
inset 0 1px 0 var(--el-input-border-color), /* 上 */
inset 0 -1px 0 var(--el-input-border-color); /* 下 */
不写右边的就相当于去掉右侧边框效果。
modelValue
作为 v-model 的绑定值;--el-input-border-color
、--el-border-color
、--el-color-primary
等。你可以封装一个自动脱 Proxy 工具:
import { toRaw, isRef, unref } from 'vue'
import cloneDeep from 'lodash-es/cloneDeep'
export function cleanReactive(val: any) {
if (isRef(val)) return unref(val)
if (val && val.__v_isReactive) return cloneDeep(toRaw(val))
return val
}