什么是函数式组件

函数组件是使组件无状态(没有data)和无实例(没有this上下文)。也没有生命周期方法,它只是一个接受一些 prop 的函数,他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。

函数组件的多种形式

(1)、只关注样式函数组件,可以借助template实现

单文件组件function.vue

<template functional>
    <ul>
        <slot/>
        <li v-for="item in props.list" :key="item.id" @click="props.itemClick(item)">{{item}}</li>
    </ul>
</template>

父组件使用函数组件

<BookList :list='list' :itemClick="bookSelect"><li>书籍列表</li></BookList>

slot是默认插槽,显示组件间的标签内容;这里需要知道,向组件中传递不带 v-slot 指令的子节点时,
比如 BookList 中的 <li>书籍列表</li>,这些子节点被存储在$slots.default中。

functional template的functional是函数组件的关键

(2)、函数的类组件(h)写法

声明function.js的文件,创建对象标明functional: true加上render function的形式就是函数组件,此时要省略template的语法

<script>
	export default {
    //标记为函数式组件
    functional: true,

    // props: {
    //     list: {
    //         type: Array,
    //         required: true
    //     }
    // },
    //render函数 或 function (createElement, context) {}
    render: function (h, {props, listeners, children, data}) { // context 结构出来的属性
        return(<ul>
                {children}
                {props.list.map(i => <li style="color:blue" οnclick={(event,i)=> data.attrs.itemClick(event.target.textContent)}>{i}</li>)}
        </ul>)
    },
}
</script>

函数类组件需要有一个render函数编译模板,接收两个参数;h默认编译, context提供上下文参数;详情参考文档

带有h的编译函数可以看成类似reactrender函数内写样式的规则去写样式,不需关心vdom的编写规则;

3、类写函数组件编译(createElement)

Vdom的直接实现,需要关注vdom的编写规则

通过一个展示书籍列表的完整案列来说明各个属性的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AV3scj0w-1647146964346)(/media/editor/vdom编译_20220301193903540753.png “效果分析展示”)]

export default {
    props: {
        list: {
            type: Array,
            required: true
        }
    },

    //标记为函数式组件
    functional: true,

    // 内部功能方法
    hoverli: function(e, i) {
        console.log(e, i)
    },

    //render函数 (createElement, context)
    render: function(createElement, { props, listeners, children, data }) {
        // 若不理解可以打印出来context来看看里面都有些什么东西
        // B: 规定组件的渲染规则
        function appropriateListComp() {
            //获取父组件传来的数据
            var list = props.list;
            //若空,则返回前面定义的emptylist
            if (list.length === 0) return { template: '<p>Empty list</p>' };
            //若为对象
            if (typeof list[0] === 'object') return 'ul';
            //其他
            return 'ul'
        }

        // C:
        function getChlidren() {
            let i = 0,
                books = [];
            while (i < props.list.length) {
                let index = i;
                books.push(createElement('li', {
                        attrs: {
                            class: 'li-name'
                        },
                        style: {
                            fontSize: '20px'
                        },
                        on: {
                            click: () => data.attrs.itemClick(props.list[index]),
                            // mouseover: (e)=> console.log(props.list[index])
                        }
                    }, 
                    [createElement('span', { attrs: { class: 'li-span' } }, [createElement('i', { style: { marginRight: '20px' } }, props.list[i]), createElement('strong', '金庸')])] // 第三个参数如果是Vdom那必须是数组的形式
                ));
                i++;
            }
            books.unshift(children) // 追加slot元素位置
            return books;
        }

        // A: 生成模板
        /**
         * 1.标签名
         * 2.标签属性配置
         * 3.标签子集,可以是数组或单个 Vdom
         */
        return createElement(
            // 模板标记为渲染规则函数返回值
            appropriateListComp(), {
                attrs: {
                    id: 'book-ul'
                },
                'class': {
                    foo: true,
                    bar: false
                },
            },
            // 模板子元素,返回一个数组
            getChlidren(),
        )
    },

}
  • render函数要返回一个编译的Vdom,return createElement(父类标签,父类样式以及属性、子类标签以及内容文本)参数简介
  • 以上案列可以看出,第三个参数如有使用必须是数组形式的数组且元素是符合createElement函数返回的Vdom;

注册组件
Vue.component('function-list', 函数组件)

使用组件

 <function-list :list='list' :itemClick="booklog"><li>书籍列表 <span>class createElement编译</span> </li></function-list>

原文信息

原文转载自:问我学院,问我社区
原文链接:http://www.wenwoha.com/blog_detail-1376.html

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐