关于compile

在带有编译版本的vue中,finishComponentSetup会对没有render方法,但是有template的Component,做编译处理。

这里推荐一个compile在线转换成render的网站:

https://vue-next-template-explorer.netlify.app/

finishComponentSetup的代码片段:

Component.render = compile(Component.template, {
        isCustomElement: instance.appContext.config.isCustomElement || NO
})

去查看一下compile的CompilerOptions相关配置。

type CompilerOptions = ParserOptions & TransformOptions & CodegenOptions

// ParserOptions:
export interface ParserOptions {
  // 平台上本地元素, 例如<div>是网页上的本地标签
  isNativeTag?: (tag: string) => boolean

  // 不需要闭合的原生元素, 例如 <img>, <br>, <hr>
  isVoidTag?: (tag: string) => boolean

  // 应该保留内部空白的元素, 例如<pre> 
  // https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/pre
  isPreTag?: (tag: string) => boolean

  // 特定于平台的内置组件,例如<Transition>
  isBuiltInComponent?: (tag: string) => symbol | void

  // 自定义于平台的本地元素
  isCustomElement?: (tag: string) => boolean

  // 获取标签的名称
  getNamespace?: (tag: string, parent: ElementNode | undefined) => Namespace

  // 获取此元素的文本分析模式
  getTextMode?: (
    node: ElementNode,
    parent: ElementNode | undefined
  ) => TextModes

  // 默认 [', '],可修改为你喜欢的
  delimiters?: [string, string]

  // Only needed for DOM compilers,解码实体
  decodeEntities?: (rawText: string, asAttr: boolean) => string

  // 错误  
  onError?: (error: CompilerError) => void
}


// TransformOptions:
export interface TransformOptions {
  /**
   * An array of node trasnforms to be applied to every AST node.
   */
  nodeTransforms?: NodeTransform[]
  /**
   * An object of { name: transform } to be applied to every directive attribute
   * node found on element nodes.
   */
  directiveTransforms?: Record<string, DirectiveTransform | undefined>
  /**
   * An optional hook to transform a node being hoisted.
   * used by compiler-dom to turn hoisted nodes into stringified HTML vnodes.
   * @default null
   */
  transformHoist?: HoistTransform | null

  // 如果提供了其他的内置元素,可以使用该选项标记为内置的,这样编译器将为这些标签生成组件vnode  
  isBuiltInComponent?: (tag: string) => symbol | void
  /**
   * 把表达式  转换成 `_ctx.foo`
   * 如果该选项为false, the generated code will be wrapped in a
   * `with (this) { ... }` block.
   * - This is force-enabled in module mode, since modules are by default strict
   * and cannot use `with`
   * @default mode === 'module'
   */
  prefixIdentifiers?: boolean


  // 静态提升到 `_hoisted_x` 变量
  // 默认值 false
  hoistStatic?: boolean

  // 开启前 { onClick: _ctx.foo }  
  // 开启后 {
  //         onClick: _cache[1] || (_cache[1] = (...args) => (_ctx.foo(...args)))
  //       }
  // _cache[index] index根据当前缓存事件数量,保证预留一个空的位置給该事件
  // 默认值 false
  cacheHandlers?: boolean

  // `@babel/parser` 中的插件,  
  // https://babeljs.io/docs/en/next/babel-parser#plugins
  expressionPlugins?: ParserPlugin[]

  // Single File Component组件中scoped styles ID
  scopeId?: string | null
  /**
   * Generate SSR-optimized render functions instead.
   * The resulting funciton must be attached to the component via the
   * `ssrRender` option instead of `render`.
   */
  ssr?: boolean
  onError?: (error: CompilerError) => void
}

// CodegenOptions

例子:

<div id="foo" :class="bar.baz">
  \{\{ world.burn() \}\}
  <div v-if="ok">yes</div>
  <template v-else>no</template>
  <div v-for="(value, index) in list"><span>NaN</span></div>
</div>

转换成render:

const _Vue = Vue

return function render(_ctx, _cache) {
  with (_ctx) {
    const { toDisplayString: _toDisplayString, createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList } = _Vue

    return (_openBlock(), _createBlock("div", {
      id: "foo",
      class: bar.baz
    }, [
      _createTextVNode(_toDisplayString(world.burn()) + " ", 1 /* TEXT */),
      ok
        ? (_openBlock(), _createBlock("div", { key: 0 }, "yes"))
        : (_openBlock(), _createBlock(_Fragment, { key: 1 }, [
            _createTextVNode("no")
          ], 64 /* STABLE_FRAGMENT */)),
      (_openBlock(true), _createBlock(_Fragment, null, _renderList(list, (value, index) => {
        return (_openBlock(), _createBlock("div", null, [
          _createVNode("span", null, _toDisplayString(value + index), 1 /* TEXT */)
        ]))
      }), 256 /* UNKEYED_FRAGMENT */))
    ], 2 /* CLASS */))
  }
}

results matching ""

    No results matching ""