【问题标题】:Inject markup into existing Vue component将标记注入现有的 Vue 组件
【发布时间】:2019-11-03 22:31:11
【问题描述】:

我想将标记注入现有组件。

这是一个简单的例子:

<!-- Arbitrary component X -->
<template>
  <div>
    <!-- I want a headline here -->
    foo!
  </div>
</template>

我知道我可以通过插入&lt;slot/&gt; 然后使用&lt;X&gt;&lt;h1&gt;Hello world!&lt;/h1&gt;&lt;/X&gt; 来实现这一点。但是,我想动态地不编辑原始组件。

所以这是我使用高阶组件的想法:

import X from '~/components/X';
import injectHeadline from '~/hoc/injectHeadline.js';

export default {
  components: {
    X: injectHeadline(X, 'Hello world!')
  }
}

与

<!-- injectHeadline.js -->
export default (component, headline) => Vue.component({
    render(createElement) {
        let result = createElement(component);

        <!-- (*) somehow insert <h1>{{ headline }}</h1> here. How? -->

        return result;
    }
})

但是,我在(*) 中处理渲染结果时运气不佳。我试着摆弄result.context.$children,但这无济于事。 任何想法?

【问题讨论】:

  • 作为一种解决方法,我找到了export default (component, title) =&gt; ({ extends: component, mounted() { let titleElement = document.createElement('h1'); titleElement.textContent = title; this.$el.insertBefore(titleElement, this.$el.firstChild); } });,但这仅适用于客户端。我更喜欢render 阶段。
  • 也许可以看看Vue.compile 将模板字符串编译成渲染函数的函数。
  • @YomS。谢谢。我考虑过。但我无法从 render 函数中确定原始组件的标记。

标签: vue.js vuejs2


【解决方案1】:

可以使用与 React 中相同的模板扩展方法,在 VNode 渲染到 DOM 之前修改它们的层次结构,如 this answer 中所述:

export default (WrappedComponent, headline) => Vue.component({
  extends: WrappedComponent,
  render(h) {
    const elements = this.$options.extends.render.call(this, h);
    elements.children.unshift(<h1>{headline}</h1>));
    return elements;
  }
});

【讨论】:

  • 谢谢,正是我需要的!出于某种原因,它只有在我返回一个没有Vue.component 的配置对象时才有效,所以我最终得到了export default (WrappedComponent, headline) =&gt; ({ extends: WrappedComponent, render(createElement) { const elements = this.$options.extends.render.call(this, createElement); elements.children.unshift(createElement('h1', headline)); return elements; } });
【解决方案2】:

就这么简单

<script>
export default {
  functional: true,
  render: function(createElement, context) {
    return createElement("div", context.slots().default);
  }
};
</script>

顺便说一句,我将其设置为功能性以提高性能(在这种情况下不需要 vnode)

在你的代码中你可以这样做

let result = createElement(component,this.$slots.default);

【讨论】:

    猜你喜欢
    • 2017-12-30
    • 2019-02-03
    • 2021-09-12
    • 2021-11-30
    • 2019-06-17
    • 2022-08-15
    • 2021-09-03
    • 2021-05-10
    • 2019-03-06
    相关资源
    最近更新 更多