【问题标题】:VueJS hydration map dom nodes to componentsVueJS 水合将 dom 节点映射到组件
【发布时间】:2018-07-18 21:20:45
【问题描述】:

我有这个要求,我正在寻找使用 VueJS 的可能解决方案,因为它具有这个很好的水合功能,已经从服务器呈现了 HTML。

我的 Vue 组件没有在 .vue 文件中指定模板,但它们应该将(水合部分)附加到 dom 元素并使用它。我对附加子组件只有一个疑问。

例子会很好......

<div class="page-component">
 <h1 v-text="pageTitle">Page Title</h1>

 <div class="child-component">
  <h2 v-text="childTitle">Child Title</h2>
 </div>
</div>

我有两个组件,第一个是 PageComponent,它应该将 h1 中的 v-text 处理为具有类 .page-component 的根 dom 元素的一部分。我有第二个组件 ChildComponent 应该附加到带有类 .child-component 的 dom 元素并处理 h2 中的 v-text。

如果不在 .vue 文件中指定与此布局匹配的模板,我目前无法理解如何做到这一点。我可以看到,如果我使用 vue SSR 渲染包进行 SSR 渲染,则映射正确。但是我想知道是否有一种方法可以创建这种无模板组件,该组件将使用从服务器呈现的内容(但任何服务器,因为在我的情况下,我使用在 Java 中运行的不同服务器,并且我不能使用 npm SSR 包) ,但我也希望能够将组件正确附加到整个 html 文档中的相应部分。

我试图做一些事情,但问题是当 PageComponent 像这样创建和附加:new PageComponent().$mount('.page-component') 时,它会尝试插入与 vue 相关的所有内容,在这种情况下,它将尝试插入两个 v-text 属性,这会中断,因为 childTitle 属性是 ChildComponent 类的一部分。

总结,如果有办法告诉 PageComponent 在哪个点(dom 子树)它应该将插值控制权移交给子组件,而不是尝试附加事件处理程序并自行插值。

我希望我的情况很清楚。

【问题讨论】:

    标签: javascript vue.js vue-component


    【解决方案1】:

    如果我理解正确,您希望从您的 Java 服务器提供一个 HTML 页面(因此不使用 Vue SSR),并在客户端使用您的 Vue 组件“水合”它,但不必复制您的 HTML 页面结构在这些组件模板中(因此您将它们描述为“无模板”)。

    此外,您希望动态数据来自每个组件,而不必指定顶级组件中的所有内容(“它应该将插值控制权移交给子组件”)

    不幸的是,无论您设置什么 Vue 组件组合,编译(“插值”)都会在您使用它们的模板中进行:

    https://vuejs.org/v2/guide/components-slots.html#Compilation-Scope

    父模板中的所有内容都在父范围内编译;子模板中的所有内容都在子范围内编译。

    在您的代码示例中,这意味着 Vue 期望在您的 "page-component" 组件中定义 pageTitlechildTitle 变量(无论是作为数据、道具、计算属性……)

    除非您使用Scoped Slots,这需要特定的语法:

    Vue.component('my-child-component', {
      template: '<div><slot :childTitle="myChildTitle"></slot></div>',
      data() {
        return {
          myChildTitle: 'Child Title from my-child-component',
        };
      },
    });
    
    function activateVue() {
      new Vue({
        el: '#app',
        data: {
          pageTitle: 'Page Title from page-component',
        },
      });
    }
    <button onclick="if (typeof Vue === 'undefined') {alert('Vue is not loaded yet');} else {activateVue();}">Activate Vue</button>
    
    <div class="page-component" id="app">
      <h1 v-text="pageTitle">Page Title from server</h1>
    
      <div class="child-component" is="my-child-component">
        <div slot-scope="{childTitle}">
          <h2 v-text="childTitle">Child Title from server</h2>
        </div>
      </div>
    </div>
    
    <script src="https://unpkg.com/vue@^2.5"></script>

    【讨论】:

    • 谢谢,我会检查并通知您!
    • 好的,我试过这个...但不是很干净,因为我必须将子组件中的所有变量形式定义到父组件中并将它们列出在 slot-scope 属性中,否则它不会工作。我希望能够将它们分开,并告诉 Vue 跳过特定于插值的子树,以便我可以使用不同的组件来渲染它。
    • 是的,不幸的是,一切都是有代价的……鉴于您有非常具体的要求,不适合常见的 Vue 用法,您还必须使用复杂的解决方法来使其符合您的需求。
    猜你喜欢
    • 1970-01-01
    • 2020-12-10
    • 2012-07-31
    • 2015-07-21
    • 1970-01-01
    • 2016-05-14
    • 2022-01-15
    • 1970-01-01
    • 2013-01-02
    相关资源
    最近更新 更多