vue 函数式(编程式) render (functional:true)

一、文档

(官方文档)
官网地址:https://cn.vuejs.org/api/options-rendering#render
渲染机制说明:https://cn.vuejs.org/guide/extras/rendering-mechanism
渲染函数说明:https://cn.vuejs.org/guide/extras/render-function
(个人参考文档)
如何使用:https://blog.csdn.net/ccattempt/article/details/120481481
render介绍:https://blog.csdn.net/w807139809/article/details/122106086

二、区别

同常规的vue有什么区别:
1、同等条件下,render编程式渲染速度优异,因为编程式跳过了三个阶段的转化(parser -> transform -> generate)
2、编程式缺少了传统template模板编写形式的便捷手段(通俗的讲:用起来不顺手,因为js需要与标签混着写)
3、语法完全不一样

三、使用

<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
		//render需要返回一个vNode节点
		//h函数 :参数一原生标签名、或者引入的组件名
		// 参数二:为创建的标签绑定的属性内容,可以是class类名、可以是事件、自定义属性......
		// 参数三:可以是字符串Text文本或者是h函数构建的对象再者可以是有插槽的对象。
		//context 由于没有全局的this,因此出现了context,context是一个对象,里面有很多属性如props、data......
		return h('div',{class:"contain"},[<p>render渲染</p>])
		}
	};
</script>

h函数的参数解释:

参数一:

<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
		//h函数 :参数一原生标签名、或者引入的组件名
		//div,就是普通的div元素标签名
		
		return h('div',{class:"contain"},[<p>render渲染</p>])
		}
	};
</script>
使用导入的组件名
<script>
	import HelloWorld from "./components/HelloWorld";
	export default {
		name: "patientSourceImage",
		functional: true,
		components: {
			HelloWorld,
		},
		render(h, context) {
			//HelloWorld ,导入的组件,没有引号,需要先进行组件注册
			return h(HelloWorld, { class: "contain" }, [<p>render渲染</p>]);
		},
	};
</script>

参数二:

绑定css
<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
			return h(
				"div",
				//绑定css可以通过类名。或者style属性
				{ class: "contain", style: { background: "black", color: "white" } },
				[<p>render渲染</p>]
			);
		},
	};
</script>
绑定事件
<script>
	export default {
		name: "patientSourceImage",
		data: function () {
			return {
				tt: "前端吴彦祖是tjq",
			};
		},
		functional: true,
		render: function (h, context) {
			return h(
				"div",
				{
					class: "contain",
					style: {
						background: "black",
						color: "white",
					},
					//绑定事件通过on来进行绑定,
					//~ 前缀,表示函数只执行一次
					on: {
						"~click": () => {
							alert("缓存清理成功");
						},

						mouseout: (e) => {
							console.log("鼠标移出", e);
						},
					},
				},
				[<p>{111}</p>]
			);
		},
	};
</script>
往组件里面传递参数
<script>
	import HelloWorld from "./components/HelloWorld.vue"
	export default {
		name: "patientSourceImage",
		data: function () {
			return {
				tt: "前端吴彦祖是tjq",
			};
		},
		components: {
			HelloWorld,
		},
		functional: true,
		render: function (h, context) {
			const name = "tjq";
			return h(
				HelloWorld,
				{
					class: "contain",
					props: {
						name: name,
					},
				},
				[<p>吴彦祖</p>]
			);
		},
	};
</script>
动态绑定值props

app.vue文件



<template>
	<div>
		<button @click="age++">age++</button>
		<HelloWorld :age="age"></HelloWorld>
	</div>
</template>
<script>
	import HelloWorld from "./components/HelloWorld.vue";
	export default {
		data() {
			return {
				age: 1,
			};
		},
		
		components: {
			HelloWorld,
		},
	};
</script>
<style scoped>
</style>

HelloWorld.vue

<script>
	export default {
		name: "HelloWorld",
		props: ["age"],
		data: function () {
			return {
				tt: "前端吴彦祖是tjq",
			};
		},
		functional: true,
		//解构赋值 context,取出props
		render: function (h, { props }) {
			return h(
				"div",
				{
					class: "contain",
					style: {
						background: "black",
						color: "white",
					},
				},
				[<p>{props.age}</p>]
			);
		},
	};
</script>
动态绑定值data

这里我们需要去掉functional:true

<script>
	export default {
		name: "helloworld",
		data() {
			return {
				name: "tjq",
				age: 18,
			};
		},
		render(h) {
			return h(
				"div",
				{
					on: {
						click: () => {
							this.age++; //或者使用this.$data.age $data是data的一个映射,同样的也有props的映射$props......
						},
					},
				},
				`name:${this.$data.name},age${this.age}`
			);
		},
	};
</script>
functional:true到底是做什么的?

在 Vue 中,当组件设置 functional: true 时,组件函数将被视为无状态函数组件。无状态函数组件没有实例,没有响应式数据,并且不支持实例方法和生命周期钩子函数。由于它们没有实例上下文,因此无法直接访问插槽。
因此我们上面的所有示例,可以把functional: true去掉,去掉之后我们的render函数缺少了context这一参数,但同时我们也可以调用this变量
举个例子:

动态绑定props 非functional:true版本

app.vue文件



<template>
	<div>
		<button @click="age++">age++</button>
		<HelloWorld :age="age"></HelloWorld>
	</div>
</template>
<script>
	import HelloWorld from "./components/HelloWorld.vue";
	export default {
		data() {
			return {
				age: 1,
			};
		},
		
		components: {
			HelloWorld,
		},
	};
</script>
<style scoped>
</style>

helloworld.vue文件

<script>
	export default {
		name: "HelloWorld",
		props: ["age"],
		render: function (h) {
		// render: function (h ,context) { 之前我们是content.props.age来进行获取的
			//现在多了this,我们直接this.$props即可
			console.log(this.$props.age);
			return h("div", {}, [<p>{this.$props.age}</p>]);
		},
	};
</script>

参数三:

<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
			return h(
				"div",
				//参数三,可以是一段文本,也可以是一个数组
				{},
				[<p>render渲染</p>]
			);
		},
	};
</script>
参数为文本时
<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
			return h(
				"div",
				{},
				'啦啦啦,我是前端吴彦祖'
			);
		},
	};
</script>

在这里插入图片描述

当参数为数组时
<script>
	export default {
		name: "patientSourceImage",
		functional: true,
		render(h, context) {
			return h("div", {}, [<em>我是前端吴彦祖</em>,<br/>, `<em>我是前端吴彦祖</em>`]);
		},
	};
</script>

在这里插入图片描述

当参数里面设置插槽时

上诉也提到,functional: true为无状态函数,没有插槽,因此用到插槽我们同样不能使用functional: true
app.vue文件

<template>
	<div>
		<HelloWorld >
            <p>我是前端吴彦祖</p>
            <em>我是前端吴彦祖</em>
        </HelloWorld>
	</div>
</template>
<script>
	import HelloWorld from "./components/HelloWorld.vue";
	export default {
		data() {
			return {
				age: 1,
			};
		},
		
		components: {
			HelloWorld,
		},
	};
</script>
<style scoped>
</style>

helloworld.vue文件

<script>
	export default {
		name: "helloworld",
		render(h) {
			return h(
				"div",
				{ class: "menuBox" },
				this.$scopedSlots.default()
			);
		},
	};
</script>

在这里插入图片描述

如何给插槽填写默认值

app.vue文件

<template>
	<div>
		<HelloWorld >
            <p>我是前端吴彦祖</p>
            <em>我是前端吴彦祖</em>
        </HelloWorld>
        <!-- 没写默认插槽,会使用默认值 -->
        <p>下面的用默认值<p/>
        <HelloWorld >
        </HelloWorld>
	</div>
</template>
<script>
	import HelloWorld from "./components/HelloWorld.vue";
	export default {
		data() {
			return {
				age: 1,
			};
		},
		
		components: {
			HelloWorld,
		},
	};
</script>
<style scoped>
</style>

helloworld.vue

<script>
	export default {
		name: "helloworld",
		data() {
			return {
				name: "tjq",
			};
		},
		render(h) {
			const scopedSlotFn = this.$scopedSlots.default;
			//scopedSlotFn为undefined时表示并没有传递插槽
			//如果传递了, scopedSlotFn会是一个函数,该函数的返回值是对应的插槽组件
			if (scopedSlotFn) {
				const slotVNode = scopedSlotFn();
				return h("div", [slotVNode]);
			}
			return h("div", {}, ["默认的插槽内容"]);
		},
	};
</script>

在这里插入图片描述

具名插槽

helloworld.vue文件

<script>
	export default {
		name: "helloworld",
		data() {
			return {
				name: "tjq",
			};
		},
		render(h) {
			//slots表示所有接收到的插槽
			const slots = this.$slots;
			//提前预设的插槽,default是默认插槽
			const slots_arr = ["default", "title"];
			const slot_key = Object.keys(slots).map((item) =>
				slots_arr.includes(item) ? slots[item] : null
			);
			if (slot_key.length) {
				return h("div", [...slot_key]);
			}

			return h("div", {}, ["默认的插槽内容"]);
		},
	};
</script>



或者使用下面这种写法
helloworld文件

<script>
	export default {
		name: "helloworld",
		data() {
			return {
				name: "tjq",
			};
		},
		render(h) {
		//预设哪个插槽就this.$slots[预设的插槽名]
			return h("div", {}, [this.$slots.title, this.$slots.default]);
		},
	};

app.vue

<template>
	<div>
		<HelloWorld >
            <p>我是前端吴彦祖</p>
            <em slot="title">标题插槽</em>
            <em slot="detail">没有接受这个插槽</em>
        </HelloWorld>
	</div>
</template>
<script>
	import HelloWorld from "./components/HelloWorld.vue";
	export default {
		data() {
			return {
				age: 1,
			};
		},
		
		components: {
			HelloWorld,
		},
	};
</script>
<style scoped>
</style>

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3 支持函数编程的特性,这意味着你可以在 Vue 组件中使用一些函数编程的概念和技术。下面是一些与函数编程相关的特性和用法: 1. 纯函数函数编程鼓励使用纯函数,这意味着函数的输出只依赖于输入,不会对外部环境产生副作用。在 Vue 组件中,你可以将计算属性、过滤器和方法尽量设计成纯函数,以便更好地进行单元测试和调试。 2. 函数组合:Vue 3 提供了 `compose` 函数,它可以将多个函数组合起来,形成一个新的函数。你可以使用 `compose` 来简化复杂的逻辑处理,提高代码的可读性和可维护性。 3. 高阶组件 (Higher-Order Components):在 Vue 3 中,你可以使用函数组件 (Functional Components) 来定义高阶组件。函数组件是一种纯函数,接收一个 props 对象作为参数,并返回一个 VNode。通过使用函数组件,你可以轻松地将一些常见的逻辑和功能封装成可复用的高阶组件。 4. 不可变数据:函数编程鼓励使用不可变的数据结构,这意味着数据一旦创建就不能被修改。在 Vue 3 中,你可以使用 `ref` 和 `reactive` 来创建响应的数据,但是不能直接修改它们的值。如果需要修改数据,应该通过使用特定的方法或函数来产生新的数据。 5. 组件复用:函数编程鼓励组件的复用性,你可以将一些通用的功能封装成可复用的函数或组件,并在不同的地方进行使用。Vue 3 中的函数组件和高阶组件是实现组件复用的一种方。 这些是 Vue 3 中支持函数编程的一些特性和用法,希望对你有所帮助!如果还有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值