Vue的函数化组件

函数化组件

Vue.js提供了一个 functional 的布尔值选项,设置为true可以使组件无状态和无实例,也就是没有 datathis上下文。

好处:只是一个函数,渲染开销要小很多。

使用函数化组件时,Render 函数提供了第二个参数 context 来提供临时上下文。 组件需要的datapropsslotschidrenparent 都是通过这个上下文来传递的。

------- 这里插一段createElement的用法 ------

createElement(
	// {String | Object | Function}
	// 一个 HTML 标签,组件选项,或是一个函数
	// 必须 Return 上述其中一个
	'div',
	// {Object}
	// 一个对应属性的数据对象,可选
	{
		//	比如:
		// attrs: {} 正常的HTML特性
		// props: {} 组件props
		// domProps: {} DOM属性
		// on: {} 自定义事件监听器“on”
	},
	// {String | Array}
	[
		createElement('h1', 'hello world'),
		createElement(MyComponent, {
			props: {
				someProps: 'foo'
			}
		})
	]
)

------------- 分割线 -------------

函数化组件实例:

<div id='app'>
	<smart-item :data="data">smart-item>
	<button @click="change('img')">切换为图片组件button>
	<button @click="change('video')">切换为视频组件button>
	<button @click="change('text')">切换为文本组件button>
div>
<script>
    // 图片组件选项
    var ImgItem = {
        props: ['data'],
        render: function (createElement) {
            return createElement('div', [
                createElement('p', '图片组件'),
                createElement('img', {
                    attrs: {
                        src: this.data.url
                    }
                })
            ]);
        }
    };

    // 视频组件选项
    var VideoItem = {
        props: ['data'],
        render: function (createElement) {
            return createElement('div', [
                createElement('p', '视频组件'),
                createElement('video', {
                    attrs: {
                        src: this.data.url,
                        controls: 'controls',
                        autoplay: 'autoplay'
                    }
                })
            ]);
        }
    };

    // 纯文本组件选项
    var TextItem = {
        props: ['data'],
        render: function (createElement) {
            return createElement('div', [
                createElement('p', '纯文本组件'),
                createElement('p', this.data.text)
            ]);
        }
    };

    Vue.component('smart-item', {
        // 函数化组件
        functional: true,
        render: function (createElement, context) {
            // 根据传入的数据,智能判断显示哪种组件
            function getComponent() {
                var data = context.props.data;
                // 判断 props: data的type字段是属于哪种类型的组件
                if (data.type === 'img') return ImgItem
                if (data.typev === 'video') return VideoItem
                return TextItem;
            }

            return createElement(
                getComponent(),
                {
                    props: {
                        // 把 smart-item 的prop: data 传给上面智能选择的组件
                        data: context.props.data
                    }
                },
                // 即原来的 this.$slot.default
                context.children
            )
        },
        props: {
            data: {
                type: Object,
                required: true
            }
        }
    });

    var app = new Vue({
        el: '#app',
        data: {
            data: {}
        },
        methods: {
            // 切换不同类型组件的数据
            change: function (type) {
                if (type === 'img') {
                    this.data = {
                        type: 'img',
                        url: ''
                    }
                } else if (type === 'video') {
                    this.data = {
                        type: 'video',
                        url: ''
                    }
                } else if (type === 'text') {
                    this.data = {
                        type: 'text',
                        context: '这是一段文本'
                    }
                }
            }
        },
        created: function () {
            this.change('img')
        }
    })
script>

函数化组件在业务中并不是很常用,主要适用于以下两个场景:

  1. 程序化地在多个组件中选择一个。
  2. 在将children, props, data 传递给子组件之前操作它们。

你可能感兴趣的:(vue)