Function Component trong Vue

Không được xuất chúng như là function component của React, nên function component trong Vue không có nhiều người để ý. Hy vọng tương lai nó sẽ được nâng cấp để cạnh tranh với bên React đang quảng bá quá rầm rộ.

Function Component trong Vue là gì

Component không chứa state và không có instance, không thể tham chiếu đến chính nó bằng từ khóa this

// dùng vue template
<template functional>
	<div>...</div>
</template>
// dùng render function
<script>
export default {
	functional: true,

	render(h) {
		//...
	}
}
</script>

Truy xuất dữ liệu

Nếu không có state hay instance vậy làm sao chúng ta có thể tham chiếu đến dữ liệu và phương thức? Vue cung cấp tham số context bên dưới hàm render để chúng ta truy xuất: prop, children, slot, scopedSlot, data, parent, listener, injection

<template functional>
	<div>
		{{ props.someProp }}
	</div>
</template>

<script>
export default {
	props: {
		someProp: String
	}
}
</script>
<script>
export default {
	functional: true,

	props: {
		someProp: String
	},

	render(h, ctx) {
		const someProp = ctx.props.someProp
	}
}
</script>

Attribute

attribute không được truyền xuống tự động, ví dụ như classid mặc định bị bỏ qua

<!-- src/components/ArticleTeaser.vue -->
<template>
	<UiHeadline
		id="hyphenCase(article.title)"
		class="ArticleTeaser__title"
		@click="readMore"
	>	
		{{ article.title }}
	</UiHeadline>
</template>
<!-- src/components/UiHeadline.vue -->
<template functional>
	<h1>
		<slot />
	</h1>
</template>

id, class, kể cả @click cũng không được truyền xuống. Nếu không mở source code đó ai mà biết được tại sao truyền các attribute này xuống mà nó không chạy.

Hên là có cách giải quyết, nếu bạn đã viết function component thì bạn phải chịu trách nhiệm bổ sung cách giải quyết cho nó

<template functional>
	<h1
		v-bind="data.attrs"
		v-on="listeners"
	>
		<slot />
	</h1>
</template>

Tuy nhiên, chưa xong hết được, vì class nó lại không nằm trong data.attrs

Bạn phải thông qua data.class/ data.staticClassdata.style/data.staticStyle

<!-- Đưa vào `data.class` -->
<UiHeadline :class="['my-class']"/>

<!-- Đưa vào `data.staticClass` -->
<UiHeadline class="my-class"/>
<template functional>
	<h1
		:class="[data.class, data.staticClass]"
		:style="[data.style, data.staticStyle]"
		v-bind="data.attrs"
		v-on="listeners"
	>
		<slot />
	</h1>
</template>

Kết

Thế quái nào chúng ta lại muốn viết function component, khi mà ta phải tự xử nhiều thứ quá hiển nhiên như vậy.

Anh Austin Gil ảnh có đo, thì thấy function component nó nhanh hơn chút xíu so với một component có state. Cái này theo bên React họ lại bảo bây giờ các js engine của trình duyệt nó handle dạng function và class gần như không khác nhiều

Vue.js functional components: What, Why, and When?

Working With Functional Vue.js Components

Function Component trong Vue