vue - render 参数详解

父组件

<template>
   <div>
      <vueRender msg="Render Test" :level="3" :items="items">
	 <div class="header">default header</div>
	 <p slot="header">slot header</p>
      </vueRender>   
   </div>
</template>

<script>
import vueRender from './vue-render.vue'
export default {
    name: 'app',
    components: { vueRender },
    data() {
      return {
	items: [{
	  name: 'hello'
	},
	{
	  name: 'vue'
        },
	{
	  name: 'js'
	}]
     }
   }
}
</script>

<style>
</style>

子组件

<template>
	<div class="render">
		<h1>{{ msg }}</h1>
		<renderComponent></renderComponent>
		<renderComponentList></renderComponentList>
	</div>
</template>

<script>
	export default {
		name: 'RenderTest',
		props: {
			msg: String,
			level: {
				type: Number,
				required: true
			},
			items: {
				type: Array,
				required: false
			}
		},
		components: {
			renderComponent: {
				/**
				 * render: 渲染函数
				 * 参数: createElement
				 * 参数类型: Function
				 */
				render: function(createElement) {
					let _this = this['$options'].parent // 我这个是在 .vue 文件的 components 中写的,这样写才能访问this
					let _header = _this.$slots.header // // $slots: vue中所有分发插槽,不具名的都在default里
					/**
					 * createElement 本身也是一个函数,它有三个参数
					 * 
					 * 返回值: VNode
					 * 
					 * 1. 一个 HTML 标签字符串,组件选项对象,或者解析上述任何一种的一个 async 异步函数。必需参数。{String | Object | Function} - 就是你要渲染的最外层标签
					 * 
					 * 2. 一个包含模板相关属性的数据对象你可以在 template 中使用这些特性。可选参数。{Object} - 1中的标签的属性
					 * 
					 * 3. 子虚拟节点 (VNodes),由 `createElement()` 构建而成,也可以使用字符串来生成“文本虚拟节点”。可选参数。{String | Array} - 1的子节点,可以用 createElement() 创建,文本节点直接写就可以
					 */
					return createElement(
						'h' + _this.level, // 标签名称 - 第一个参数
						{
							style: {
								color: 'gray',
								border: '1px solid pink'
							},
							class: { // 样式类名 例如 cassname就是样式类名
								cassname: true
							},
							// 正常的 HTML 特性
							attrs: {
								id: 'foo'
							},
							// 组件 props
							props: {
								myProp: 'bar'
							},
							// DOM 属性
							domProps: {
								innerHTML: 'baz',
								value: '' // input select 
							},
							//  事件监听器基于 `on`
							on: { // 绑定事件
								click: () => {
									console.log('点击事件')
								},
								input: (event) => { // 用于input
									self.$emit('input', event.target.value)
								}
							},
							// 仅对于组件,用于监听原生事件,而不是组件内部使用
							// `vm.$emit` 触发的事件。
							nativeOn: {
								click: this.nativeClickHandler
							},
							// 自定义指令。注意,你无法对 `binding` 中的 `oldValue`
							// 赋值,因为 Vue 已经自动为你进行了同步。
							directives: [
								{
									name: 'my-custom-directive',
									value: '2',
									expression: '1 + 1',
									arg: 'foo',
									modifiers: {
										bar: true
									}
								}
							],
							// Scoped slots in the form of
							// { name: props => VNode | Array<VNode> }
							scopedSlots: {
								default: props => createElement('span', props.text)
							},
							// 如果组件是其他组件的子组件,需为插槽指定名称
							slot: 'name-of-slot',
							// 其他特殊顶层属性
							key: 'myKey',
							ref: 'myRef'
						}, // 第二个单数
						[
							'text', // 文本节点直接写就可以
							_this.$slots.default, // 默认插槽
							createElement('div', _header)   // 具名插槽  createElement()创建的VNodes
						] // 子元素数组 - 第三个参数 也可以直接  文本'text'
					)
				}
			},
			renderComponentList: {
				render: function(createElement) {
					let _this = this['$options'].parent
					if (_this.items.length) {
						return createElement(
							'ul',
							_this.items.map(function(item) {
								return createElement('li', item.name)
							})
						)
					} else {
						return createElement('p', 'No items found.')
					}
				}
			}
		}
	}
</script>

posted @ 2020-08-28 22:17  一城柳絮吹成雪  阅读(2215)  评论(0编辑  收藏  举报