diff --git a/flow/compiler.js b/flow/compiler.js index 5c88bc9b..43daa46c 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -19,6 +19,7 @@ declare type CompilerOptions = { shouldDecodeTags?: boolean; shouldDecodeNewlines?: boolean; shouldDecodeNewlinesForHref?: boolean; + optimize?: boolean; // support in weex recyclable?: boolean; diff --git a/src/compiler/helpers.js b/src/compiler/helpers.js index ebcd5708..2c7cd127 100644 --- a/src/compiler/helpers.js +++ b/src/compiler/helpers.js @@ -18,10 +18,12 @@ export function pluckModuleFunction ( export function addProp (el: ASTElement, name: string, value: string) { (el.props || (el.props = [])).push({ name, value }) + el.plain = false } export function addAttr (el: ASTElement, name: string, value: any) { (el.attrs || (el.attrs = [])).push({ name, value }) + el.plain = false } export function addDirective ( @@ -33,6 +35,7 @@ export function addDirective ( modifiers: ?ASTModifiers ) { (el.directives || (el.directives = [])).push({ name, rawName, value, arg, modifiers }) + el.plain = false } export function addHandler ( @@ -105,6 +108,8 @@ export function addHandler ( } else { events[name] = newHandler } + + el.plain = false } export function getBindingAttr ( diff --git a/src/compiler/index.js b/src/compiler/index.js index 075917bd..56b54fd3 100644 --- a/src/compiler/index.js +++ b/src/compiler/index.js @@ -13,7 +13,9 @@ export const createCompiler = createCompilerCreator(function baseCompile ( options: CompilerOptions ): CompiledResult { const ast = parse(template.trim(), options) - optimize(ast, options) + if (options.optimize !== false) { + optimize(ast, options) + } const code = generate(ast, options) return { ast, diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index e93840cb..3f857ef2 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -4,6 +4,7 @@ import VNode from './vnode' import { resolveConstructorOptions } from 'core/instance/init' import { queueActivatedComponent } from 'core/observer/scheduler' import { createFunctionalComponent } from './create-functional-component' +import { renderRecyclableComponentTemplate } from 'weex/runtime/recycle-list/render-component-template' import { warn, @@ -144,21 +145,6 @@ export function createComponent ( data = data || {} - // recycle-list optimized render function for extracting cell-slot - // template. This is essentially inline expanding instead of creating - // an actual instance. - // https://github.com/Hanks10100/weex-native-directive/tree/master/component - if (__WEEX__ && data.attrs && data.attrs['@isInRecycleList']) { - const altRender = Ctor.options['@render'] - if (altRender) { - return altRender.call( - context, - context.$createElement, - data.attrs - ) - } - } - // resolve constructor options in case global mixins are applied after // component constructor creation resolveConstructorOptions(Ctor) @@ -206,6 +192,14 @@ export function createComponent ( { Ctor, propsData, listeners, tag, children }, asyncFactory ) + + // Weex specific: invoke recycle-list optimized @render function for + // extracting cell-slot template. + // https://github.com/Hanks10100/weex-native-directive/tree/master/component + if (__WEEX__ && data.attrs && ('@inRecycleList' in data.attrs)) { + return renderRecyclableComponentTemplate(vnode) + } + return vnode } diff --git a/src/platforms/weex/compiler/index.js b/src/platforms/weex/compiler/index.js index 89ed6ebd..cd4e07ea 100644 --- a/src/platforms/weex/compiler/index.js +++ b/src/platforms/weex/compiler/index.js @@ -43,6 +43,8 @@ export function compile ( // generate @render function for if (options && generateAltRender) { options.recyclable = true + // disable static optimizations + options.optimize = false const { render } = compiler.compile(template, options) result['@render'] = render } diff --git a/src/platforms/weex/compiler/modules/recycle-list/component.js b/src/platforms/weex/compiler/modules/recycle-list/component.js new file mode 100644 index 00000000..a00ee83c --- /dev/null +++ b/src/platforms/weex/compiler/modules/recycle-list/component.js @@ -0,0 +1,12 @@ +/* @flow */ + +import { addAttr } from 'compiler/helpers' +import { RECYCLE_LIST_MARKER } from 'weex/util/index' + +// mark components as inside recycle-list so that we know we need to invoke +// their special @render function instead of render in create-component.js +export function postTransformComponent (el: ASTElement, options: CompilerOptions) { + if (!options.isReservedTag(el.tag) && el.tag !== 'cell-slot') { + addAttr(el, RECYCLE_LIST_MARKER, true) + } +} diff --git a/src/platforms/weex/compiler/modules/recycle-list/index.js b/src/platforms/weex/compiler/modules/recycle-list/index.js index 646f151e..7d449afb 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/index.js +++ b/src/platforms/weex/compiler/modules/recycle-list/index.js @@ -1,5 +1,6 @@ /* @flow */ +import { postTransformComponent } from './component' import { postTransformText } from './text' import { preTransformVBind } from './v-bind' import { preTransformVIf } from './v-if' @@ -32,6 +33,7 @@ function transformNode (el: ASTElement, options: CompilerOptions) { function postTransformNode (el: ASTElement, options: CompilerOptions) { if (shouldCompile(el, options)) { + postTransformComponent(el, options) // : transform children text into value attr if (el.tag === 'text') { postTransformText(el, options) diff --git a/src/platforms/weex/compiler/modules/recycle-list/text.js b/src/platforms/weex/compiler/modules/recycle-list/text.js index 32781054..d896d53c 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/text.js +++ b/src/platforms/weex/compiler/modules/recycle-list/text.js @@ -19,6 +19,5 @@ export function postTransformText (el: ASTElement, options: CompilerOptions) { if (el.children.length) { addAttr(el, 'value', genText(el.children[0])) el.children = [] - el.plain = false } } diff --git a/src/platforms/weex/runtime/recycle-list/render-component-template.js b/src/platforms/weex/runtime/recycle-list/render-component-template.js new file mode 100644 index 00000000..3353c6f5 --- /dev/null +++ b/src/platforms/weex/runtime/recycle-list/render-component-template.js @@ -0,0 +1,17 @@ +/* @flow */ + +import { RECYCLE_LIST_MARKER } from 'weex/util/index' +import { createComponentInstanceForVnode } from 'core/vdom/create-component' + +export function isRecyclableComponent (vnode: VNodeWithData): boolean { + return vnode.data.attrs && (RECYCLE_LIST_MARKER in vnode.data.attrs) +} + +export function renderRecyclableComponentTemplate (vnode: VNodeWithData): VNode { + // TODO: + // 1. adding @isComponentRoot / @componentProps to the root node + // 2. proper error handling + delete vnode.data.attrs[RECYCLE_LIST_MARKER] + const instance = createComponentInstanceForVnode(vnode) + return instance.$options['@render'].call(instance) +} diff --git a/src/platforms/weex/runtime/recycle-list/virtual-component.js b/src/platforms/weex/runtime/recycle-list/virtual-component.js new file mode 100644 index 00000000..da378da8 --- /dev/null +++ b/src/platforms/weex/runtime/recycle-list/virtual-component.js @@ -0,0 +1,6 @@ +// import { +// // id, 'lifecycle', hookname, fn +// // https://github.com/Hanks10100/weex-native-directive/tree/master/component +// registerComponentHook, +// updateComponentData +// } from '../util/index' diff --git a/src/platforms/weex/util/index.js b/src/platforms/weex/util/index.js index 38108343..cffc2ede 100755 --- a/src/platforms/weex/util/index.js +++ b/src/platforms/weex/util/index.js @@ -4,6 +4,8 @@ declare var document: Object; import { makeMap } from 'shared/util' import { warn } from 'core/util/index' +export const RECYCLE_LIST_MARKER = '@inRecycleList' + export const isReservedTag = makeMap( 'template,script,style,element,content,slot,link,meta,svg,view,' + 'a,div,img,image,text,span,input,switch,textarea,spinner,select,' +