Просмотр исходного кода

feat(weex): WIP fix flow + handle errors in recycle-list template render

Evan You 8 лет назад
Родитель
Сommit
5c2ce0017f

+ 0 - 4
flow/compiler.js

@@ -21,9 +21,6 @@ declare type CompilerOptions = {
   shouldDecodeNewlinesForHref?: boolean;
   optimize?: boolean;
 
-  // support <recycle-list> 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<string>;
   stringRenderFns?: Array<string>;
   errors?: Array<string>;

+ 12 - 3
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 <recycle-list>
+  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

+ 3 - 1
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)
   }

+ 5 - 4
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)
     // <text>: transform children text into value attr

+ 24 - 6
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 <recycle-list>. ` +
+      `Make sure to declare \`recyclable="true"\` on the component's template.`,
+      vm
+    )
+  }
 }