From 5c2ce0017ff8929e70ce9f701b91d950fb351adb Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 29 Nov 2017 10:35:20 -0500 Subject: [PATCH] feat(weex): WIP fix flow + handle errors in recycle-list template render --- flow/compiler.js | 4 --- src/platforms/weex/compiler/index.js | 15 ++++++++-- .../modules/recycle-list/component.js | 4 ++- .../compiler/modules/recycle-list/index.js | 9 +++--- .../recycle-list/render-component-template.js | 30 +++++++++++++++---- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/flow/compiler.js b/flow/compiler.js index 43daa46c..39e559ac 100644 --- a/flow/compiler.js +++ b/flow/compiler.js @@ -21,9 +21,6 @@ declare type CompilerOptions = { shouldDecodeNewlinesForHref?: boolean; optimize?: boolean; - // support in weex - recyclable?: boolean; - // for ssr optimization compiler scopeId?: string; @@ -37,7 +34,6 @@ declare type CompilerOptions = { declare type CompiledResult = { ast: ?ASTElement; render: string; - '@render'?: string; staticRenderFns: Array; stringRenderFns?: Array; errors?: Array; diff --git a/src/platforms/weex/compiler/index.js b/src/platforms/weex/compiler/index.js index cd4e07ea..47d7835f 100644 --- a/src/platforms/weex/compiler/index.js +++ b/src/platforms/weex/compiler/index.js @@ -14,7 +14,16 @@ import { getTagNamespace } from '../util/index' -export const baseOptions: CompilerOptions = { +export type WeexCompilerOptions = CompilerOptions & { + // whether to compile special template for + recyclable?: boolean; +}; + +export type WeexCompiledResult = CompiledResult & { + '@render'?: string; +}; + +export const baseOptions: WeexCompilerOptions = { modules, directives, isUnaryTag, @@ -31,8 +40,8 @@ const compiler = createCompiler(baseOptions) export function compile ( template: string, - options?: CompilerOptions -): CompiledResult { + options?: WeexCompilerOptions +): WeexCompiledResult { let generateAltRender = false if (options && options.recyclable === true) { generateAltRender = true diff --git a/src/platforms/weex/compiler/modules/recycle-list/component.js b/src/platforms/weex/compiler/modules/recycle-list/component.js index a00ee83c..cade4df4 100644 --- a/src/platforms/weex/compiler/modules/recycle-list/component.js +++ b/src/platforms/weex/compiler/modules/recycle-list/component.js @@ -2,10 +2,12 @@ import { addAttr } from 'compiler/helpers' import { RECYCLE_LIST_MARKER } from 'weex/util/index' +import type { WeexCompilerOptions } from 'weex/compiler/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) { +export function postTransformComponent (el: ASTElement, options: WeexCompilerOptions) { + // $flow-disable-line (we know isReservedTag is there) 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 7d449afb..d3cb85a9 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 type { WeexCompilerOptions } from 'weex/compiler/index' import { postTransformComponent } from './component' import { postTransformText } from './text' import { preTransformVBind } from './v-bind' @@ -9,12 +10,12 @@ import { postTransformVOn } from './v-on' let currentRecycleList = null -function shouldCompile (el: ASTElement, options: CompilerOptions) { +function shouldCompile (el: ASTElement, options: WeexCompilerOptions) { return options.recyclable || (currentRecycleList && el !== currentRecycleList) } -function preTransformNode (el: ASTElement, options: CompilerOptions) { +function preTransformNode (el: ASTElement, options: WeexCompilerOptions) { if (el.tag === 'recycle-list') { currentRecycleList = el } @@ -25,13 +26,13 @@ function preTransformNode (el: ASTElement, options: CompilerOptions) { } } -function transformNode (el: ASTElement, options: CompilerOptions) { +function transformNode (el: ASTElement, options: WeexCompilerOptions) { if (shouldCompile(el, options)) { // do nothing yet } } -function postTransformNode (el: ASTElement, options: CompilerOptions) { +function postTransformNode (el: ASTElement, options: WeexCompilerOptions) { if (shouldCompile(el, options)) { postTransformComponent(el, options) // : transform children text into value attr diff --git a/src/platforms/weex/runtime/recycle-list/render-component-template.js b/src/platforms/weex/runtime/recycle-list/render-component-template.js index 3353c6f5..bd3f7f05 100644 --- a/src/platforms/weex/runtime/recycle-list/render-component-template.js +++ b/src/platforms/weex/runtime/recycle-list/render-component-template.js @@ -1,17 +1,35 @@ /* @flow */ +import { warn } from 'core/util/debug' +import { handleError } from 'core/util/error' 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) + return vnode.data.attrs + ? (RECYCLE_LIST_MARKER in vnode.data.attrs) + : false } -export function renderRecyclableComponentTemplate (vnode: VNodeWithData): VNode { +export function renderRecyclableComponentTemplate (vnode: MountedComponentVNode): VNode { // TODO: - // 1. adding @isComponentRoot / @componentProps to the root node - // 2. proper error handling + // adding @isComponentRoot / @componentProps to the root node + + // $flow-disable-line delete vnode.data.attrs[RECYCLE_LIST_MARKER] - const instance = createComponentInstanceForVnode(vnode) - return instance.$options['@render'].call(instance) + const vm = createComponentInstanceForVnode(vnode) + const render = (vm.$options: any)['@render'] + if (render) { + try { + return render.call(vm) + } catch (err) { + handleError(err, vm, `@render`) + } + } else { + warn( + `@render function not defined on component used in . ` + + `Make sure to declare \`recyclable="true"\` on the component's template.`, + vm + ) + } }