Component phần 6: Tổng kết và hệ thống hóa lại về UI Builder, Web Component và React

I am a developer, I write blogs occasionally. I hope you will find something new when reading my blogs.
Fonts, Sizes và Colors
Vì chúng ta sẽ làm việc trực tiếp trên Wordpress + Elemetor nên bước này cả 3 sẽ giống nhau:
Vào Site settings và cài đặt Global Colors để dùng cho Elementor
Tạo global style trong Custom CSS để dùng CSS variable cho Web Component và React (có thể dùng inspect để check CSS variable của Elementor luôn).
Trường hợp design sử dụng font custom, upload file font lên transfronter và copy code về cho vào Custom HTML.
Tạo và lưu component để dùng cho nhiều trang
| UI Builder | Web component | React Component |
| Save as Template | Tạo block code khai báo Component và save template | Tạo block code khai báo Component và save template |
| Save as Default |
Gọi component ra sử dụng
Đối với Web component và React component, cái phần lưu Template sẽ chỉ là phần khai báo, còn việc gọi ra sẽ thực hiện ở App Logic (tạo 1 block code), lúc này component đã có sẵn ở biến JS.
Với UI Builder thì khác 1 chút vì phần lưu Template sẽ bao gồm cả render luôn, nên có 2 cách xử lý:
Sau khi gọi template ra, dùng JS để lưu HTML sau đó xóa block template đó đi.
hoặc có thể đặt tag của block Container là
<template />, mặc định code trong thẻ này sẽ k hiển thị. Lưu ý: Cái này chỉ được áp dụng sau khi có chỉnh sửa vào plugin elements để cho block Container nhận thêm tag. Cùng xem cách sử dụng của<template />
Giờ áp dụng vào lại bài lần trước ta sẽ có hướng xử lý gọn gàng hơn chút như sau:
%[https://www.youtube.com/watch?v=3OwSI92m4t4]
Cái hay của <template /> là nó có thể tự chạy javascript trong thẻ <script />, nên chúng ta không cần phải chạy function rerunHTMLScript nữa.
Quản lý state
UI Builder: dùng function
useState.statecần được đồng bộ vớidata attribute.Web component: dùng
this.setState.statecũng cần được đồng bộ vớidata attributeReact: dùng
useStatevới React function vàthis.setStatevới React class, không cần dùng attribute và có thể dùngpropsthay thế
Quản lý render
UI Builder: đồng bộ giữa
data attributeở parent với giao diện, khi data attribute đổi thì giao diện cũng đổi. setinnerHTMLdùngtemplate stringđể chèn state, cẩn thận khi sử dụnginnerHTMLvì sẽ xuất hiện nháy. Khi bị nháy thì chuyển sang set attribute bằng JS. Loop qua state để render hàng loạt dùngtemplateEl.contentđể tạo node vàappendChild.Web compoment: cũng set
innerHTMLdùngtemplate stringđể chèn state, cũng cẩn thận khi sử dụnginnerHTML, nếu bị nháy thì chuyển sang dùngmapStateRender. Loop qua state để render hàng loạt component con thì đơn giản hơn vì chỉ cần chèn thẳng tag của thằng component con vào là đc, không cần dùng<template />.React: return thẳng mã html mà không sợ bị nháy (JSX). loop của state để render hàng loạt component con bằng việc dùng trực tiếp
.maptừ biến.
Quản lý listener
UI Builder: khai báo listener của phần tử bên trong component ở
render. thông báo ra bên ngoài bằng cách update attributeevent-*. bên ngoài listen bằngonAttributeChange.Web component: cũng khai báo listener của phần tử bên trong ở
render. Viết thẳng method vào class và gọi thẳng từ element sau khi đã querySelector. VD:const inputElement = document.querySelector('input-component'); inputElement.onEnter = () => {};React: Viết thẳng trực tiếp trong code JSX. Báo ra ngoài component bằng
props. VD:<Input onEnter={() => {}} />.
Style
UI Builder: Dùng trực tiếp UI Builder tạo giao diện, có thể dùng thêm Custom CSS ở tab Advance. Hoặc tạo hẳn 1 block HTML để style thêm bằng code CSS.
Web component: viết
renderCSSContainervà viếtrenderStyleđể dùng trongrender. Luôn ghi nhớ các code CSS bên ngoài component sẽ k tác động đến các phần tử bên trong component.React: có thể đặt
classNameđể nhận style bằng class, hoặc viết thẳng style vào qua object style. VD:<div style={{ backgroundColor: 'white' }} />. Lưu ý style này sẽ viết theo kiểu style của JS DOM (camel case). VD:const divEL = document.querySelector('div'); divEL.style.backgroundColor = 'white';.
Cách để các loại giao diện giao tiếp với nhau
Vì bản chất tất cả đều dùng để làm giao diện, nên cuối cùng chúng sẽ đề được render thành các tag HTML. Do đó, cách chung nhất để giao tiếp với nhau là thông qua attribute:
dùng
getAttribute,setAttributeđể đọc, ghi giá trị. vớidata attributethì dùng.datasetcho tiện.dùng
onAttributeChangeđể listen thay đổi.các event xảy ra bên trong component cũng nên thông báo thông qua attribute
event-*
Với React thì để đồng bộ giữa attribute và state thì chúng ta dùng code sau:
const { useEffect, useState, useRef } = React;
const useAttrState = (initialState, arrayOfDataAttr) => {
const [state, setState] = useState({});
const stateRef = useRef(state);
const getState = () => stateRef.current;
const elementRef = useRef(null);
useEffect(() => {
mapDataAttributeToState(
elementRef.current,
getState,
setState,
arrayOfDataAttr
);
}, []);
useEffect(() => {
stateRef.current = state;
}, [state]);
return [state, setState, elementRef];
}
const Task = () => {
const [state, setState, elementRef] = useAttrState({
text: '',
important: '0',
subtask: '0',
type: 'unfinished',
}, ['text', 'important', 'subtask', 'type']);
return (
<div ref={elementRef}>...</div>
)
};
Lưu ý:
Nếu chỉ giao tiếp giữa các React component với nhau thì k cần dùng đến attribute mà dùng props. props nó như kiểu 1 loại Virtual attribute, sẽ không thể hiện ra tag html
attribute phần lớn chỉ nhận dữ liệu là string, trong khi props có thể nhận mọi loại biến JS. có thể nhận cả function (do đó có thể gắn listener trực tiếp vào).
đoạn code trên thì chúng ta có thể khai báo
useAttrStateở common funcs và dùng đi dùng lại ở nhiều component. Đó được gọi làReact hook1 concept khá phổ biến của React để tái sử dụng logic.


