wip: class/style fallthrough compat
This commit is contained in:
parent
a75b00c558
commit
12abd4af85
22
packages/runtime-core/src/compat/attrsFallthrough.ts
Normal file
22
packages/runtime-core/src/compat/attrsFallthrough.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { isOn } from '@vue/shared'
|
||||||
|
import { ComponentInternalInstance } from '../component'
|
||||||
|
import { DeprecationTypes, isCompatEnabled } from './compatConfig'
|
||||||
|
|
||||||
|
export function shouldSkipAttr(
|
||||||
|
key: string,
|
||||||
|
instance: ComponentInternalInstance
|
||||||
|
): boolean {
|
||||||
|
if (
|
||||||
|
(key === 'class' || key === 'style') &&
|
||||||
|
isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
isOn(key) &&
|
||||||
|
isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@ -216,15 +216,15 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
[DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE]: {
|
[DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE]: {
|
||||||
message:
|
message: componentName =>
|
||||||
`vm.$attrs now includes class and style bindings passed from parent. ` +
|
`Component <${componentName}> has \`inheritAttrs: false\` but is ` +
|
||||||
`Components with inheritAttrs: false will no longer auto-inherit ` +
|
`relying on class/style fallthrough from parent. In Vue 3, class/style ` +
|
||||||
`class/style on its root element. If your code relies on this behavior, ` +
|
`are now included in $attrs and will no longer fallthrough when ` +
|
||||||
`you may see broken styling and need to adjust your CSS. Otherwise, ` +
|
`inheritAttrs is false. If you are already using v-bind="$attrs" on ` +
|
||||||
`you can disable the compat behavior and suppress this warning with:` +
|
`component root it should render the same end result. ` +
|
||||||
`\n\n configureCompat({ ${
|
`If you are binding $attrs to a non-root element and expecting ` +
|
||||||
DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE
|
`class/style to fallthrough on root, you will need to now manually bind ` +
|
||||||
}: false )\n`,
|
`them on root via :class="$attrs.class".`,
|
||||||
link: `https://v3.vuejs.org/guide/migration/attrs-includes-class-style.html`
|
link: `https://v3.vuejs.org/guide/migration/attrs-includes-class-style.html`
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import { getCompatChildren } from './instanceChildren'
|
|||||||
import {
|
import {
|
||||||
DeprecationTypes,
|
DeprecationTypes,
|
||||||
assertCompatEnabled,
|
assertCompatEnabled,
|
||||||
checkCompatEnabled,
|
|
||||||
isCompatEnabled
|
isCompatEnabled
|
||||||
} from './compatConfig'
|
} from './compatConfig'
|
||||||
import { off, on, once } from './instanceEventEmitter'
|
import { off, on, once } from './instanceEventEmitter'
|
||||||
@ -75,14 +74,6 @@ export function installCompatInstanceProperties(map: PublicPropertiesMap) {
|
|||||||
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
return __DEV__ ? shallowReadonly(i.slots) : i.slots
|
||||||
},
|
},
|
||||||
|
|
||||||
// overrides existing accessor
|
|
||||||
$attrs: i => {
|
|
||||||
if (__DEV__ && i.type.inheritAttrs === false) {
|
|
||||||
checkCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, i)
|
|
||||||
}
|
|
||||||
return __DEV__ ? shallowReadonly(i.attrs) : i.attrs
|
|
||||||
},
|
|
||||||
|
|
||||||
$on: i => on.bind(null, i),
|
$on: i => on.bind(null, i),
|
||||||
$once: i => once.bind(null, i),
|
$once: i => once.bind(null, i),
|
||||||
$off: i => off.bind(null, i),
|
$off: i => off.bind(null, i),
|
||||||
|
@ -20,8 +20,7 @@ import {
|
|||||||
isReservedProp,
|
isReservedProp,
|
||||||
EMPTY_ARR,
|
EMPTY_ARR,
|
||||||
def,
|
def,
|
||||||
extend,
|
extend
|
||||||
isOn
|
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import {
|
import {
|
||||||
@ -37,6 +36,7 @@ import { AppContext } from './apiCreateApp'
|
|||||||
import { createPropsDefaultThis } from './compat/props'
|
import { createPropsDefaultThis } from './compat/props'
|
||||||
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
|
import { isCompatEnabled, softAssertCompatEnabled } from './compat/compatConfig'
|
||||||
import { DeprecationTypes } from './compat/compatConfig'
|
import { DeprecationTypes } from './compat/compatConfig'
|
||||||
|
import { shouldSkipAttr } from './compat/attrsFallthrough'
|
||||||
|
|
||||||
export type ComponentPropsOptions<P = Data> =
|
export type ComponentPropsOptions<P = Data> =
|
||||||
| ComponentObjectPropsOptions<P>
|
| ComponentObjectPropsOptions<P>
|
||||||
@ -229,11 +229,7 @@ export function updateProps(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (__COMPAT__ && shouldSkipAttr(key, instance)) {
|
||||||
__COMPAT__ &&
|
|
||||||
isOn(key) &&
|
|
||||||
isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)
|
|
||||||
) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (value !== attrs[key]) {
|
if (value !== attrs[key]) {
|
||||||
@ -341,11 +337,7 @@ function setFullProps(
|
|||||||
// Any non-declared (either as a prop or an emitted event) props are put
|
// Any non-declared (either as a prop or an emitted event) props are put
|
||||||
// into a separate `attrs` object for spreading. Make sure to preserve
|
// into a separate `attrs` object for spreading. Make sure to preserve
|
||||||
// original key casing
|
// original key casing
|
||||||
if (
|
if (__COMPAT__ && shouldSkipAttr(key, instance)) {
|
||||||
__COMPAT__ &&
|
|
||||||
isOn(key) &&
|
|
||||||
isCompatEnabled(DeprecationTypes.INSTANCE_LISTENERS, instance)
|
|
||||||
) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (value !== attrs[key]) {
|
if (value !== attrs[key]) {
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
ComponentInternalInstance,
|
ComponentInternalInstance,
|
||||||
FunctionalComponent,
|
FunctionalComponent,
|
||||||
Data
|
Data,
|
||||||
|
getComponentName
|
||||||
} from './component'
|
} from './component'
|
||||||
import {
|
import {
|
||||||
VNode,
|
VNode,
|
||||||
@ -20,6 +21,11 @@ import { isHmrUpdating } from './hmr'
|
|||||||
import { NormalizedProps } from './componentProps'
|
import { NormalizedProps } from './componentProps'
|
||||||
import { isEmitListener } from './componentEmits'
|
import { isEmitListener } from './componentEmits'
|
||||||
import { setCurrentRenderingInstance } from './componentRenderContext'
|
import { setCurrentRenderingInstance } from './componentRenderContext'
|
||||||
|
import {
|
||||||
|
DeprecationTypes,
|
||||||
|
isCompatEnabled,
|
||||||
|
warnDeprecation
|
||||||
|
} from './compat/compatConfig'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev only flag to track whether $attrs was used during render.
|
* dev only flag to track whether $attrs was used during render.
|
||||||
@ -117,7 +123,7 @@ export function renderComponentRoot(
|
|||||||
;[root, setRoot] = getChildRoot(result)
|
;[root, setRoot] = getChildRoot(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Component.inheritAttrs !== false && fallthroughAttrs) {
|
if (fallthroughAttrs && Component.inheritAttrs !== false) {
|
||||||
const keys = Object.keys(fallthroughAttrs)
|
const keys = Object.keys(fallthroughAttrs)
|
||||||
const { shapeFlag } = root
|
const { shapeFlag } = root
|
||||||
if (keys.length) {
|
if (keys.length) {
|
||||||
@ -175,6 +181,29 @@ export function renderComponentRoot(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
__COMPAT__ &&
|
||||||
|
isCompatEnabled(DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE, instance) &&
|
||||||
|
vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT &&
|
||||||
|
(root.shapeFlag & ShapeFlags.ELEMENT ||
|
||||||
|
root.shapeFlag & ShapeFlags.COMPONENT)
|
||||||
|
) {
|
||||||
|
const { class: cls, style } = vnode.props || {}
|
||||||
|
if (cls || style) {
|
||||||
|
if (__DEV__ && Component.inheritAttrs === false) {
|
||||||
|
warnDeprecation(
|
||||||
|
DeprecationTypes.INSTANCE_ATTRS_CLASS_STYLE,
|
||||||
|
instance,
|
||||||
|
getComponentName(instance.type)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
root = cloneVNode(root, {
|
||||||
|
class: cls,
|
||||||
|
style: style
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// inherit directives
|
// inherit directives
|
||||||
if (vnode.dirs) {
|
if (vnode.dirs) {
|
||||||
if (__DEV__ && !isElementRoot(root)) {
|
if (__DEV__ && !isElementRoot(root)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user