vue 插槽scope_vue中的h是什么,createElement如何使用

56a7e4eae999ede89e801b65d1c23187.png

目录

  1. h方法介绍
  2. createElement简介
  3. createElement、this.$slots、scopedSlots用法
  4. 完整代码下载

一、h方法介绍

如果你接触过 vue 一段时间了,那么你可能会遇到过rendering方法在你的 app 文件中 -- 在最新版本的CLI中它是一个默认值, 并且是在main.js文件中:

new Vue({
 render: h => h(App)
}).$mount('#app')

或者是,如果你使用了 render 方法 (函数),可能会使用 JSX:

Vue.component('jsx-example', {
  render (h) {
    return <div id="foo">bar</div>
  }
})

或许你想知道,h 是用来干嘛的?它表示什么意思呢? h 代表的是 hyperscript 。它是 HTML 的一部分,表示的是 超文本标记语言:当我们正在处理一个脚本的时候,在虚拟 DOM 节点中去使用它进行替换已成为一种惯例。这个定义同时也被运用到其他的框架文档中。详情点击这里 Cycle.js。

在这个问题上,Evan 描述到:

Hyperscript 它本身表示的是 "生成 HTML 结构的脚本"

缩写为 h 是因为它更容易去输入。 他还在 Frontend Masters 上描述了这一点 他的高级 Vue 研讨会 。

真的,你可以认为它是 createElement 的缩写。 这将是一个长长的形式:

//使用createElement
render: function (createElement) {
  return createElement(App);
}

//用 h 代替它
render: function (h) {
  return h(App);
}

//ES6简写
render: h => h (App)

名称 hyperscript 可能会让某些人感到困惑,因为 hyperscript 实际上是 一个库的名字(这些日子没有更新 ),它实际上有一个 小的生态系统。 在这种情况下,我们不是在谈论那个特定的实现。

希望能为那些感到困惑的人解决问题!

二、createElement简介

h(createElement)函数有3个参数

render(h){return h(param1,{},param3)}
  1. param1可以是 String | Object | Function
  2. 第二个是数据对象。 我们在这里主要包括:props, attrs, dom props, class 和 style....
  3. param3代表子节点,可以是 String | Array

更深入的信息你可以在 Vue 指南 里找到。

三、createElement、this.$slots、scopedSlots用法

3.1 createElement有3个参数(接上),我们先看看简单的

h( ’ div‘ , {} , String) 和 h( ’ div‘ , {} , Array) 这两种情况

父组件Parent.vue

//Parent.vue
//...
<baseComponent @customize-click="handleCustClick" :test="100"/>
const baseComponent = () => import("./BaseComponent")
export default {
    components: {
      baseComponent
    }
    //...
}

子组件BaseComponent.vue

//BaseComponent.vue
<style scoped>
  .box{ background: rgba(0, 0, 0, 0.5) }
  .a{ color: blue; text-decoration: underline }
  .p{ color: firebrick }
</style>

<script>

export default {
  name: 'BaseComponent',
  props: {
    test: Number,
  },
  methods: {
    handleClick () {
      this.$emit('customize-click')
    }
  },
  render(h){
    return h('div',{
      'class': { box: true },
      style: { fontSize: '14px' }
    },[
       '我是字符串',        
        h('p',{ 'class': { p: true } },'我是p标签'),
        h('a',{ 'class': { a: true } },'我是a标签呀'),
        h('p',{ on: { click: this.handleClick } },'点我!!!')
    ])
  }
}
</script>

a97c2323119f56b79051df7e91945e50.png

3.2 在看点有难度的:使用 this.$slots、this.$scopedSlots.default 创建带slot的子组件

PS :vue中提到的slot有匿名插槽、具名插槽、作用域插槽,同时也需要注意废弃的API

前2个先不看了,来看看作用域插槽:

有时让插槽内容能够访问子组件中才有的数据是很有用的。

我觉得官网说的不太清楚,我理解实质就是在具名插槽的基础上加了一个data,把data放到组件中。看demo理解的更快

Page.vue父组件引入调用

//Page.vue
<template>
  <child>
    //废弃写法
    <template slot-scope="user">{{user.data}}</template>
    //2.6.0之后写法
    <template v-slot="user">{{user.data}}</template>
  </child>
</template>
//...

Child.vue子组件定义

//Child.vue
 <template>
  <div>
    <slot :data="list" name="user">
      <h6>具名slot</h6>
    </slot>
  </div>
</template>
<script>
export default {
 data: function(){
  return {
    list: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
  }
 }   
}
</script> 

3f4103cd474fa9eea6ef6ef1cba137b1.png
结果很完美

3.2.1 对作用域插槽有了基本了解,我们在看看this.$slots 和 this.$scopedSlots的使用

this.$slots

你可以通过 this.$slots访问静态插槽的内容
//template版本
<template>
  <div>
    <slot></slot>
  </div>
</template>


//render版本
render: function (h) {
  return h('div', this.$slots.default)
}

this.$scopedSlots :

也可以通过 this.$scopedSlots 访问作用域插槽,每个作用域插槽都是一个返回若干 VNode 的函数:
//template版本
<template>
  <div>
    <slot :text="message" name="name1"></slot>
  </div>
</template>


//...
props: ['message'],
render: function (h) {
  return h('div', [
    this.$scopedSlots.name1({
      text: this.message
    })
  ])
}
//...

下面我们来看一个简单的例子,来实战一下

Parent.vue

//Parent.vue
<template>
  <h1>slot使用</h1>
  <SlotC :list="[1,2,3,4]">
    <p>asdasdsa</p>
  </SlotC>

  <h1>slot-scope使用</h1>
  <Scc>
    <!-- 废弃写法 -->
    <div slot-scope="props">{{ props.text }}</div>

    <!-- 推荐写法 -->
    <template v-slot:deff222="props">
      <p>{{props.text}}</p>
    </template>
    <template v-slot:csgo="props">
      <p>{{props.text}}</p>
    </template>
   </Scc>
</template>

SlotC.vue

<script>
export default {
  props: ['list'],
  render(h){
    console.log('我是$slots ',this.$slots);
    return h('div', [this.list.map(item=>'-'+item),this.$slots.default])
 }
}
</script>

CcopedSlotsC.vue

<script>
export default {
  data(){
    return {
      default:'default',
      deff222:'deff222',
      csgo:'csgo'
    }
  },
  props: ['list'],
  render(h){
        console.log('我是this.$scopedSlots',this.$scopedSlots);
        return h('div', [
            this.$scopedSlots.default({
                text: this.default
            }),
            this.$scopedSlots.deff222({
                text: this.deff222
            }),
            this.$scopedSlots.csgo({
                text: this.csgo
            })
        ])  
 }
}
</script>

5d4b86a838be7365356319d6fa81a658.png

3.2.2 createElement 第一个参数有个Object(组件选项对象)、第二个参数有个scopedSlots,我们来看下。

Parent.vue

//Parent.vue
<baseComponent @customize-click="handleCustClick" :test="100"/>
//...

BaseComponent.vue

//BaseComponent.vue
<style scoped>
  .box{ background: rgba(0, 0, 0, 0.5) }
  .a{ color: blue; text-decoration: underline }
  .p{ color: firebrick }
</style>

<script>
import hw from './HelloWorld.vue';

export default {
  name: 'BaseComponent',
  props: {
    test: Number,
  },
  methods: {
    handleClick () {
      this.$emit('customize-click')
    }
  },
  // 使用scopedSlots
  render(h){
    return h(hw,{
      scopedSlots: {
        'name-slot': props => h(
          'ul',
          props.text.map(item=> h('li',item))
        )
      }},[
        h('p',123),h('p',666),h('p',999)
      ])
  }
}
</script>

HelloWorld.vue

//HelloWorld.vue
<template>
    <div>
      <slot name='name-slot' :text='list'></slot>
      <h1>我是HW</h1>
      <slot name="header"/>
      <slot/>
      <slot name="footer"></slot>
    </div>
</template>
<script>
export default {
  data() {
      return {
        list: ['zhangsan','lisi','wanwu','zhaoliu','tianqi','xiaoba']
      }
  }
}
</script>

2d94ecc2f9a19876151d54f3a6322f8d.png

四 、代码地址: 点我、点我、点我

参考:

在 Vue 的 render 方法中 h 是什么意思?​learnku.com
d13c49923f34b7293469c26674ccbdde.png
render 函数基础 | Slot与scopedSlots使用​blog.csdn.net
c06e15135c4169fcfd9ab2ff8f43e4e5.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值