特点:无状态 (没有响应式数据),也没有实例 (没有 this 上下文)
可以使用数据
官网列出了函数式组件中可以使用的东西
根据官网我全部列出了参数
因为有一些参数有循环引用,JSON无法解析,所以我打印在控制台上面
下面是组件的源码
<template functional>
<div>
<el-row :gutter="20">
<el-col :span="5">props:提供所有 prop 的对象</el-col>
<el-col :span="19">{{props}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">children:VNode 子节点的数组</el-col>
<el-col :span="19">{{props.showChildren(children)}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">slots:一个函数,返回了包含所有插槽的对象</el-col>
<el-col :span="19">{{props.showSlots(slots())}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。</el-col>
<el-col :span="19">{{scopedSlots}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件</el-col>
<el-col :span="19">{{data}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">parent:对父组件的引用</el-col>
<el-col :span="19">
<span>
{{props.showParent}}
</span>
{{props.showParent(parent)}}
</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。</el-col>
<el-col :span="19">{{listeners}}</el-col>
</el-row>
<el-divider></el-divider>
<el-row :gutter="20">
<el-col :span="5">injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。</el-col>
<el-col :span="19">{{props.showInjections(injections)}}</el-col>
</el-row>
<el-divider></el-divider>
</div>
</template>
<script lang="ts">
// @ts-nocheck
export default {
name: 'FunGetData',
props:{
showParent:{
type: Function,
default:(val)=>{
console.log('showParent',val)
return '66666'
}
},
showInjections:{
type: Function,
default:(val)=>{
console.log('showInjections',val)
return '66666'
}
},
showChildren:{
type: Function,
default:(val)=>{
console.log('showChildren',val)
return '66666'
}
},
showSlots:{
type: Function,
default:(val)=>{
console.log('showSlots',val)
return '66666'
}
},
showValue: {
type:String,
default: '5555'
}
},
inject:['testData']
}
</script>
<style scoped lang="scss">
</style>
父级组件
<template>
<div class="funcComIndex">
<el-card>
<h1>函数单文件</h1>
<p><a href="https://v2.cn.vuejs.org/v2/guide/render-function.html#函数式组件" target="_blank">函数式组件</a></p>
</el-card>
<el-card>
<h1>可以获取的数据</h1>
<FunGetData>
<div>test</div>
</FunGetData>
</el-card>
<el-card>
<h1>ref</h1>
<p>这个ref应该写在函数组件内部,函数组件自己是没有实例的,所以获取的ref都是函数组件里面带有实例的</p>
<FunRef refs="FunRefs"></FunRef>
</el-card>
<el-card>
<h1>递归</h1>
<Recursion
:count="1"
:flood="3"
></Recursion>
</el-card>
</div>
</template>
<script lang="ts">
// @ts-nocheck
import FunGetData from './FunGetData'
import FunRef from './FunRef'
import Recursion from './Recursion'
export default {
name: "FuncCom",
components:{
FunRef,
FunGetData,
Recursion,
},
data(){
return {
data: '6666'
}
},
provide(){
return {
testData: this.data
}
},
methods:{
}
}
</script>
<style scoped lang="scss">
.funcComIndex{
color: blue;
}
.FunGetData{
color: red;
}
</style>
一开始我以为children就是slot,但是官网有解释
控制台打印出来的数据也是如此
小提示
函数式组件的props也是可以有默认值的
实例引用ref
父组件都是上面提到的父组件
比如想引用这个组件调用方法,这个ref怎么用?
这个官网没有提到,就比如下面的这个组件我想引用里面这个元素怎么办?
<template functional>
<div :ref="props.refs">
我是funRef函数式组件: {{props.refs}}
</div>
</template>
<script lang="ts">
// @ts-nocheck
export default {
props:{
refs:{
type:String,
default: ''
}
}
}
</script>
<style scoped lang="scss">
</style>
一开始我是这样写的
<FunRef ref="FunRef"></FunRef>
在refs中没有FunRef这个引用,绝了
后来我在组件里面写了一个,不过现在这里我是通过props传入名字,也是一样的,props不能是ref,这个ref就像关键词一样,会不生效,所以我写了一个refs传入进去 ̄□ ̄||
<FunRef refs="FunRefs"></FunRef>
在组件引用中就出现了
这个就完全实现了我想要减少vue层级的功能
样式-class
我只在父级写了样式
发现编译出来的data-v是一样的,我在想这样是不是样式就是要写在一起
事实证明是可以写在一起的
但是如果你在组件里面也写了样式
这个data-v就变了,也就是说这个函数式组件可以写独立的样式
递归
<template functional>
<div :ref="'count'+props.count">
这是递归:层级{{props.count}}
<Recursion
v-if="props.count < props.flood"
:flood="props.flood"
:count="props.count+1"
></Recursion>
</div>
</template>
<script lang="ts">
// @ts-nocheck
export default {
name: 'Recursion',
props: {
count: {
type: Number,
default: 3
},
flood:{
type:Number,
default: 3
}
}
}
</script>
<style scoped lang="scss">
</style>
递归也是完全可以使用的
层级再多,这个$refs也是挂载在父级中,非常的好用
总结
利用函数式组件的这些特性,我们封装组件就可以减少vue层级,也就是减少$refs的个数就可以拿到对应的实例,
比如:
page--》vue1---》vue3---》vue2
功能上面vue2其实就是展示vue1的数据,用vue1的数据进行双向绑定,但是vue2比较麻烦我就用vue3包装了一下,这个时候我要拿vue2,我就要这样:
page.$refs.vue1.$refs.vue3.$refs.vue2
如果vue3是一个函数式组件,我就可以这样写
page--》vue1---》vue3---》vue2
page.$refs.vue1.$refs.vue2
非常的快乐
最后
欢迎关注公众号致心空间:O(∩_∩)O😁