mirror of
https://gitee.com/vuejs/vue.git
synced 2024-12-02 03:57:36 +08:00
parent
daed1e7355
commit
df82aeb0bf
@ -103,7 +103,23 @@ export function createPatchFunction (backend) {
|
||||
}
|
||||
}
|
||||
|
||||
let inPre = 0
|
||||
function isUnknownElement (vnode, inVPre) {
|
||||
return (
|
||||
!inVPre &&
|
||||
!vnode.ns &&
|
||||
!(
|
||||
config.ignoredElements.length &&
|
||||
config.ignoredElements.some(ignore => {
|
||||
return isRegExp(ignore)
|
||||
? ignore.test(vnode.tag)
|
||||
: ignore === vnode.tag
|
||||
})
|
||||
) &&
|
||||
config.isUnknownElement(vnode.tag)
|
||||
)
|
||||
}
|
||||
|
||||
let creatingElmInVPre = 0
|
||||
function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
|
||||
vnode.isRootInsert = !nested // for transition enter check
|
||||
if (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
|
||||
@ -116,21 +132,9 @@ export function createPatchFunction (backend) {
|
||||
if (isDef(tag)) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (data && data.pre) {
|
||||
inPre++
|
||||
creatingElmInVPre++
|
||||
}
|
||||
if (
|
||||
!inPre &&
|
||||
!vnode.ns &&
|
||||
!(
|
||||
config.ignoredElements.length &&
|
||||
config.ignoredElements.some(ignore => {
|
||||
return isRegExp(ignore)
|
||||
? ignore.test(tag)
|
||||
: ignore === tag
|
||||
})
|
||||
) &&
|
||||
config.isUnknownElement(tag)
|
||||
) {
|
||||
if (isUnknownElement(vnode, creatingElmInVPre)) {
|
||||
warn(
|
||||
'Unknown custom element: <' + tag + '> - did you ' +
|
||||
'register the component correctly? For recursive components, ' +
|
||||
@ -172,7 +176,7 @@ export function createPatchFunction (backend) {
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production' && data && data.pre) {
|
||||
inPre--
|
||||
creatingElmInVPre--
|
||||
}
|
||||
} else if (isTrue(vnode.isComment)) {
|
||||
vnode.elm = nodeOps.createComment(vnode.text)
|
||||
@ -527,25 +531,28 @@ export function createPatchFunction (backend) {
|
||||
}
|
||||
}
|
||||
|
||||
let bailed = false
|
||||
let hydrationBailed = false
|
||||
// list of modules that can skip create hook during hydration because they
|
||||
// are already rendered on the client or has no need for initialization
|
||||
const isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key')
|
||||
|
||||
// Note: this is a browser-only function so we can assume elms are DOM nodes.
|
||||
function hydrate (elm, vnode, insertedVnodeQueue) {
|
||||
function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
|
||||
let i
|
||||
const { tag, data, children } = vnode
|
||||
inVPre = inVPre || (data && data.pre)
|
||||
vnode.elm = elm
|
||||
|
||||
if (isTrue(vnode.isComment) && isDef(vnode.asyncFactory)) {
|
||||
vnode.elm = elm
|
||||
vnode.isAsyncPlaceholder = true
|
||||
return true
|
||||
}
|
||||
// assert node match
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!assertNodeMatch(elm, vnode)) {
|
||||
if (!assertNodeMatch(elm, vnode, inVPre)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
vnode.elm = elm
|
||||
const { tag, data, children } = vnode
|
||||
if (isDef(data)) {
|
||||
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode, true /* hydrating */)
|
||||
if (isDef(i = vnode.componentInstance)) {
|
||||
@ -566,9 +573,9 @@ export function createPatchFunction (backend) {
|
||||
/* istanbul ignore if */
|
||||
if (process.env.NODE_ENV !== 'production' &&
|
||||
typeof console !== 'undefined' &&
|
||||
!bailed
|
||||
!hydrationBailed
|
||||
) {
|
||||
bailed = true
|
||||
hydrationBailed = true
|
||||
console.warn('Parent: ', elm)
|
||||
console.warn('server innerHTML: ', i)
|
||||
console.warn('client innerHTML: ', elm.innerHTML)
|
||||
@ -580,7 +587,7 @@ export function createPatchFunction (backend) {
|
||||
let childrenMatch = true
|
||||
let childNode = elm.firstChild
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {
|
||||
if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue, inVPre)) {
|
||||
childrenMatch = false
|
||||
break
|
||||
}
|
||||
@ -592,9 +599,9 @@ export function createPatchFunction (backend) {
|
||||
/* istanbul ignore if */
|
||||
if (process.env.NODE_ENV !== 'production' &&
|
||||
typeof console !== 'undefined' &&
|
||||
!bailed
|
||||
!hydrationBailed
|
||||
) {
|
||||
bailed = true
|
||||
hydrationBailed = true
|
||||
console.warn('Parent: ', elm)
|
||||
console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
|
||||
}
|
||||
@ -617,10 +624,10 @@ export function createPatchFunction (backend) {
|
||||
return true
|
||||
}
|
||||
|
||||
function assertNodeMatch (node, vnode) {
|
||||
function assertNodeMatch (node, vnode, inVPre) {
|
||||
if (isDef(vnode.tag)) {
|
||||
return (
|
||||
vnode.tag.indexOf('vue-component') === 0 ||
|
||||
return vnode.tag.indexOf('vue-component') === 0 || (
|
||||
!isUnknownElement(vnode, inVPre) &&
|
||||
vnode.tag.toLowerCase() === (node.tagName && node.tagName.toLowerCase())
|
||||
)
|
||||
} else {
|
||||
|
@ -150,6 +150,17 @@ describe('vdom patch: hydration', () => {
|
||||
expect('not matching server-rendered content').toHaveBeenWarned()
|
||||
})
|
||||
|
||||
it('should warn failed hydration when component is not properly registered', () => {
|
||||
const dom = createMockSSRDOM('<div><foo></foo></div>')
|
||||
|
||||
new Vue({
|
||||
template: '<div><foo></foo></div>'
|
||||
}).$mount(dom)
|
||||
|
||||
expect('not matching server-rendered content').toHaveBeenWarned()
|
||||
expect('Unknown custom element: <foo>').toHaveBeenWarned()
|
||||
})
|
||||
|
||||
it('should overwrite textNodes in the correct position but with mismatching text without warning', () => {
|
||||
const dom = createMockSSRDOM('<div><span>foo</span></div>')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user