mirror of https://github.com/vuejs/core.git
Merge 74d74d77f4
into 56be3dd4db
This commit is contained in:
commit
7ac8263bdc
|
@ -7,6 +7,8 @@ import {
|
|||
vModelCheckbox,
|
||||
withDirectives,
|
||||
} from '../src'
|
||||
import { defineComponent } from '@vue/runtime-test'
|
||||
import { render as domRender } from 'vue'
|
||||
|
||||
describe('runtime-dom: props patching', () => {
|
||||
test('basic', () => {
|
||||
|
@ -395,3 +397,114 @@ describe('runtime-dom: props patching', () => {
|
|||
expect(fn).toBeCalledTimes(0)
|
||||
})
|
||||
})
|
||||
|
||||
// #13055
|
||||
test('should lookup camelCase keys in element properties', async () => {
|
||||
class TestElement extends HTMLElement {
|
||||
_complexData = {}
|
||||
|
||||
get primitiveValue(): string | null {
|
||||
return this.getAttribute('primitive-value')
|
||||
}
|
||||
|
||||
set primitiveValue(value: string | undefined) {
|
||||
if (value) {
|
||||
this.setAttribute('primitive-value', value)
|
||||
} else {
|
||||
this.removeAttribute('primitive-value')
|
||||
}
|
||||
}
|
||||
|
||||
get complexData() {
|
||||
return this._complexData
|
||||
}
|
||||
|
||||
set complexData(data) {
|
||||
this._complexData = data
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('test-element', TestElement)
|
||||
const el = document.createElement('test-element') as TestElement
|
||||
|
||||
patchProp(el, 'primitive-value', null, 'foo')
|
||||
expect(el.primitiveValue).toBe('foo')
|
||||
|
||||
patchProp(el, 'complex-data', null, { foo: 'bar' })
|
||||
expect(el.hasAttribute('complex-data')).toBe(false)
|
||||
expect(el.getAttribute('complex-data')).not.toBe('[object Object]')
|
||||
expect(el.complexData).toStrictEqual({ foo: 'bar' })
|
||||
})
|
||||
|
||||
// #13055
|
||||
test('should handle kebab-case prop bindings', async () => {
|
||||
class HelloWorld extends HTMLElement {
|
||||
#testProp = ''
|
||||
#output: HTMLDivElement
|
||||
|
||||
get testProp() {
|
||||
return this.#testProp
|
||||
}
|
||||
|
||||
set testProp(value: string) {
|
||||
this.#testProp = value
|
||||
this.#update()
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
this.attachShadow({ mode: 'open' })
|
||||
this.shadowRoot!.innerHTML = `<div class="output"></div>`
|
||||
this.#output = this.shadowRoot?.querySelector('.output') as HTMLDivElement
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
console.log('UPDATING!')
|
||||
this.#update()
|
||||
}
|
||||
|
||||
#update() {
|
||||
this.#output.innerHTML = `this.testProp = ${this.#testProp}`
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define('hello-world', HelloWorld)
|
||||
|
||||
const Comp = defineComponent({
|
||||
setup() {
|
||||
const testProp = ref('Hello, world! from App.vue')
|
||||
return {
|
||||
testProp,
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<hello-world .testProp="testProp" />
|
||||
<hello-world .test-prop="testProp" />
|
||||
<hello-world .test-prop.camel="testProp" />
|
||||
`,
|
||||
})
|
||||
|
||||
const root = document.createElement('div')
|
||||
|
||||
// Note this one is using the main Vue render so it can compile template
|
||||
// on the fly
|
||||
domRender(h(Comp), root)
|
||||
|
||||
expect(root.innerHTML).toBe(
|
||||
`<hello-world></hello-world><hello-world></hello-world><hello-world></hello-world>`,
|
||||
)
|
||||
|
||||
const [child1, child2, child3] = Array.from(
|
||||
root.querySelectorAll('hello-world'),
|
||||
)
|
||||
expect(child3.shadowRoot?.innerHTML).toBe(
|
||||
'<div class="output">this.testProp = Hello, world! from App.vue</div>',
|
||||
)
|
||||
expect(child2.shadowRoot?.innerHTML).toBe(
|
||||
'<div class="output">this.testProp = Hello, world! from App.vue</div>',
|
||||
)
|
||||
expect(child1.shadowRoot?.innerHTML).toBe(
|
||||
'<div class="output">this.testProp = Hello, world! from App.vue</div>',
|
||||
)
|
||||
})
|
||||
|
|
|
@ -47,7 +47,9 @@ export const patchProp: DOMRendererOptions['patchProp'] = (
|
|||
? ((key = key.slice(1)), false)
|
||||
: shouldSetAsProp(el, key, nextValue, isSVG)
|
||||
) {
|
||||
patchDOMProp(el, key, nextValue, parentComponent)
|
||||
const camelKey = camelize(key)
|
||||
const propKey = camelKey in el ? camelKey : key
|
||||
patchDOMProp(el, propKey, nextValue, parentComponent, key)
|
||||
// #6007 also set form state as attributes so they work with
|
||||
// <input type="reset"> or libs / extensions that expect attributes
|
||||
// #11163 custom elements may use value as an prop and set it as object
|
||||
|
@ -145,5 +147,5 @@ function shouldSetAsProp(
|
|||
return false
|
||||
}
|
||||
|
||||
return key in el
|
||||
return camelize(key) in el || key in el
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue