Vue.js提供了一个functional的布尔值选项,设置为true可以使组件无状态和无实例,也就是没有data和this上下文。如许用render函数返回假造节点可以更轻易渲染,由于函数化组件只是一个函数,渲染开销要小很多。
利用函数化组件时,Render函数提供了第二个参数context来提供临时上下文。组件需要的data、props、slots、children、parent都是通过这个上下文来转达的,比如this.level要改写为context.props.level, this.$slots.default改写为context.children。
比方,下面的示例用函数化组件展示了一个根据数据智能选择差异组件的场景:
<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; // 判断prop: data的type字段是属于哪种范例的组件 if (data.type === 'img') return ImgItem; if (data.type === 'video') return VideoItem; return TextItem; } return createElement( getComponent(), { props: { //把smart-item的prop: data传给上面智能选择的组件 data: context.props.data } }, 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: 'https://raw.githubusercontent.com/iview/iview/master/assets/logo.png' } } else if (type === 'video') { this.data = { type: 'video', url: 'http://vjs.zencdn.net/v/oceans.mp4">http://vjs.zencdn.net/v/oceans.mp4' } } else if (type === 'text') { this.data = { type: 'text', content: ’这是一段纯文本’ } } } }, created: function () { // 初始化时,默认设置图片组件的数据 this.change('img'); } }) </script>代码片断比力长,渐渐分析一下实现的内容。ImgItem、VideoItem、TextItem这3个对象分别是图片组件、视频组件和纯文本组件的选项,它们都吸取一个prop:data。在函数化组件smart-item里,也有props:data,通过getComponent函数来判断其字段type的值,选择这条数据得当渲染的组件。通过createElement把getComponent()返回的对象设置为第一个参数,然后通过第二个参数把smart-item的data转到达选择的组件里的prop:data,组件渲染出差异的内容。
根实例app中的方法change用来天生差异的数据,通过3个button来切换。
该示例难明确的地方在于smart-item和3个功能组件都有prop:data,它们的转达序次和原理看起来比力暗昧。
函数化组件在业务中并不是很常用,而且也有其他类似的方法来实现,比如上例也可以用组件的is特性来动态挂载。总结起来,函数化组件重要实用于以下两个场景:
● 步伐化地在多个组件中选择一个。
● 在将children, props,data转达给子组件之前操纵它们。 |