Vue pass slot template to extended component

前端 未结 5 1540
Happy的楠姐
Happy的楠姐 2021-01-12 02:24

Is any way to pass a template to extended component? Example, that illustrates the problem:

There is a component named Slide with a template like so:

相关标签:
5条回答
  • 2021-01-12 02:33

    If You can change Your source code structure, You should also be able to use jsx. In Vue-Cli3 it requires additional babel plugin, in Nuxt it works out of the box). You simply create some hook function as method or compute, for example:

    slotHook () {
      return(
      <template v-slot.../>
    )}
    

    and place it inside the render function. Then, in the child (component extending the default one), You overwrite the slotHook method:

    slotHook () {
      return (
        <template v-slot... some-differen-params:.../>
    )}
    

    This approach does not cause any errors/issues during render and works flawless. Other approach might be to use PUG templates and their block & extend functionality. I know I'm posting this response quite late, but maybe it could help somebody.

    0 讨论(0)
  • 2021-01-12 02:34

    You have to pass it like this:

    <Slide>
       //HTML code here goes to slot
    </Slide>
    
    0 讨论(0)
  • 2021-01-12 02:40

    (This question is similar to this SO question. I am just gonna share a similar answer I post for that question here.)

    The trick is simple. Basically, when extending, create a new component that registers Parent as a local component.

    Demo: https://jsfiddle.net/jacobgoh101/omjgmb3f/

    const Slide = Vue.extend({
      components: {
        Parent
      },
      template: `
      <Parent>
        <div style="color:red">I am a slot</div>
      </Parent>
    `
    });
    new Slide().$mount('#container')
    
    0 讨论(0)
  • 2021-01-12 02:48

    You can use Vue.compile combined with $createElement.

    const slotTemplate = `<div><h4>This is the slot content</h4>{{message}}</div>`;
    const renderer = Vue.compile(slotTemplate)
    const slotContent = {
      data(){
        return {
          message: "some data in the slot"
        }
      },
      render: renderer.render,
      staticRenderFns: renderer.staticRenderFns
    }
    
    const instance = new Slide();
    instance.$slots.default = [instance.$createElement(slotContent)];
    instance.$mount("#container");
    

    Above is an example of a slot that requires some data. If your slot content is just HTML you could get away with just this:

    const slotTemplate = `<div><h4>This is the slot content</h4></div>`
    const instance = new Slide();
    instance.$slots.default = [instance.$createElement(Vue.compile(slotTemplate))];
    instance.$mount("#container");
    

    Here is an example.

    Note: $slots[key] should be an array of vNodes. It will render correctly if you use a vNode, but there will be bugs (e.g. when calling vm._update)

    0 讨论(0)
  • 2021-01-12 02:51

    If you are open to change your approach a little bit, a <component> instead of <slot>:

    https://jsfiddle.net/jonataswalker/z5Lgbjv8/

    const Parent = {
      template: `<div>
            <span>parent content</span>
          <component :is="view"></component>
        </div>`,
      data() {
        return { view: '' }
      }
    }
    
    const Other = {
      template: `<div>
            <h1>from Other</h1>
        </div>`
    }
    
    const Slide = Vue.extend(Parent)
    
    // how to pass template to the Parent`s slot?
    new Slide({
      data: { view: Other }
    }).$mount('#container')
    
    0 讨论(0)
提交回复
热议问题