【问题标题】:Use the HTML of a slot as a raw (uncompiled) template将插槽的 HTML 用作原始(未编译)模板
【发布时间】:2018-12-13 01:42:37
【问题描述】:

是否可以不编译默认插槽?

或者我可以在编译之前访问 innerHTML 吗?

我想使用一个组件的默认插槽作为另一个动态创建的组件的模板。

这似乎是不可能的,即我看了一段时间并没有找到任何关于它的东西......但是像 v-if 这样的指令确实会阻止内容的编译。我在哪里可以访问这些仍未编译的内容?

一个例子如下:

<my-component>
  <ul>
    <li v-for="a in b">{{a.text}}</li>
  </ul>
</my-component>

我需要获取内容,作为一个字符串,即:

  <ul>
    <li v-for="a in b">{{a.text}}</li>
  </ul>

在它被编译之前。

我尝试在组件生命周期的每一步获取默认插槽内容,但我只编译它。

编辑:好的,我将尝试解释我真正想要实现的目标:

我有这些组件,它们是某种内容持有者(标签),我可以在它们之间切换。它们是另一个组件(选项卡容器)的一部分。问题是我希望能够以多种不同的方式配置和初始化我的选项卡。示例:

<tabs-container :tabs="[
  {title: 'Tab 4', content: '<p>Lore ipsum...</p>', url: 'tab4'},
  {title: 'Tab 5', content: '<p>Lore ipsum...</p>', url: 'tab5'}
]">
  <tab title="Tab 1" url="tab1">
    <!-- This is bound to the parent data -->
    <ul>
     <li v-for="a in b">{{a.text}}</li>
    </ul>
  </tab>
  <tab title="Tab 2" component="my-other-component" :data="myData"/>
  <tab title="Tab 3" load="true" url="tab3"/>
</tabs-container>

其实这里我几乎可以做任何事情,但是Tab 3,因为它的内容被加载需要变异,这是不可能的。

所以我应该在挂载此选项卡之前获取它的属性,将其合并到我的选项卡数组中,然后将其从插槽中删除。

但是,如果我不安装插槽,那么我需要以相同的方式处理其中的所有选项卡,并将它们包含在我的全局选项卡数组中(我不能使用插槽中的选项卡组件)。

但如果我这样做,我需要能够将我的插槽的 innerHTML 内容作为字符串获取,并将其用作动态本地组件的模板 - 动态创建的组件。

使用动态字符串作为模板创建这样的组件是可行的,但我的问题是从我的插槽中获取此字符串。

我希望我是有道理的:)

编辑 2:

另一种可能的解决方案:

我的容器中有一个 内容,其中 v-if=“test”。如果我理解得很好,如果测试为假,我的内容将不会被编译。如果它成为真的,它会的。所以虽然测试是假的,我在哪里可以得到我的 v-if 的内容?必须有一个内部隐藏属性,我可以在其中访问此信息。

有人知道吗?

非常感谢!

【问题讨论】:

  • 你能分享你的代码示例吗?
  • 为什么需要它作为字符串?你能给我们更多的背景信息吗?
  • 听起来像XY problem;为什么需要动态创建组件?肯定有更好的方法来实现您想要做的任何事情(需要更多信息)。
  • 您的 TabsContainer 组件是否接受来自 tabs 属性(作为数据)它的槽的选项卡?理想情况下,它应该只有一种方式或另一种方式,否则将难以管理。我仍然对标签 1、2 和 3 感到困惑;选项卡 1 具有插槽内容,选项卡 2 具有 componentdata 道具(不确定它是如何工作的),选项卡 3 具有 load=true (这是否意味着它的内容是异步加载的?)。这里发生了太多事情。
  • @DecadeMoon 是的,基本上这就是问题所在,标签道具 + 插槽 + 用户操作(添加/删除标签),有些是静态的,有些是异步的,其他是绑定到给定数据的组件。我知道这很令人困惑,但如果我能在编译之前获得 innerHTML,我的问题就会得到解决......

标签: vue.js vue-component


【解决方案1】:

您想到的解决方案(获取插槽的原始未编译模板以便在运行时动态生成组件)不是理想的解决方案。

如果您的组件模板是预编译的(例如,通过vue-loader),则不可能将模板源作为字符串获取,因为它在最终构建中不存在 - 模板被编译为 JavaScript 渲染函数.

你的 TabsContainer 和 Tab 组件都做的太多了:

  • TabsContainer 组件通过tabs 属性(作为数据)和/或直接作为插槽呈现的&lt;tab&gt; 组件接受选项卡。 tabs 道具不是必需的;只需使用 v-for 直接在模板中将数据渲染为插槽。
  • Tab 组件以 3 种不同方式之一工作:
    1. 在其默认槽中预先定义的内容
    2. 通过componentdata 道具提供的内容
    3. 内容异步加载(我假设是 Tab 组件),load 属性设置为 true

您的 TabContainer 和 Tab 组件应该非常简单且“愚蠢”(没有太多逻辑)。如果您需要一些逻辑,例如需要通过 API 获取某些选项卡的内容,那么这应该由父组件执行,或者定义一个包装器组件来执行此操作。

其实这里我几乎可以做任何事情,但是Tab 3,因为它的内容被加载需要变异,这是不可能的。

这一点我最难理解。您要获取的内容是组件模板(例如,带有{{ }} 标记)还是纯 HTML?如果是前者,那么您需要compile it at runtime。无论哪种情况,在您获取内容后仍然可以呈现选项卡,只需使用v-ifv-for 将动态选项卡呈现为选项卡容器的插槽。

我不确定您所说的“需要变异”是什么意思;即使 Tab 模板的某些部分需要更改以响应数据/内容的变化,这仍然可以通过像渲染任何类型的动态数据时通常那样渲染 Tab 来完全实现。

我很难提供一个能满足所有条件的解决方案;如果您能提供fiddlecodesandbox,那就太好了。

【讨论】:

  • 感谢您的宝贵时间。我在 SPA 中有一个基于选项卡的导航系统 - 可以在生产中使用。完整组件:github.com/nabab/bbn-vue/tree/master/src/components/tabnav 我正在从选项卡中删除导航系统,将所有路由逻辑放在一个专用且更通用的组件中,我们可以将其称为内容切换器或路由器。我希望混合配置它的方式,因为即使对象将是默认值,如果我想在 2 个非常简单的内容之间切换,我不想要 3 个文件,但只能在插槽中内联写入所有内容。
猜你喜欢
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-11
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
相关资源
最近更新 更多