Merge remote-tracking branch 'github/master' into changing_unwrap_ref
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
import { patchAttr, xlinkNS } from '../../src/modules/attrs'
|
||||
|
||||
describe('attrs', () => {
|
||||
test('xlink attributes', () => {
|
||||
const el = document.createElementNS('http://www.w3.org/2000/svg', 'use')
|
||||
patchAttr(el, 'xlink:href', 'a', true)
|
||||
expect(el.getAttributeNS(xlinkNS, 'href')).toBe('a')
|
||||
patchAttr(el, 'xlink:href', null, true)
|
||||
expect(el.getAttributeNS(xlinkNS, 'href')).toBe(null)
|
||||
})
|
||||
|
||||
test('boolean attributes', () => {
|
||||
const el = document.createElement('input')
|
||||
patchAttr(el, 'readonly', true, false)
|
||||
expect(el.getAttribute('readonly')).toBe('')
|
||||
patchAttr(el, 'readonly', false, false)
|
||||
expect(el.getAttribute('readonly')).toBe(null)
|
||||
})
|
||||
|
||||
test('attributes', () => {
|
||||
const el = document.createElement('div')
|
||||
patchAttr(el, 'id', 'a', false)
|
||||
expect(el.getAttribute('id')).toBe('a')
|
||||
patchAttr(el, 'id', null, false)
|
||||
expect(el.getAttribute('id')).toBe(null)
|
||||
})
|
||||
})
|
||||
@@ -1,188 +0,0 @@
|
||||
// https://github.com/vuejs/vue/blob/dev/test/unit/features/directives/class.spec.js
|
||||
|
||||
import { h, render, defineComponent } from '../../src'
|
||||
|
||||
type ClassItem = {
|
||||
value: string | object | string[]
|
||||
}
|
||||
|
||||
function assertClass(assertions: Array<Array<any>>) {
|
||||
const root = document.createElement('div')
|
||||
const dynamic = { value: '' }
|
||||
const wrapper = () => h('div', { class: ['foo', dynamic.value] })
|
||||
|
||||
for (const [input, expected] of assertions) {
|
||||
if (typeof input === 'function') {
|
||||
input(dynamic.value)
|
||||
} else {
|
||||
dynamic.value = input
|
||||
}
|
||||
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe(expected)
|
||||
}
|
||||
}
|
||||
|
||||
describe('class', () => {
|
||||
test('plain string', () => {
|
||||
assertClass([
|
||||
['bar', 'foo bar'],
|
||||
['baz qux', 'foo baz qux'],
|
||||
['qux', 'foo qux'],
|
||||
[undefined, 'foo']
|
||||
])
|
||||
})
|
||||
|
||||
test('object value', () => {
|
||||
assertClass([
|
||||
[{ bar: true, baz: false }, 'foo bar'],
|
||||
[{ baz: true }, 'foo baz'],
|
||||
[null, 'foo'],
|
||||
[{ 'bar baz': true, qux: false }, 'foo bar baz'],
|
||||
[{ qux: true }, 'foo qux']
|
||||
])
|
||||
})
|
||||
|
||||
test('array value', () => {
|
||||
assertClass([
|
||||
[['bar', 'baz'], 'foo bar baz'],
|
||||
[['qux', 'baz'], 'foo qux baz'],
|
||||
[['w', 'x y z'], 'foo w x y z'],
|
||||
[undefined, 'foo'],
|
||||
[['bar'], 'foo bar'],
|
||||
[(val: Array<any>) => val.push('baz'), 'foo bar baz']
|
||||
])
|
||||
})
|
||||
|
||||
test('array of mixed values', () => {
|
||||
assertClass([
|
||||
[['x', { y: true, z: true }], 'foo x y z'],
|
||||
[['x', { y: true, z: false }], 'foo x y'],
|
||||
[['f', { z: true }], 'foo f z'],
|
||||
[['l', 'f', { n: true, z: true }], 'foo l f n z'],
|
||||
[['x', {}], 'foo x'],
|
||||
[undefined, 'foo']
|
||||
])
|
||||
})
|
||||
|
||||
test('class merge between parent and child', () => {
|
||||
const root = document.createElement('div')
|
||||
|
||||
const childClass: ClassItem = { value: 'd' }
|
||||
const child = {
|
||||
render: () => h('div', { class: ['c', childClass.value] })
|
||||
}
|
||||
|
||||
const parentClass: ClassItem = { value: 'b' }
|
||||
const parent = {
|
||||
render: () => h(child, { class: ['a', parentClass.value] })
|
||||
}
|
||||
|
||||
render(h(parent), root)
|
||||
expect(root.children[0].className).toBe('c d a b')
|
||||
|
||||
parentClass.value = 'e'
|
||||
// the `foo` here is just for forcing parent to be updated
|
||||
// (otherwise it's skipped since its props never change)
|
||||
render(h(parent, { foo: 1 }), root)
|
||||
expect(root.children[0].className).toBe('c d a e')
|
||||
|
||||
parentClass.value = 'f'
|
||||
render(h(parent, { foo: 2 }), root)
|
||||
expect(root.children[0].className).toBe('c d a f')
|
||||
|
||||
parentClass.value = { foo: true }
|
||||
childClass.value = ['bar', 'baz']
|
||||
render(h(parent, { foo: 3 }), root)
|
||||
expect(root.children[0].className).toBe('c bar baz a foo')
|
||||
})
|
||||
|
||||
test('class merge between multiple nested components sharing same element', () => {
|
||||
const component1 = defineComponent({
|
||||
render() {
|
||||
return this.$slots.default!()[0]
|
||||
}
|
||||
})
|
||||
|
||||
const component2 = defineComponent({
|
||||
render() {
|
||||
return this.$slots.default!()[0]
|
||||
}
|
||||
})
|
||||
|
||||
const component3 = defineComponent({
|
||||
render() {
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
class: 'staticClass'
|
||||
},
|
||||
[this.$slots.default!()]
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const root = document.createElement('div')
|
||||
const componentClass1 = { value: 'componentClass1' }
|
||||
const componentClass2 = { value: 'componentClass2' }
|
||||
const componentClass3 = { value: 'componentClass3' }
|
||||
|
||||
const wrapper = () =>
|
||||
h(component1, { class: componentClass1.value }, () => [
|
||||
h(component2, { class: componentClass2.value }, () => [
|
||||
h(component3, { class: componentClass3.value }, () => ['some text'])
|
||||
])
|
||||
])
|
||||
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe(
|
||||
'staticClass componentClass3 componentClass2 componentClass1'
|
||||
)
|
||||
|
||||
componentClass1.value = 'c1'
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe(
|
||||
'staticClass componentClass3 componentClass2 c1'
|
||||
)
|
||||
|
||||
componentClass2.value = 'c2'
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe('staticClass componentClass3 c2 c1')
|
||||
|
||||
componentClass3.value = 'c3'
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe('staticClass c3 c2 c1')
|
||||
})
|
||||
|
||||
test('deep update', () => {
|
||||
const root = document.createElement('div')
|
||||
const test = {
|
||||
a: true,
|
||||
b: false
|
||||
}
|
||||
|
||||
const wrapper = () => h('div', { class: test })
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe('a')
|
||||
|
||||
test.b = true
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].className).toBe('a b')
|
||||
})
|
||||
|
||||
// a vdom patch edge case where the user has several un-keyed elements of the
|
||||
// same tag next to each other, and toggling them.
|
||||
test('properly remove staticClass for toggling un-keyed children', () => {
|
||||
const root = document.createElement('div')
|
||||
const ok = { value: true }
|
||||
const wrapper = () =>
|
||||
h('div', [ok.value ? h('div', { class: 'a' }) : h('div')])
|
||||
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].children[0].className).toBe('a')
|
||||
|
||||
ok.value = false
|
||||
render(wrapper(), root)
|
||||
expect(root.children[0].children[0].className).toBe('')
|
||||
})
|
||||
})
|
||||
37
packages/runtime-dom/__tests__/patchAttrs.spec.ts
Normal file
37
packages/runtime-dom/__tests__/patchAttrs.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { patchProp } from '../src/patchProp'
|
||||
import { xlinkNS } from '../src/modules/attrs'
|
||||
|
||||
describe('runtime-dom: attrs patching', () => {
|
||||
test('xlink attributes', () => {
|
||||
const el = document.createElementNS('http://www.w3.org/2000/svg', 'use')
|
||||
patchProp(el, 'xlink:href', null, 'a', true)
|
||||
expect(el.getAttributeNS(xlinkNS, 'href')).toBe('a')
|
||||
patchProp(el, 'xlink:href', 'a', null, true)
|
||||
expect(el.getAttributeNS(xlinkNS, 'href')).toBe(null)
|
||||
})
|
||||
|
||||
test('boolean attributes', () => {
|
||||
const el = document.createElement('input')
|
||||
patchProp(el, 'readonly', null, true)
|
||||
expect(el.getAttribute('readonly')).toBe('')
|
||||
patchProp(el, 'readonly', true, false)
|
||||
expect(el.getAttribute('readonly')).toBe(null)
|
||||
})
|
||||
|
||||
test('attributes', () => {
|
||||
const el = document.createElement('div')
|
||||
patchProp(el, 'foo', null, 'a')
|
||||
expect(el.getAttribute('foo')).toBe('a')
|
||||
patchProp(el, 'foo', 'a', null)
|
||||
expect(el.getAttribute('foo')).toBe(null)
|
||||
})
|
||||
|
||||
// #949
|
||||
test('onxxx but non-listener attributes', () => {
|
||||
const el = document.createElement('div')
|
||||
patchProp(el, 'onwards', null, 'a')
|
||||
expect(el.getAttribute('onwards')).toBe('a')
|
||||
patchProp(el, 'onwards', 'a', null)
|
||||
expect(el.getAttribute('onwards')).toBe(null)
|
||||
})
|
||||
})
|
||||
31
packages/runtime-dom/__tests__/patchClass.spec.ts
Normal file
31
packages/runtime-dom/__tests__/patchClass.spec.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { patchProp } from '../src/patchProp'
|
||||
import { ElementWithTransition } from '../src/components/Transition'
|
||||
import { svgNS } from '../src/nodeOps'
|
||||
|
||||
describe('runtime-dom: class patching', () => {
|
||||
test('basics', () => {
|
||||
const el = document.createElement('div')
|
||||
patchProp(el, 'class', null, 'foo')
|
||||
expect(el.className).toBe('foo')
|
||||
patchProp(el, 'class', null, null)
|
||||
expect(el.className).toBe('')
|
||||
})
|
||||
|
||||
test('transition class', () => {
|
||||
const el = document.createElement('div') as ElementWithTransition
|
||||
el._vtc = new Set(['bar', 'baz'])
|
||||
patchProp(el, 'class', null, 'foo')
|
||||
expect(el.className).toBe('foo bar baz')
|
||||
patchProp(el, 'class', null, null)
|
||||
expect(el.className).toBe('bar baz')
|
||||
delete el._vtc
|
||||
patchProp(el, 'class', null, 'foo')
|
||||
expect(el.className).toBe('foo')
|
||||
})
|
||||
|
||||
test('svg', () => {
|
||||
const el = document.createElementNS(svgNS, 'svg')
|
||||
patchProp(el, 'class', null, 'foo', true)
|
||||
expect(el.getAttribute('class')).toBe('foo')
|
||||
})
|
||||
})
|
||||
@@ -1,13 +1,13 @@
|
||||
import { patchEvent } from '../../src/modules/events'
|
||||
import { patchProp } from '../src/patchProp'
|
||||
|
||||
const timeout = () => new Promise(r => setTimeout(r))
|
||||
|
||||
describe(`events`, () => {
|
||||
describe(`runtime-dom: events patching`, () => {
|
||||
it('should assign event handler', async () => {
|
||||
const el = document.createElement('div')
|
||||
const event = new Event('click')
|
||||
const fn = jest.fn()
|
||||
patchEvent(el, 'onClick', null, fn, null)
|
||||
patchProp(el, 'onClick', null, fn)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
el.dispatchEvent(event)
|
||||
@@ -22,9 +22,9 @@ describe(`events`, () => {
|
||||
const event = new Event('click')
|
||||
const prevFn = jest.fn()
|
||||
const nextFn = jest.fn()
|
||||
patchEvent(el, 'onClick', null, prevFn, null)
|
||||
patchProp(el, 'onClick', null, prevFn)
|
||||
el.dispatchEvent(event)
|
||||
patchEvent(el, 'onClick', prevFn, nextFn, null)
|
||||
patchProp(el, 'onClick', prevFn, nextFn)
|
||||
await timeout()
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
@@ -39,7 +39,7 @@ describe(`events`, () => {
|
||||
const event = new Event('click')
|
||||
const fn1 = jest.fn()
|
||||
const fn2 = jest.fn()
|
||||
patchEvent(el, 'onClick', null, [fn1, fn2], null)
|
||||
patchProp(el, 'onClick', null, [fn1, fn2])
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
expect(fn1).toHaveBeenCalledTimes(1)
|
||||
@@ -50,8 +50,8 @@ describe(`events`, () => {
|
||||
const el = document.createElement('div')
|
||||
const event = new Event('click')
|
||||
const fn = jest.fn()
|
||||
patchEvent(el, 'onClick', null, fn, null)
|
||||
patchEvent(el, 'onClick', fn, null, null)
|
||||
patchProp(el, 'onClick', null, fn)
|
||||
patchProp(el, 'onClick', fn, null)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
expect(fn).not.toHaveBeenCalled()
|
||||
@@ -67,7 +67,7 @@ describe(`events`, () => {
|
||||
once: true
|
||||
}
|
||||
}
|
||||
patchEvent(el, 'onClick', null, nextValue, null)
|
||||
patchProp(el, 'onClick', null, nextValue)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
el.dispatchEvent(event)
|
||||
@@ -86,8 +86,8 @@ describe(`events`, () => {
|
||||
once: true
|
||||
}
|
||||
}
|
||||
patchEvent(el, 'onClick', null, prevFn, null)
|
||||
patchEvent(el, 'onClick', prevFn, nextValue, null)
|
||||
patchProp(el, 'onClick', null, prevFn)
|
||||
patchProp(el, 'onClick', prevFn, nextValue)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
el.dispatchEvent(event)
|
||||
@@ -106,8 +106,8 @@ describe(`events`, () => {
|
||||
once: true
|
||||
}
|
||||
}
|
||||
patchEvent(el, 'onClick', null, nextValue, null)
|
||||
patchEvent(el, 'onClick', nextValue, null, null)
|
||||
patchProp(el, 'onClick', null, nextValue)
|
||||
patchProp(el, 'onClick', nextValue, null)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
el.dispatchEvent(event)
|
||||
@@ -115,21 +115,23 @@ describe(`events`, () => {
|
||||
expect(fn).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should assign native onclick attribute', async () => {
|
||||
it('should support native onclick', async () => {
|
||||
const el = document.createElement('div')
|
||||
const event = new Event('click')
|
||||
const fn = ((window as any)._nativeClickSpy = jest.fn())
|
||||
|
||||
patchEvent(el, 'onclick', null, '_nativeClickSpy()' as any)
|
||||
// string should be set as attribute
|
||||
const fn = ((window as any).__globalSpy = jest.fn())
|
||||
patchProp(el, 'onclick', null, '__globalSpy(1)')
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
expect(fn).toHaveBeenCalledTimes(1)
|
||||
delete (window as any).__globalSpy
|
||||
expect(fn).toHaveBeenCalledWith(1)
|
||||
|
||||
const fn2 = jest.fn()
|
||||
patchEvent(el, 'onclick', null, fn2)
|
||||
patchProp(el, 'onclick', '__globalSpy(1)', fn2)
|
||||
el.dispatchEvent(event)
|
||||
await timeout()
|
||||
expect(fn).toHaveBeenCalledTimes(1)
|
||||
expect(fn2).toHaveBeenCalledTimes(1)
|
||||
expect(fn2).toHaveBeenCalledWith(event)
|
||||
})
|
||||
})
|
||||
78
packages/runtime-dom/__tests__/patchProps.spec.ts
Normal file
78
packages/runtime-dom/__tests__/patchProps.spec.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { patchProp } from '../src/patchProp'
|
||||
import { render, h } from '../src'
|
||||
|
||||
describe('runtime-dom: props patching', () => {
|
||||
test('basic', () => {
|
||||
const el = document.createElement('div')
|
||||
patchProp(el, 'id', null, 'foo')
|
||||
expect(el.id).toBe('foo')
|
||||
patchProp(el, 'id', null, null)
|
||||
expect(el.id).toBe('')
|
||||
})
|
||||
|
||||
test('value', () => {
|
||||
const el = document.createElement('input')
|
||||
patchProp(el, 'value', null, 'foo')
|
||||
expect(el.value).toBe('foo')
|
||||
patchProp(el, 'value', null, null)
|
||||
expect(el.value).toBe('')
|
||||
const obj = {}
|
||||
patchProp(el, 'value', null, obj)
|
||||
expect(el.value).toBe(obj.toString())
|
||||
expect((el as any)._value).toBe(obj)
|
||||
})
|
||||
|
||||
test('boolean prop', () => {
|
||||
const el = document.createElement('select')
|
||||
patchProp(el, 'multiple', null, '')
|
||||
expect(el.multiple).toBe(true)
|
||||
patchProp(el, 'multiple', null, null)
|
||||
expect(el.multiple).toBe(false)
|
||||
})
|
||||
|
||||
test('innerHTML unmount prev children', () => {
|
||||
const fn = jest.fn()
|
||||
const comp = {
|
||||
render: () => 'foo',
|
||||
unmounted: fn
|
||||
}
|
||||
const root = document.createElement('div')
|
||||
render(h('div', null, [h(comp)]), root)
|
||||
expect(root.innerHTML).toBe(`<div>foo</div>`)
|
||||
|
||||
render(h('div', { innerHTML: 'bar' }), root)
|
||||
expect(root.innerHTML).toBe(`<div>bar</div>`)
|
||||
expect(fn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// #954
|
||||
test('(svg) innerHTML unmount prev children', () => {
|
||||
const fn = jest.fn()
|
||||
const comp = {
|
||||
render: () => 'foo',
|
||||
unmounted: fn
|
||||
}
|
||||
const root = document.createElement('div')
|
||||
render(h('div', null, [h(comp)]), root)
|
||||
expect(root.innerHTML).toBe(`<div>foo</div>`)
|
||||
|
||||
render(h('svg', { innerHTML: '<g></g>' }), root)
|
||||
expect(root.innerHTML).toBe(`<svg><g></g></svg>`)
|
||||
expect(fn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test('textContent unmount prev children', () => {
|
||||
const fn = jest.fn()
|
||||
const comp = {
|
||||
render: () => 'foo',
|
||||
unmounted: fn
|
||||
}
|
||||
const root = document.createElement('div')
|
||||
render(h('div', null, [h(comp)]), root)
|
||||
expect(root.innerHTML).toBe(`<div>foo</div>`)
|
||||
|
||||
render(h('div', { textContent: 'bar' }), root)
|
||||
expect(root.innerHTML).toBe(`<div>bar</div>`)
|
||||
expect(fn).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -1,39 +1,39 @@
|
||||
import { patchStyle } from '../../src/modules/style'
|
||||
import { patchProp } from '../src/patchProp'
|
||||
|
||||
describe(`module style`, () => {
|
||||
describe(`runtime-dom: style patching`, () => {
|
||||
it('string', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, 'color:red')
|
||||
patchProp(el, 'style', {}, 'color:red')
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
|
||||
})
|
||||
|
||||
it('plain object', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, { color: 'red' })
|
||||
patchProp(el, 'style', {}, { color: 'red' })
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red;')
|
||||
})
|
||||
|
||||
it('camelCase', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, { marginRight: '10px' })
|
||||
patchProp(el, 'style', {}, { marginRight: '10px' })
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe('margin-right:10px;')
|
||||
})
|
||||
|
||||
it('remove if falsy value', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, { color: 'red' }, { color: undefined })
|
||||
patchProp(el, 'style', { color: 'red' }, { color: undefined })
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe('')
|
||||
})
|
||||
|
||||
it('!important', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, { color: 'red !important' })
|
||||
patchProp(el, 'style', {}, { color: 'red !important' })
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe('color:red!important;')
|
||||
})
|
||||
|
||||
it('camelCase with !important', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, { marginRight: '10px !important' })
|
||||
patchProp(el, 'style', {}, { marginRight: '10px !important' })
|
||||
expect(el.style.cssText.replace(/\s/g, '')).toBe(
|
||||
'margin-right:10px!important;'
|
||||
)
|
||||
@@ -41,7 +41,7 @@ describe(`module style`, () => {
|
||||
|
||||
it('object with multiple entries', () => {
|
||||
const el = document.createElement('div')
|
||||
patchStyle(el, {}, { color: 'red', marginRight: '10px' })
|
||||
patchProp(el, 'style', {}, { color: 'red', marginRight: '10px' })
|
||||
expect(el.style.getPropertyValue('color')).toBe('red')
|
||||
expect(el.style.getPropertyValue('margin-right')).toBe('10px')
|
||||
})
|
||||
@@ -65,13 +65,13 @@ describe(`module style`, () => {
|
||||
|
||||
it('CSS custom properties', () => {
|
||||
const el = mockElementWithStyle()
|
||||
patchStyle(el as any, {}, { '--theme': 'red' } as any)
|
||||
patchProp(el as any, 'style', {}, { '--theme': 'red' } as any)
|
||||
expect(el.style.getPropertyValue('--theme')).toBe('red')
|
||||
})
|
||||
|
||||
it('auto vendor prefixing', () => {
|
||||
const el = mockElementWithStyle()
|
||||
patchStyle(el as any, {}, { transition: 'all 1s' })
|
||||
patchProp(el as any, 'style', {}, { transition: 'all 1s' })
|
||||
expect(el.style.WebkitTransition).toBe('all 1s')
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vue/runtime-dom",
|
||||
"version": "3.0.0-alpha.11",
|
||||
"version": "3.0.0-alpha.12",
|
||||
"description": "@vue/runtime-dom",
|
||||
"main": "index.js",
|
||||
"module": "dist/runtime-dom.esm-bundler.js",
|
||||
@@ -37,8 +37,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/runtime-dom#readme",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.0.0-alpha.11",
|
||||
"@vue/runtime-core": "3.0.0-alpha.11",
|
||||
"@vue/shared": "3.0.0-alpha.12",
|
||||
"@vue/runtime-core": "3.0.0-alpha.12",
|
||||
"csstype": "^2.6.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,15 +6,18 @@ export function patchClass(el: Element, value: string | null, isSVG: boolean) {
|
||||
if (value == null) {
|
||||
value = ''
|
||||
}
|
||||
// directly setting className should be faster than setAttribute in theory
|
||||
if (isSVG) {
|
||||
el.setAttribute('class', value)
|
||||
} else {
|
||||
// directly setting className should be faster than setAttribute in theory
|
||||
// if this is an element during a transition, take the temporary transition
|
||||
// classes into account.
|
||||
const transitionClasses = (el as ElementWithTransition)._vtc
|
||||
if (transitionClasses) {
|
||||
value = [value, ...transitionClasses].join(' ')
|
||||
value = (value
|
||||
? [value, ...transitionClasses]
|
||||
: [...transitionClasses]
|
||||
).join(' ')
|
||||
}
|
||||
el.className = value
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { EMPTY_OBJ, isString } from '@vue/shared'
|
||||
import { EMPTY_OBJ } from '@vue/shared'
|
||||
import {
|
||||
ComponentInternalInstance,
|
||||
callWithAsyncErrorHandling
|
||||
@@ -71,16 +71,6 @@ export function patchEvent(
|
||||
nextValue: EventValueWithOptions | EventValue | null,
|
||||
instance: ComponentInternalInstance | null = null
|
||||
) {
|
||||
// support native onxxx handlers
|
||||
if (rawName in el) {
|
||||
if (isString(nextValue)) {
|
||||
el.setAttribute(rawName, nextValue)
|
||||
} else {
|
||||
;(el as any)[rawName] = nextValue
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const name = rawName.slice(2).toLowerCase()
|
||||
const prevOptions = prevValue && 'options' in prevValue && prevValue.options
|
||||
const nextOptions = nextValue && 'options' in nextValue && nextValue.options
|
||||
|
||||
@@ -14,8 +14,10 @@ export function patchDOMProp(
|
||||
parentSuspense: any,
|
||||
unmountChildren: any
|
||||
) {
|
||||
if ((key === 'innerHTML' || key === 'textContent') && prevChildren) {
|
||||
unmountChildren(prevChildren, parentComponent, parentSuspense)
|
||||
if (key === 'innerHTML' || key === 'textContent') {
|
||||
if (prevChildren) {
|
||||
unmountChildren(prevChildren, parentComponent, parentSuspense)
|
||||
}
|
||||
el[key] = value == null ? '' : value
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { RendererOptions } from '@vue/runtime-core'
|
||||
|
||||
export const svgNS = 'http://www.w3.org/2000/svg'
|
||||
|
||||
const doc = (typeof document !== 'undefined' ? document : null) as Document
|
||||
const svgNS = 'http://www.w3.org/2000/svg'
|
||||
|
||||
let tempContainer: HTMLElement
|
||||
let tempSVGContainer: SVGElement
|
||||
|
||||
@@ -3,9 +3,11 @@ import { patchStyle } from './modules/style'
|
||||
import { patchAttr } from './modules/attrs'
|
||||
import { patchDOMProp } from './modules/props'
|
||||
import { patchEvent } from './modules/events'
|
||||
import { isOn } from '@vue/shared'
|
||||
import { isOn, isString, isFunction } from '@vue/shared'
|
||||
import { RendererOptions } from '@vue/runtime-core'
|
||||
|
||||
const nativeOnRE = /^on[a-z]/
|
||||
|
||||
export const patchProp: RendererOptions<Node, Element>['patchProp'] = (
|
||||
el,
|
||||
key,
|
||||
@@ -31,7 +33,18 @@ export const patchProp: RendererOptions<Node, Element>['patchProp'] = (
|
||||
if (key.indexOf('onUpdate:') < 0) {
|
||||
patchEvent(el, key, prevValue, nextValue, parentComponent)
|
||||
}
|
||||
} else if (!isSVG && key in el) {
|
||||
} else if (
|
||||
isSVG
|
||||
? // most keys must be set as attribute on svg elements to work
|
||||
// ...except innerHTML
|
||||
key === 'innerHTML' ||
|
||||
// or native onclick with function values
|
||||
(key in el && nativeOnRE.test(key) && isFunction(nextValue))
|
||||
: // for normal html elements, set as a property if it exists
|
||||
key in el &&
|
||||
// except native onclick with string values
|
||||
!(nativeOnRE.test(key) && isString(nextValue))
|
||||
) {
|
||||
patchDOMProp(
|
||||
el,
|
||||
key,
|
||||
|
||||
Reference in New Issue
Block a user