vue3组件中使用render函数

官方API见这里: https://v3.vuejs.org/api/options-dom.html#render

为了制作一个下面这样的自定义组件,满足: 传入值作为heading的层级,并将自定义中的内容作为heading的内容。

<anchored-heading :level="1">Hello world!</anchored-heading>

如果不用render()函数,那么你的代码可能是这样的:

const { createApp } = Vue

const app = createApp({})

app.component('anchored-heading', {
  template: `
    <h1 v-if="level === 1">
      <slot></slot>
    </h1>
    <h2 v-else-if="level === 2">
      <slot></slot>
    </h2>
    <h3 v-else-if="level === 3">
      <slot></slot>
    </h3>
    <h4 v-else-if="level === 4">
      <slot></slot>
    </h4>
    <h5 v-else-if="level === 5">
      <slot></slot>
    </h5>
    <h6 v-else-if="level === 6">
      <slot></slot>
    </h6>
  `,
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

使用render(),你的代码可能是这样的:

const { createApp, h } = Vue

const app = createApp({})

app.component('anchored-heading', {
  render() {
    return h(
      'h' + this.level, // tag name
      {}, // props/attributes
      this.$slots.default() // array of children
    )
  },
  props: {
    level: {
      type: Number,
      required: true
    }
  }
})

我们再来看一个例子:

Goal

Implement the "example" component which given the following usage:

<example :tags="['h1', 'h2', 'h3']"></example>

which renders the expected output:

<div>
  <h1>0</h1>
  <h2>1</h2>
  <h3>2</h3>
</div>

Solution

Vue.component('example', {
  props: ['tags'],
  render (h) {
    // Note that the second argument (data object) can be omitted, and the
    // children argument can accept strings or numbers besides Array of vnodes.
    // api 可以参考 https://v3.vuejs.org/api/global-api.html#h
    return h('div', this.tags.map((tag, i) => h(tag, i)))
  }
})

我们还可以将一个组件作为第一个参数传入render函数。下面的这个例子中,我们将一个[functional组件](https://v3.vuejs.org/guide/render-function.html#functional-components)作为参数传入了render函数, 并将render函数结果作为这个组件的内容传递出去:

Goal

  1. Implement a Foo component which simply renders <div>foo</div>, and a Bar component which simply renders <div>bar</div> (using render functions, obviously).

  2. Implement an <example> component which renders the Foo component or the Bar component based on its ok prop. For if ok is true, the final rendered dom should be <div>foo</div>.

  3. Implement a button in the root component that toggles <example> between Foo and Bar by controlling its ok prop.

Solution

const Foo = {
  render (h) {
    return h('div', 'foo')
  }
}

const Bar = {
  render (h) {
    return h('div', 'bar')
  }
}

Vue.component('example', {
  props: ['ok'],
  render (h) {
    return h(this.ok ? Foo : Bar)
  }
})

new Vue({
  el: '#app',
  data: { ok: true }
})
posted @ 2021-12-29 21:45  Bravo_Jack  阅读(2424)  评论(2编辑  收藏  举报