Skip to content

Commit 9dce7ad

Browse files
committed
Streaming render for weex
fix append mode for keep-alive reactivation streaming render for weex fix weex test case inject __WEEX__ during tests fix append:tree for iOS ignore weex branch
1 parent 68e560a commit 9dce7ad

File tree

12 files changed

+122
-45
lines changed

12 files changed

+122
-45
lines changed

.eslintrc

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"parser": "babel-eslint",
44
"extends": "vue",
55
"plugins": ["flowtype"],
6+
"globals": {
7+
"__WEEX__": true
8+
},
69
"rules": {
710
"no-useless-escape": 0,
811
"flowtype/define-flow-type": 1,

build/config.js

+5
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,14 @@ const builds = {
7878
},
7979
// Weex runtime framework (CommonJS).
8080
'weex-framework': {
81+
weex: true,
8182
entry: path.resolve(__dirname, '../src/entries/weex-framework.js'),
8283
dest: path.resolve(__dirname, '../packages/weex-vue-framework/index.js'),
8384
format: 'cjs'
8485
},
8586
// Weex compiler (CommonJS). Used by Weex's Webpack loader.
8687
'weex-compiler': {
88+
weex: true,
8789
entry: path.resolve(__dirname, '../src/entries/weex-compiler.js'),
8890
dest: path.resolve(__dirname, '../packages/weex-template-compiler/build.js'),
8991
format: 'cjs',
@@ -100,6 +102,9 @@ function genConfig (opts) {
100102
banner: opts.banner,
101103
moduleName: 'Vue',
102104
plugins: [
105+
replace({
106+
__WEEX__: !!opts.weex
107+
}),
103108
flow(),
104109
buble(),
105110
alias(Object.assign({}, require('./alias'), opts.alias))

build/karma.base.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ var webpackConfig = {
1616
},
1717
plugins: [
1818
new webpack.DefinePlugin({
19+
__WEEX__: false,
1920
'process.env': {
2021
NODE_ENV: '"development"',
2122
TRANSITION_DURATION: process.env.SAUCE ? 200 : 50,

flow/compiler.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ declare type ASTElement = {
125125
wrapData?: (code: string) => string;
126126

127127
// weex specific
128-
atom?: boolean;
128+
appendAsTree?: boolean;
129129
}
130130

131131
declare type ASTExpression = {

flow/options.js

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ declare type InternalComponentOptions = {
66
_parentListeners: ?Object;
77
_renderChildren: ?VNodeChildren;
88
_componentTag: ?string;
9+
_parentElm: ?Node;
10+
_refElm: ?Node;
911
render?: Function;
1012
staticRenderFns?: Array<Function>
1113
}
@@ -61,6 +63,8 @@ declare type ComponentOptions = {
6163
_componentTag: ?string;
6264
_scopeId: ?string;
6365
_base: Class<Component>;
66+
_parentElm: ?Node;
67+
_refElm: ?Node;
6468
}
6569

6670
declare type PropOptions = {

src/core/instance/init.js

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ function initInternalComponent (vm: Component, options: InternalComponentOptions
5555
opts._parentListeners = options._parentListeners
5656
opts._renderChildren = options._renderChildren
5757
opts._componentTag = options._componentTag
58+
opts._parentElm = options._parentElm
59+
opts._refElm = options._refElm
5860
if (options.render) {
5961
opts.render = options.render
6062
opts.staticRenderFns = options.staticRenderFns

src/core/instance/lifecycle.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,21 @@ export function lifecycleMixin (Vue: Class<Component>) {
7979
callHook(vm, 'beforeUpdate')
8080
}
8181
const prevEl = vm.$el
82+
const prevVnode = vm._vnode
8283
const prevActiveInstance = activeInstance
8384
activeInstance = vm
84-
const prevVnode = vm._vnode
8585
vm._vnode = vnode
86+
// Vue.prototype.__patch__ is injected in entry points
87+
// based on the rendering backend used.
8688
if (!prevVnode) {
87-
// Vue.prototype.__patch__ is injected in entry points
88-
// based on the rendering backend used.
89-
vm.$el = vm.__patch__(vm.$el, vnode, hydrating)
89+
// initial render
90+
vm.$el = vm.__patch__(
91+
vm.$el, vnode, hydrating, false /* removeOnly */,
92+
vm.$options._parentElm,
93+
vm.$options._refElm
94+
)
9095
} else {
96+
// updates
9197
vm.$el = vm.__patch__(prevVnode, vnode)
9298
}
9399
activeInstance = prevActiveInstance

src/core/vdom/create-component.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ function createFunctionalComponent (
129129

130130
export function createComponentInstanceForVnode (
131131
vnode: any, // we know it's MountedComponentVNode but flow doesn't
132-
parent: any // activeInstance in lifecycle state
132+
parent: any, // activeInstance in lifecycle state
133+
parentElm?: ?Node,
134+
refElm?: ?Node
133135
): Component {
134136
const vnodeComponentOptions = vnode.componentOptions
135137
const options: InternalComponentOptions = {
@@ -139,7 +141,9 @@ export function createComponentInstanceForVnode (
139141
_componentTag: vnodeComponentOptions.tag,
140142
_parentVnode: vnode,
141143
_parentListeners: vnodeComponentOptions.listeners,
142-
_renderChildren: vnodeComponentOptions.children
144+
_renderChildren: vnodeComponentOptions.children,
145+
_parentElm: parentElm || null,
146+
_refElm: refElm || null
143147
}
144148
// check inline-template render functions
145149
const inlineTemplate = vnode.data.inlineTemplate
@@ -150,14 +154,25 @@ export function createComponentInstanceForVnode (
150154
return new vnodeComponentOptions.Ctor(options)
151155
}
152156

153-
function init (vnode: VNodeWithData, hydrating: boolean) {
157+
function init (
158+
vnode: VNodeWithData,
159+
hydrating: boolean,
160+
parentElm: ?Node,
161+
refElm: ?Node
162+
): ?boolean {
154163
if (!vnode.child || vnode.child._isDestroyed) {
155-
const child = vnode.child = createComponentInstanceForVnode(vnode, activeInstance)
164+
const child = vnode.child = createComponentInstanceForVnode(
165+
vnode,
166+
activeInstance,
167+
parentElm,
168+
refElm
169+
)
156170
child.$mount(hydrating ? vnode.elm : undefined, hydrating)
157171
} else if (vnode.data.keepAlive) {
158172
// kept-alive components, treat as a patch
159173
const mountedNode: any = vnode // work around flow
160174
prepatch(mountedNode, mountedNode)
175+
return true // let the patcher know this is a reactivated component
161176
}
162177
}
163178

src/core/vdom/patch.js

+63-24
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,26 @@ export function createPatchFunction (backend) {
8585
}
8686

8787
let inPre = 0
88-
function createElm (vnode, insertedVnodeQueue, nested) {
89-
let i
88+
function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
89+
let i, isReactivated
9090
const data = vnode.data
9191
vnode.isRootInsert = !nested
9292
if (isDef(data)) {
93-
if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode)
93+
if (isDef(i = data.hook) && isDef(i = i.init)) {
94+
isReactivated = i(vnode, false /* hydrating */, parentElm, refElm)
95+
}
9496
// after calling the init hook, if the vnode is a child component
9597
// it should've created a child instance and mounted it. the child
9698
// component also has set the placeholder vnode's elm.
9799
// in that case we can just return the element and be done.
98100
if (isDef(i = vnode.child)) {
99101
initComponent(vnode, insertedVnodeQueue)
100-
return vnode.elm
102+
if (isReactivated) {
103+
// unlike a newly created component,
104+
// a reactivated keep-alive component doesn't insert itself
105+
insert(parentElm, vnode.child.$el, refElm)
106+
}
107+
return
101108
}
102109
}
103110
const children = vnode.children
@@ -125,25 +132,56 @@ export function createPatchFunction (backend) {
125132
? nodeOps.createElementNS(vnode.ns, tag)
126133
: nodeOps.createElement(tag, vnode)
127134
setScope(vnode)
128-
createChildren(vnode, children, insertedVnodeQueue)
129-
if (isDef(data)) {
130-
invokeCreateHooks(vnode, insertedVnodeQueue)
135+
136+
/* istanbul ignore if */
137+
if (__WEEX__) {
138+
// in Weex, the default insertion order is parent-first.
139+
// List items can be optimized to use children-first insertion
140+
// with append="tree".
141+
const appendAsTree = data && data.appendAsTree
142+
if (!appendAsTree) {
143+
if (isDef(data)) {
144+
invokeCreateHooks(vnode, insertedVnodeQueue)
145+
}
146+
insert(parentElm, vnode.elm, refElm)
147+
}
148+
createChildren(vnode, children, insertedVnodeQueue)
149+
if (appendAsTree) {
150+
if (isDef(data)) {
151+
invokeCreateHooks(vnode, insertedVnodeQueue)
152+
}
153+
insert(parentElm, vnode.elm, refElm)
154+
}
155+
} else {
156+
createChildren(vnode, children, insertedVnodeQueue)
157+
if (isDef(data)) {
158+
invokeCreateHooks(vnode, insertedVnodeQueue)
159+
}
160+
insert(parentElm, vnode.elm, refElm)
131161
}
162+
132163
if (process.env.NODE_ENV !== 'production' && data && data.pre) {
133164
inPre--
134165
}
135166
} else if (vnode.isComment) {
136167
vnode.elm = nodeOps.createComment(vnode.text)
168+
insert(parentElm, vnode.elm, refElm)
137169
} else {
138170
vnode.elm = nodeOps.createTextNode(vnode.text)
171+
insert(parentElm, vnode.elm, refElm)
172+
}
173+
}
174+
175+
function insert (parent, elm, ref) {
176+
if (parent) {
177+
nodeOps.insertBefore(parent, elm, ref)
139178
}
140-
return vnode.elm
141179
}
142180

143181
function createChildren (vnode, children, insertedVnodeQueue) {
144182
if (Array.isArray(children)) {
145183
for (let i = 0; i < children.length; ++i) {
146-
nodeOps.appendChild(vnode.elm, createElm(children[i], insertedVnodeQueue, true))
184+
createElm(children[i], insertedVnodeQueue, vnode.elm, null, true)
147185
}
148186
} else if (isPrimitive(vnode.text)) {
149187
nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text))
@@ -200,9 +238,9 @@ export function createPatchFunction (backend) {
200238
}
201239
}
202240

203-
function addVnodes (parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
241+
function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
204242
for (; startIdx <= endIdx; ++startIdx) {
205-
nodeOps.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before)
243+
createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm)
206244
}
207245
}
208246

@@ -271,7 +309,7 @@ export function createPatchFunction (backend) {
271309
let newEndIdx = newCh.length - 1
272310
let newStartVnode = newCh[0]
273311
let newEndVnode = newCh[newEndIdx]
274-
let oldKeyToIdx, idxInOld, elmToMove, before
312+
let oldKeyToIdx, idxInOld, elmToMove, refElm
275313

276314
// removeOnly is a special flag used only by <transition-group>
277315
// to ensure removed elements stay in correct relative positions
@@ -305,7 +343,7 @@ export function createPatchFunction (backend) {
305343
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
306344
idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null
307345
if (isUndef(idxInOld)) { // New element
308-
nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
346+
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
309347
newStartVnode = newCh[++newStartIdx]
310348
} else {
311349
elmToMove = oldCh[idxInOld]
@@ -318,7 +356,7 @@ export function createPatchFunction (backend) {
318356
}
319357
if (elmToMove.tag !== newStartVnode.tag) {
320358
// same key but different element. treat as new element
321-
nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
359+
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
322360
newStartVnode = newCh[++newStartIdx]
323361
} else {
324362
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)
@@ -330,8 +368,8 @@ export function createPatchFunction (backend) {
330368
}
331369
}
332370
if (oldStartIdx > oldEndIdx) {
333-
before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
334-
addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
371+
refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
372+
addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
335373
} else if (newStartIdx > newEndIdx) {
336374
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
337375
}
@@ -462,7 +500,7 @@ export function createPatchFunction (backend) {
462500
}
463501
}
464502

465-
return function patch (oldVnode, vnode, hydrating, removeOnly) {
503+
return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
466504
if (!vnode) {
467505
if (oldVnode) invokeDestroyHook(oldVnode)
468506
return
@@ -473,12 +511,13 @@ export function createPatchFunction (backend) {
473511
const insertedVnodeQueue = []
474512

475513
if (!oldVnode) {
476-
// empty mount, create new root element
514+
// empty mount (likely as component), create new root element
477515
isInitialPatch = true
478-
createElm(vnode, insertedVnodeQueue)
516+
createElm(vnode, insertedVnodeQueue, parentElm, refElm)
479517
} else {
480518
const isRealElement = isDef(oldVnode.nodeType)
481519
if (!isRealElement && sameVnode(oldVnode, vnode)) {
520+
// patch existing root node
482521
patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
483522
} else {
484523
if (isRealElement) {
@@ -507,14 +546,15 @@ export function createPatchFunction (backend) {
507546
// create an empty node and replace it
508547
oldVnode = emptyNodeAt(oldVnode)
509548
}
549+
550+
// replacing existing element
510551
elm = oldVnode.elm
511552
parent = nodeOps.parentNode(elm)
553+
createElm(vnode, insertedVnodeQueue, parent, nodeOps.nextSibling(elm))
512554

513-
createElm(vnode, insertedVnodeQueue)
514-
515-
// component root element replaced.
516-
// update parent placeholder node element, recursively
517555
if (vnode.parent) {
556+
// component root element replaced.
557+
// update parent placeholder node element, recursively
518558
let ancestor = vnode.parent
519559
while (ancestor) {
520560
ancestor.elm = vnode.elm
@@ -528,7 +568,6 @@ export function createPatchFunction (backend) {
528568
}
529569

530570
if (parent !== null) {
531-
nodeOps.insertBefore(parent, vnode.elm, nodeOps.nextSibling(elm))
532571
removeVnodes(parent, [oldVnode], 0, 0)
533572
} else if (isDef(oldVnode.tag)) {
534573
invokeDestroyHook(oldVnode)
+6-11
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
/* @flow */
22

3-
import {
4-
getAndRemoveAttr
5-
} from 'compiler/helpers'
6-
7-
function parse (el: ASTElement, options: CompilerOptions) {
8-
const staticStyle = getAndRemoveAttr(el, 'append')
9-
if (staticStyle === 'tree') {
10-
el.atom = true
3+
function transformNode (el: ASTElement, options: CompilerOptions) {
4+
if (el.attrsMap.append === 'tree') {
5+
el.appendAsTree = true
116
}
127
}
138

149
function genData (el: ASTElement): string {
15-
return el.atom ? `atom:true,` : ''
10+
return el.appendAsTree ? `appendAsTree:true,` : ''
1611
}
1712

1813
export default {
19-
staticKeys: ['atom'],
20-
parse,
14+
staticKeys: ['appendAsTree'],
15+
transformNode,
2116
genData
2217
}

src/platforms/weex/runtime/node-ops.js

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ export function createComment (text) {
1919
}
2020

2121
export function insertBefore (node, target, before) {
22+
if (!before) {
23+
return appendChild(node, target)
24+
}
2225
if (target.nodeType === 3) {
2326
if (node.type === 'text') {
2427
node.setAttr('value', target.text)

src/platforms/weex/runtime/patch.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ import platformModules from 'weex/runtime/modules/index'
99
// built-in modules have been applied.
1010
const modules = platformModules.concat(baseModules)
1111

12-
export const patch: Function = createPatchFunction({ nodeOps, modules })
12+
export const patch: Function = createPatchFunction({
13+
nodeOps,
14+
modules,
15+
LONG_LIST_THRESHOLD: 10
16+
})

0 commit comments

Comments
 (0)