函数式组件


标记组件为 functional:true,这意味它是无状态 (没有响应式数据),无实例 (没有 this 上下文,没有生命周期),为了弥补缺少的实例,提供第二个参数ctx作为函数式组件的上下文(Render 函数提供了第⼆个参数 context 来提供临时上下⽂)。

函数式组件做子组件

  • 函数式组件一:功能实现临时变量的目的
创建tempVar.js函数式组件
// 父组件中传递变量给函数式组件,函数式组件用ctx.props接收数据,render的时候将内容返回给父组件中的插槽。

export default {
    functional:true,
    render:(h,ctx)=>{
        return ctx.scopedSlots.default&&
        ctx.scopedSlots.default(ctx.props||{});
    }
}

//在render的时候,直接将传递过来的属性返回给调用方

// 在父组件中
<tempVar :var1='`hello${name}`' :var2 = "destrogclock?'hello':'world'">
<template v-slot = "{var1,var2}">
    {{var1}} {{var2}}
</template>
</tempVar>

<script>
import TempVar from './TempVar' ;
export defalt {
    components:{
        TempVar }
}
</script>

  • 函数式组件二:选择性显示tooltip
// 在函数式组件中,变量用{}单花括号包裹

export default {
  functional: true,
  render: (h, ctx) => {
    if (ctx.props.isHaveTooltip) {
      return (<el-tooltip content={ctx.props.content}> { ctx.scopedSlots.default && ctx.scopedSlots.default(ctx.props || {})}</el-tooltip>)
    }
    return ctx.scopedSlots.default &&
    ctx.scopedSlots.default(ctx.props || {})
  }
}

// 在父组件中使用


<hoverTooltip :is-have-tooltip="true" content="Top Center 提示文字2">
    <el-button type="success">已解决,提交客户确认</el-button>
</hoverTooltip>

import hoverTooltip from './hoverTooltip.js'
export default {
  components: { hoverTooltip }
}

  • 函数式组件三
    Vue.component('item', {
        functional:true,
        render:function (h,context){
            return h('li',
            // 'li' 是参数一
            {
                on:{
                    click:function(){
                      console.log(context.parent);
                      console.log(context.props); 
                         }
                     }
             },
             // 对象是参数二
             context.children //参数三
             )}
            }, 
            props:[
                value:{
                type:string , default:'给函数式子组件的数据'}]
                }
            })
        }
    })

对比非函数式组件三:

// 创建childHeader.js文件,作为子组件
export default {
    props:{
        value:{
            type:Number,
            default:1
        }
    },
    render:function (creatElement){
        return creatElement(
        'h'+this.value,this.$slots.defalut
        )
    }
}
// 父组件
<childHeader :value = '1'>
  <template v-slot:leader>
  <h1>内容</h1>
</childHeader>
import childHeader from 'childHeader.js'
export defalut {
    components:{
        childHeader
    }
}
// 或者子组件写法二

components:{
    childHeader:{
        functional:true,
        render:(h,ctx)=> h('h'+ctx.props.value)
    }
}

函数式组件做孙组件1 — slot

// 父组件(使用组件)
     <CommonTable
            v-loading="table_loading"
            :table-data="getsystemTableDataTest"
            :columns="getsystemTableArr"
          >
            <template v-slot:isOperate="{ row }">
              <el-link type="primary" @click="handleLinkToDetail(row)">
                查看详情
              </el-link>
            </template>
    </CommonTable>
    
    
// 子组件内容 - CommonTable组件  
<template slot-scope="scope">
 <table-slot v-bind="scope" :column-data="col" />
</template>
 
 export default {
  name: 'CommonTable', 
  provide() {
    return {
      tableRoot: this
    }
  }
}
 
// 孙组件-函数式组件

//ctx.props.column.property 是使用时定义的表格这列的具名插槽的名称

export default {
  name: 'table-slot',
  functional: true,
  inject: ['tableRoot'], 
  props: {
    row: Object,
    column: Object, //表格列的数据
    $index: Number,
    columnData: Object
  },
  render: (h, ctx) => {
    return h('div', {
      style: {
        'white-space': 'nowrap'
      }
    }, ctx.injections.tableRoot.$scopedSlots[ctx.props.column.property]({
      row: ctx.props.row,
      column: ctx.props.column,
      index: ctx.props.$index,
      columnData: ctx.props.columnData
    }))
  }
}


函数式组件做孙组件2 - render

// 父组件(使用组件)

<template>

 <div>

 <my-component :render="render"></my-component>

 </div>

</template>

<script>

import myComponent from '../components/my-component.vue'

export default {

 components: { myComponent },

 data() {

 return {

 render: (h) => {
 
 // h是从函数式组件中传递过来的
 return h('div', { style: { color: 'red' } }, '⾃定义内容')

 },

 }

 },

}

</script>

// 子组件 


<!-- my-component.vue -->

<template>

 <div><Render :render="render"></Render></div>

</template>

<script>

import Render from './render.js'

export default { 
components: { Render }, 
props: { render: Function } 
}

</script>


// 孙组件 - 函数组件

 //   它只定义了⼀个 props:render,格式为 Function,因为是 functional,所以在 render ⾥使⽤了第⼆个参数 ctx 来获取 props。这是⼀个中间⽂件,并且可以复⽤,其它组件需要这 个功能时,都可以引⼊它

 // render.js

 export default {

 functional: true,
// render 函数可以取成其他名字
 props: { render: Function },

 render: (h, ctx) => {
 return ctx.props.render(h)

 },

 }

参考

组件封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值