vue函数式组件

什么是函数式组件?

我们可以把函数式组件想象成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML

对于函数式组件,可以这样定义:

  • Stateless(无状态):组件自身是没有状态的
  • Instanceless(无实例):组件自身没有实例,也就没有this

由于函数式徐建拥有拥有这两个特性,我们就可以把它用作高阶组件(High order components),所谓高阶,就是可以生成其他组件的组件。

函数式组件的特点

没有管理任何状态
没有监听任何传递给它的状态
没有生命周期方法
只接收一些prop的函数

函数式组件的优点

渲染开销低,因为函数式组件只是函数

为什么要使用函数式组件

速度快

因为函数式组件没有状态,所以我们不需要像vue的响应式 系统一样需要经过额外的 初始化。

函数式组件任然会对响应的变化 做出响应式变化,比如新传入props,但是在组件本身中,它无法知道数据什么时候发生变化,因为它不维护自身状态。

对于大型应用程序,在使用函数式组件之后,你会看到DOM的渲染和更新会有很大的改进。

函数式组件的适用场景

函数式组件可能不适用很多情况。因为使用JavaScript框架的目的是构建响应式的应用程序

适用场景:

  • 一个简单的展示组件,也就是所谓的dumb组件,例如button组件,pills,tags,cards,甚至整个页面都是静态文本,比如about页面
  • “高阶组件”用于接收一个组件作为参数,返回一个被包装过的组件
  • v-for循环中每项通常都是很好的候选项。

functional:true加上render function,就是一个简单的函数式组件了

demo:

创建一个functionButton.js的函数式组件:

1 export default {
2     name: 'functional-button',
3     functional: true,
4     render(createElement, context) {
5         return createElement('button', 'click me')
6     }
7 }

函数式组件没有this,参数就靠context来传递

context的属性:

  • props
  • children
  • slots(a slots object)
  • parent
  • listeners
  • injections
  • data

其中上面的data包含了其他属性的引用,nibility。

现在创建一个App.vue来引入上面的函数式组件

1 <template>
2     <FunctionalButton>
3         click me
4     </FunctionButton>
5 </template>

上面的click me就是FunctionButton.js的children属性,我们可以把组件改造下,有App.vue来定义组件的button按钮

1 export default {
2     name: 'funtional-button',
3     functional: true,
4     render(createElement, { children }) {
5         return createElement('button', children)
6     }
7 }

上面用了ES6参数的解构,用{children}来代替context

事件定义

函数式组件没有实例,事件只由父组件传递。下面在app.vue上定义一个最简单的click事件。

1 <template>
2   <FunctionalButton @click="log">
3     Click me
4   </FunctionalButton>
5 </template>

对应的functionButton.js

 1 export default {
 2   functional: true,
 3   render(createElement, { props, listeners, children }) {
 4     return createElement(
 5       'button',
 6       {
 7         attrs: props,
 8         on: {
 9           click: listeners.click
10         }
11       },
12       children
13     );
14   }
15 }

简单写法

vue中设计的api比较人性化,我们可以将props、listeners统一集中在data中。

1 export default {
2   functional: true,
3   render(createElement, { data, children }) {
4     return createElement( 'button', data, children );
5   }
6 }
1 createElement('button', data, ['hello', ...children])

 

自己测试代码:

 

 

 页面:

 

 

 

 打印出来的数据

 

 

 父通过v-bind传给子组件的,基本数据类型能在props中拿到,但是复杂数据类型Array,Object,Function就会在data中的attrs中拿到

父通过v-on传给子组件的事件能在render中context中data.on和listeners中拿到并通过元素的on+事件可以触发

贴上代码

parent.vue

 1 <template>
 2   <div>
 3     <Child
 4       v-bind="{
 5         name,
 6         age,
 7         sex,
 8         infos,
 9         infos5,
10         obj: { name: 'jackals', age: 32 },
11         arr: [1, 2, 3]
12       }"
13       v-on="{infos2, infos3, infos4}"
14     />
15   </div>
16 </template>
17 
18 <script>
19 import Child from 'components/exersize1/Child'
20 export default {
21   components: {
22     Child
23   },
24   data() {
25     return {
26       name: 'jackal',
27       age: 20,
28       sex: 'man'
29     }
30   },
31   methods: {
32     infos() {
33       console.log('print', this.name, this.age)
34     },
35     infos2() {
36       console.log('infos2')
37     },
38     infos3() {
39       console.log('infos3')
40     },
41     infos4() {
42       console.log('infos4')
43     },
44     infos5() {
45       console.log('infos5')
46     }
47   }
48 }
49 </script>
50 
51 <style>
52 </style>

child.vue

 1 <script>
 2 export default {
 3   name: 'TextChild',
 4   functional: true,
 5   props: {
 6     name: {
 7       type: String,
 8       default: ''
 9     },
10     age: {
11       type: Number
12     },
13     sex: {
14       type: String,
15       default: ''
16     }
17   },
18   render(h, context) {
19     const { props: { name, age, sex }, data: { attrs: { infos }, on: { infos2, infos3, infos4 }}} = context
20     console.log('conteext', context)
21     return (
22       <div>
23         <div>
24           <p onClick={infos}>name: { name }</p>
25           <p>age: { age }</p>
26           <p>sex: { sex }</p>
27         </div>
28         <div>
29           <p onClick={infos2}>测试1:infos2</p>
30           <p onClick={infos3}>测试2:infos3</p>
31           <p onClick={infos4}>测试3:infos4</p>
32         </div>
33       </div>
34     )
35   }
36 }
37 </script>

部分来自https://blog.csdn.net/time141/article/details/121927589

posted @ 2022-09-08 23:27  强者之途  阅读(492)  评论(0编辑  收藏  举报
/* 看板娘 */