标记组件为 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)
},
}