javascript - 如何将内容传递到渲染函数(功能组件)中的插槽 - Vue

标签 javascript vue.js

功能按钮组件:

const Button = createElement('button', {}, [slots().icon ? createElement('span', slots().icon[0].text) : null])
上面使用 Button 的另一个功能组件:
createElement(Button, {}, ['this goes to children'])
但这会呈现文本 this goes to children不在 span 内当我把它包裹在上面时。
如何将内容放入 Button 的插槽中来自另一个 createElement() 的组件?
使用模板很容易:
<template>
  <Button>
    <template #icon>This would be wrapped inside span</template>
  </Button>
</template>
更新 1
我必须使用 slot: 'name-of-the-slot'键入数据属性:
const icon = createElement('span', { slot: 'icon' }, 'text inside span')
createElement(Button, {}, [icon])
没有成功。它甚至有效吗?在 Vue 存储库中创建了一个错误报告:https://github.com/vuejs/vue/issues/11519
半解决方案
在 Posva 的帮助下:
export default {
  name: "Wrapper",
  functional: true,
  render(h) {
    return h(Button, { scopedSlots: {
      icon: () => h('span', {}, 'its from wrapper')
    } });
  }
};

export default {
  name: "Button",
  functional: true,
  render(createElement, { scopedSlots }) {
    return createElement("button", {}, scopedSlots.icon(null));
  }
};
ScopedSlots 是关键。
另外不要忘记添加检查,如果此插槽存在,例如:
return createElement("button", {}, scopedSlots.icon ? scopedSlots.icon(null) : null)

最佳答案

使用模板的组件:MyButton.vue

<template>
  <div>
    <slot name="left"></slot>
    <button>
      <slot v-bind:person="person">
        <span>按钮</span>
      </slot>
    </button>
    <slot name="right" v-bind:age="person.age"></slot>
  </div>
</template>

<script>
  export default {
    name: 'MyButton',
    data() {
      return {
        person: {
          name: 'jack',
          age: 23,
        },
      }
    },
  }
</script>
在模板中使用 MyButton:
 <MyButton>
   <template #right="{age}">
     <span>button rigt side. I am  {{ age }} years</span>
   </template>
   <template v-slot="{ person }">this is a button,{{ person }}</template>
   <template #left>
     <span>button left side</span>
   </template>
</MyButton>
在渲染函数中使用它:
import MyButton from './MyButton.vue'
export default {
  name: 'UseButton',
  render(h) {
    const slotLeft = h('template', { slot: 'left' }, 'in the left of button')
    const slotRight = h('template', { slot: 'right' }, 'right')
    const slotDefault = h('template', { slot: 'default' }, 'default slot')
    const children = [slotRight, slotLeft, slotDefault]
    // normal slots in third parms, any order work well
    return h(MyButton, {}, children)
  },
}
从渲染函数中的作用域槽获取数据:
import MyButton from './MyButton.vue'
export default {
  name: 'UseButton',
  render(h) {
    const slotLeft = h('template', { slot: 'left' }, 'normal slot with name left')
    const children = [slotLeft]
    return h(
      MyButton,
      {
       // scopedSlot in the second param
        scopedSlots: {
          // props come from MyButton inside
          default: props => {
            console.log(props)
            const { person } = props
            const text = `defaul scopedSlot,${JSON.stringify(person)}`
            // use h
            return h('span', {}, text)
          },
          right: props => {
            console.log(props)
            const { age } = props
            // use jsx
            return <span>in the right,I am {age} years</span>
          },
        },
      },
      // normal slot
      children
    )
  },
}
MyButton.vue 的实现使用 jsx 或 js。MyButton.jsx
export default {
  name: 'MyButton',
  data() {
    return {
      person: {
        name: 'jack',
        age: 23,
      },
    }
  },
  render(h) {
    const { left, right, default: _defaultSlot } = this.$scopedSlots
    // checek the default exist or not
    const defaultSlot = (_defaultSlot && _defaultSlot({ person: this.person })) || <span>按钮</span>
    const leftSlot = (left && left()) || ''
    const rightSlot = right(this.person)
    const button = h('button', {}, [defaultSlot])
    //  jsx make structure more clear
    return (
      <div>
        {leftSlot}
        {button}
        {rightSlot}
      </div>
    )
  },
}
使用 jsx 的功能组件:FunctionalButton.jsx
export default {
  name: 'FunctionalButton',
  functional: true,
  props: {
    person: {
      type: Object,
      default: () => ({ name: 'jack', age: 23 }),
    },
  },
  // NO DATA in functional component
  // data() {
  //   return {
  //     person: {
  //       name: 'jack',
  //       age: 23,
  //     },
  //   }
  // },
  render(h, { props, scopedSlots }) {
    const { left, right, default: _defaultSlot } = scopedSlots
    const defaultSlot = (_defaultSlot && _defaultSlot({ person: props.person })) || <span>按钮</span>
    const leftSlot = (left && left()) || ''
    const rightSlot = right(props.person)
    const button = h('button', {}, [defaultSlot])
    return (
      <div>
        {leftSlot}
        {button}
        {rightSlot}
      </div>
    )
  },
}

关于javascript - 如何将内容传递到渲染函数(功能组件)中的插槽 - Vue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62912011/

相关文章:

javascript - 如何在一个表中放入多个v-for和v-if语句: Vue. js

javascript - 我在循环中有一个函数,它接受当前循环的匹配并返回具有特定名称的参与者。如何避免重复?

javascript - 音频 : tag write using JavaScript

javascript - Ember : Back button broken

javascript - Flowplayer 的嵌套条件语句

vue.js - 如何更改 v-alert 内部文本/html?

javascript - Chrome 上点击标题时如何防止表格滚动?

javascript - 具有粘性/固定标题的水平和垂直响应表?

vue.js - (VueJS) vue-router 匹配多个路径

vue.js - Vue Single page app Router,当我们改变路由时组件会发生什么?