Permalink
Browse files

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
  • Loading branch information...
1 parent 68e560a commit 9dce7adfa252eaf76468bbb5ed660675f7ef4e7b @yyx990803 yyx990803 committed Nov 25, 2016
View
@@ -3,6 +3,9 @@
"parser": "babel-eslint",
"extends": "vue",
"plugins": ["flowtype"],
+ "globals": {
+ "__WEEX__": true
+ },
"rules": {
"no-useless-escape": 0,
"flowtype/define-flow-type": 1,
View
@@ -78,12 +78,14 @@ const builds = {
},
// Weex runtime framework (CommonJS).
'weex-framework': {
+ weex: true,
entry: path.resolve(__dirname, '../src/entries/weex-framework.js'),
dest: path.resolve(__dirname, '../packages/weex-vue-framework/index.js'),
format: 'cjs'
},
// Weex compiler (CommonJS). Used by Weex's Webpack loader.
'weex-compiler': {
+ weex: true,
entry: path.resolve(__dirname, '../src/entries/weex-compiler.js'),
dest: path.resolve(__dirname, '../packages/weex-template-compiler/build.js'),
format: 'cjs',
@@ -100,6 +102,9 @@ function genConfig (opts) {
banner: opts.banner,
moduleName: 'Vue',
plugins: [
+ replace({
+ __WEEX__: !!opts.weex
+ }),
flow(),
buble(),
alias(Object.assign({}, require('./alias'), opts.alias))
@@ -16,6 +16,7 @@ var webpackConfig = {
},
plugins: [
new webpack.DefinePlugin({
+ __WEEX__: false,
'process.env': {
NODE_ENV: '"development"',
TRANSITION_DURATION: process.env.SAUCE ? 200 : 50,
View
@@ -125,7 +125,7 @@ declare type ASTElement = {
wrapData?: (code: string) => string;
// weex specific
- atom?: boolean;
+ appendAsTree?: boolean;
}
declare type ASTExpression = {
View
@@ -6,6 +6,8 @@ declare type InternalComponentOptions = {
_parentListeners: ?Object;
_renderChildren: ?VNodeChildren;
_componentTag: ?string;
+ _parentElm: ?Node;
+ _refElm: ?Node;
render?: Function;
staticRenderFns?: Array<Function>
}
@@ -61,6 +63,8 @@ declare type ComponentOptions = {
_componentTag: ?string;
_scopeId: ?string;
_base: Class<Component>;
+ _parentElm: ?Node;
+ _refElm: ?Node;
}
declare type PropOptions = {
@@ -55,6 +55,8 @@ function initInternalComponent (vm: Component, options: InternalComponentOptions
opts._parentListeners = options._parentListeners
opts._renderChildren = options._renderChildren
opts._componentTag = options._componentTag
+ opts._parentElm = options._parentElm
+ opts._refElm = options._refElm
if (options.render) {
opts.render = options.render
opts.staticRenderFns = options.staticRenderFns
@@ -79,15 +79,21 @@ export function lifecycleMixin (Vue: Class<Component>) {
callHook(vm, 'beforeUpdate')
}
const prevEl = vm.$el
+ const prevVnode = vm._vnode
const prevActiveInstance = activeInstance
activeInstance = vm
- const prevVnode = vm._vnode
vm._vnode = vnode
+ // Vue.prototype.__patch__ is injected in entry points
+ // based on the rendering backend used.
if (!prevVnode) {
- // Vue.prototype.__patch__ is injected in entry points
- // based on the rendering backend used.
- vm.$el = vm.__patch__(vm.$el, vnode, hydrating)
+ // initial render
+ vm.$el = vm.__patch__(
+ vm.$el, vnode, hydrating, false /* removeOnly */,
+ vm.$options._parentElm,
+ vm.$options._refElm
+ )
} else {
+ // updates
vm.$el = vm.__patch__(prevVnode, vnode)
}
activeInstance = prevActiveInstance
@@ -129,7 +129,9 @@ function createFunctionalComponent (
export function createComponentInstanceForVnode (
vnode: any, // we know it's MountedComponentVNode but flow doesn't
- parent: any // activeInstance in lifecycle state
+ parent: any, // activeInstance in lifecycle state
+ parentElm?: ?Node,
+ refElm?: ?Node
): Component {
const vnodeComponentOptions = vnode.componentOptions
const options: InternalComponentOptions = {
@@ -139,7 +141,9 @@ export function createComponentInstanceForVnode (
_componentTag: vnodeComponentOptions.tag,
_parentVnode: vnode,
_parentListeners: vnodeComponentOptions.listeners,
- _renderChildren: vnodeComponentOptions.children
+ _renderChildren: vnodeComponentOptions.children,
+ _parentElm: parentElm || null,
+ _refElm: refElm || null
}
// check inline-template render functions
const inlineTemplate = vnode.data.inlineTemplate
@@ -150,14 +154,25 @@ export function createComponentInstanceForVnode (
return new vnodeComponentOptions.Ctor(options)
}
-function init (vnode: VNodeWithData, hydrating: boolean) {
+function init (
+ vnode: VNodeWithData,
+ hydrating: boolean,
+ parentElm: ?Node,
+ refElm: ?Node
+): ?boolean {
if (!vnode.child || vnode.child._isDestroyed) {
- const child = vnode.child = createComponentInstanceForVnode(vnode, activeInstance)
+ const child = vnode.child = createComponentInstanceForVnode(
+ vnode,
+ activeInstance,
+ parentElm,
+ refElm
+ )
child.$mount(hydrating ? vnode.elm : undefined, hydrating)
} else if (vnode.data.keepAlive) {
// kept-alive components, treat as a patch
const mountedNode: any = vnode // work around flow
prepatch(mountedNode, mountedNode)
+ return true // let the patcher know this is a reactivated component
}
}
@@ -85,19 +85,26 @@ export function createPatchFunction (backend) {
}
let inPre = 0
- function createElm (vnode, insertedVnodeQueue, nested) {
- let i
+ function createElm (vnode, insertedVnodeQueue, parentElm, refElm, nested) {
+ let i, isReactivated
const data = vnode.data
vnode.isRootInsert = !nested
if (isDef(data)) {
- if (isDef(i = data.hook) && isDef(i = i.init)) i(vnode)
+ if (isDef(i = data.hook) && isDef(i = i.init)) {
+ isReactivated = i(vnode, false /* hydrating */, parentElm, refElm)
+ }
// after calling the init hook, if the vnode is a child component
// it should've created a child instance and mounted it. the child
// component also has set the placeholder vnode's elm.
// in that case we can just return the element and be done.
if (isDef(i = vnode.child)) {
initComponent(vnode, insertedVnodeQueue)
- return vnode.elm
+ if (isReactivated) {
+ // unlike a newly created component,
+ // a reactivated keep-alive component doesn't insert itself
+ insert(parentElm, vnode.child.$el, refElm)
+ }
+ return
}
}
const children = vnode.children
@@ -125,25 +132,56 @@ export function createPatchFunction (backend) {
? nodeOps.createElementNS(vnode.ns, tag)
: nodeOps.createElement(tag, vnode)
setScope(vnode)
- createChildren(vnode, children, insertedVnodeQueue)
- if (isDef(data)) {
- invokeCreateHooks(vnode, insertedVnodeQueue)
+
+ /* istanbul ignore if */
+ if (__WEEX__) {
+ // in Weex, the default insertion order is parent-first.
+ // List items can be optimized to use children-first insertion
+ // with append="tree".
+ const appendAsTree = data && data.appendAsTree
+ if (!appendAsTree) {
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
+ }
+ createChildren(vnode, children, insertedVnodeQueue)
+ if (appendAsTree) {
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
+ }
+ } else {
+ createChildren(vnode, children, insertedVnodeQueue)
+ if (isDef(data)) {
+ invokeCreateHooks(vnode, insertedVnodeQueue)
+ }
+ insert(parentElm, vnode.elm, refElm)
}
+
if (process.env.NODE_ENV !== 'production' && data && data.pre) {
inPre--
}
} else if (vnode.isComment) {
vnode.elm = nodeOps.createComment(vnode.text)
+ insert(parentElm, vnode.elm, refElm)
} else {
vnode.elm = nodeOps.createTextNode(vnode.text)
+ insert(parentElm, vnode.elm, refElm)
+ }
+ }
+
+ function insert (parent, elm, ref) {
+ if (parent) {
+ nodeOps.insertBefore(parent, elm, ref)
}
- return vnode.elm
}
function createChildren (vnode, children, insertedVnodeQueue) {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; ++i) {
- nodeOps.appendChild(vnode.elm, createElm(children[i], insertedVnodeQueue, true))
+ createElm(children[i], insertedVnodeQueue, vnode.elm, null, true)
}
} else if (isPrimitive(vnode.text)) {
nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(vnode.text))
@@ -200,9 +238,9 @@ export function createPatchFunction (backend) {
}
}
- function addVnodes (parentElm, before, vnodes, startIdx, endIdx, insertedVnodeQueue) {
+ function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx, insertedVnodeQueue) {
for (; startIdx <= endIdx; ++startIdx) {
- nodeOps.insertBefore(parentElm, createElm(vnodes[startIdx], insertedVnodeQueue), before)
+ createElm(vnodes[startIdx], insertedVnodeQueue, parentElm, refElm)
}
}
@@ -271,7 +309,7 @@ export function createPatchFunction (backend) {
let newEndIdx = newCh.length - 1
let newStartVnode = newCh[0]
let newEndVnode = newCh[newEndIdx]
- let oldKeyToIdx, idxInOld, elmToMove, before
+ let oldKeyToIdx, idxInOld, elmToMove, refElm
// removeOnly is a special flag used only by <transition-group>
// to ensure removed elements stay in correct relative positions
@@ -305,7 +343,7 @@ export function createPatchFunction (backend) {
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
idxInOld = isDef(newStartVnode.key) ? oldKeyToIdx[newStartVnode.key] : null
if (isUndef(idxInOld)) { // New element
- nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx]
} else {
elmToMove = oldCh[idxInOld]
@@ -318,7 +356,7 @@ export function createPatchFunction (backend) {
}
if (elmToMove.tag !== newStartVnode.tag) {
// same key but different element. treat as new element
- nodeOps.insertBefore(parentElm, createElm(newStartVnode, insertedVnodeQueue), oldStartVnode.elm)
+ createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm)
newStartVnode = newCh[++newStartIdx]
} else {
patchVnode(elmToMove, newStartVnode, insertedVnodeQueue)
@@ -330,8 +368,8 @@ export function createPatchFunction (backend) {
}
}
if (oldStartIdx > oldEndIdx) {
- before = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
- addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
+ refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm
+ addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)
} else if (newStartIdx > newEndIdx) {
removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)
}
@@ -462,7 +500,7 @@ export function createPatchFunction (backend) {
}
}
- return function patch (oldVnode, vnode, hydrating, removeOnly) {
+ return function patch (oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) {
if (!vnode) {
if (oldVnode) invokeDestroyHook(oldVnode)
return
@@ -473,12 +511,13 @@ export function createPatchFunction (backend) {
const insertedVnodeQueue = []
if (!oldVnode) {
- // empty mount, create new root element
+ // empty mount (likely as component), create new root element
isInitialPatch = true
- createElm(vnode, insertedVnodeQueue)
+ createElm(vnode, insertedVnodeQueue, parentElm, refElm)
} else {
const isRealElement = isDef(oldVnode.nodeType)
if (!isRealElement && sameVnode(oldVnode, vnode)) {
+ // patch existing root node
patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
} else {
if (isRealElement) {
@@ -507,14 +546,15 @@ export function createPatchFunction (backend) {
// create an empty node and replace it
oldVnode = emptyNodeAt(oldVnode)
}
+
+ // replacing existing element
elm = oldVnode.elm
parent = nodeOps.parentNode(elm)
+ createElm(vnode, insertedVnodeQueue, parent, nodeOps.nextSibling(elm))
- createElm(vnode, insertedVnodeQueue)
-
- // component root element replaced.
- // update parent placeholder node element, recursively
if (vnode.parent) {
+ // component root element replaced.
+ // update parent placeholder node element, recursively
let ancestor = vnode.parent
while (ancestor) {
ancestor.elm = vnode.elm
@@ -528,7 +568,6 @@ export function createPatchFunction (backend) {
}
if (parent !== null) {
- nodeOps.insertBefore(parent, vnode.elm, nodeOps.nextSibling(elm))
removeVnodes(parent, [oldVnode], 0, 0)
} else if (isDef(oldVnode.tag)) {
invokeDestroyHook(oldVnode)
@@ -1,22 +1,17 @@
/* @flow */
-import {
- getAndRemoveAttr
-} from 'compiler/helpers'
-
-function parse (el: ASTElement, options: CompilerOptions) {
- const staticStyle = getAndRemoveAttr(el, 'append')
- if (staticStyle === 'tree') {
- el.atom = true
+function transformNode (el: ASTElement, options: CompilerOptions) {
+ if (el.attrsMap.append === 'tree') {
+ el.appendAsTree = true
}
}
function genData (el: ASTElement): string {
- return el.atom ? `atom:true,` : ''
+ return el.appendAsTree ? `appendAsTree:true,` : ''
}
export default {
- staticKeys: ['atom'],
- parse,
+ staticKeys: ['appendAsTree'],
+ transformNode,
genData
}
@@ -19,6 +19,9 @@ export function createComment (text) {
}
export function insertBefore (node, target, before) {
+ if (!before) {
+ return appendChild(node, target)
+ }
if (target.nodeType === 3) {
if (node.type === 'text') {
node.setAttr('value', target.text)
@@ -9,4 +9,8 @@ import platformModules from 'weex/runtime/modules/index'
// built-in modules have been applied.
const modules = platformModules.concat(baseModules)
-export const patch: Function = createPatchFunction({ nodeOps, modules })
+export const patch: Function = createPatchFunction({
+ nodeOps,
+ modules,
+ LONG_LIST_THRESHOLD: 10
+})

0 comments on commit 9dce7ad

Please sign in to comment.