从Vue的渲染功能中控制儿童

时间:2017-11-24 16:17:49

标签: javascript twitter-bootstrap vue.js vuejs2 vue-component

我正在努力使用JS渲染功能在Vue.js中创建一个看似简单的组件 - just a bootstrap panel with optional heading, content and optional footer。我的想法就是这样:

<panel>

  <panel-header> Header </panel-header>

     [ The panel content goes here ]

  <panel-footer> Footer </panel-footer>

</panel>

我的问题是:如何在渲染功能中“包含”子组件(panel-header&amp; panel-footer)及其特定类(即“panel-header”类),将它们保持为可选然而允许完全自由地组成面板主体,使用自己的类(即“panel-body”类和props.title)?

换句话说:我如何控制孩子,但是分开组件,然后让[孩子]填充在面板的中间?

我的渲染sctipt看起来像这样:

import classNames from 'classnames';

export const props = {
tag: {
  type: String,
  default: "div"
},
className: {
  type: String
},
align: {
  type: String,
  default: 'left'
},
title: {
  type: String,
},
header: {
  type: String,
}
};

export default {
 functional: true,
 props,
 render(h, { props, data, children }) {
  const dataObj = {
    class: classNames(
      'card',
      props.align ? 'text-' + props.align : '',
      props.className ? props.className : ''
    ),
 };
 const title = [
  h('h4', {
    class: 'card-title'
  }, props.title)
];

 const content = [
   h('div', {
     class: 'card-body'
   })
 ];
return h(props.tag, dataObj, [title, children] );
}
};

最诚挚的问候, Paco Pacici

编辑:我知道,一旦我按上述方式执行,我将获得所需的效果 - 在面板中以正确的顺序显示标题,内容和页脚。但是如果我想单独为面板的内容添加一些属性,不包括页脚和标题呢?因此,他们也被视为儿童,因此屈服于我的操纵。我想将它们分开处理,但在同一个功能中。

1 个答案:

答案 0 :(得分:2)

基本上,你会检查孩子,根据需要抓住页眉和页脚,并根据需要将它们展开。

console.clear()

const PanelHeader = {
  template: `<div>Im a panel header</div>`
}

const PanelFooter = {
  template: `<div>Im a panel Footer</div>`
}

const Panel = {
  functional: true,
  render(h, context){
    // find the header if there is one. Note that if there is more than
    // one panel-header, only the first one will be used
    let header = context.children.find(c => c.componentOptions && c.componentOptions.tag === "panel-header")
    // same deal for the footer
    let footer = context.children.find(c => c.componentOptions && c.componentOptions.tag === "panel-footer")
    // filter out anything that isn't header/footer
    let body = context.children.filter(c => c !== header && c !== footer)
    
    // layout as desired.
    return h('div', [header, body, footer])
  }
}

new Vue({
  el: "#app",
  components: {Panel, PanelHeader, PanelFooter}
})
<script src="https://unpkg.com/vue@2.5.3"></script>
<div id="app">
  <panel>
    <panel-footer></panel-footer>
    some stuff
    <panel-header></panel-header>
  </panel>
  <hr>
  <panel>
    some stuff
  </panel>
  <hr>  
  <panel>
    <panel-footer></panel-footer>
    some stuff
  </panel>
</div>

此示例仅显示如何获取组件并将其布局。它显然不完全按照你的例子或包括必要的类。

相关问题