CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.
Bài viết blog CFSDN này phân tích quá trình biên dịch Remax framework sử dụng React để viết các chương trình nhỏ (được khuyến khích) Tác giả sưu tầm và biên soạn. Nếu bạn quan tâm tới bài viết này thì nhớ like nhé.
Remax là một framework mã nguồn mở được phát triển bởi Ant, sử dụng React để phát triển các chương trình nhỏ. Nó áp dụng một giải pháp không có hạn chế về cú pháp trong thời gian chạy. Nghiên cứu tổng thể chủ yếu được chia thành ba phần: nguyên tắc thời gian chạy, nguyên tắc kết xuất mẫu và quá trình biên dịch. Sau khi xem hầu hết các bài viết hiện có, chúng chủ yếu tập trung vào nguyên tắc thời gian chạy và kết xuất mẫu của Reamx, trong khi toàn bộ mã React được biên dịch. thành một phần nhỏ mà tôi chưa thấy phần giới thiệu quy trình của chương trình, vì vậy bài viết này ở đây để lấp đầy khoảng trống này. Để biết nguyên tắc hiển thị mẫu, hãy đọc bài viết này: http://www.zzvips.com/article/229724.html Để biết nguyên tắc thời gian chạy remax, hãy đọc bài viết này: http://www.zzvips.com/article/229723 .html Giới thiệu về trình kết xuất tùy chỉnh React, hãy đọc bài viết này: http://www.zzvips.com/article/229725.html.
Cấu trúc cơ bản của Remax:
1. Khi chạy remax-runtime, nó cung cấp trình kết xuất tùy chỉnh, đóng gói các thành phần máy chủ và trình tạo cấu hình cho Ứng dụng, Trang và Thành phần từ các thành phần React đến các chương trình nhỏ.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
xuất khẩu {
mặc định
như render } từ
'./kết xuất'
;
xuất khẩu {
mặc định
như createAppConfig } từ
'./createAppConfig'
;
xuất khẩu {
mặc định
như createPageConfig } từ
'./createPageConfig'
;
xuất khẩu {
mặc định
như createComponentConfig } từ
'./createComponentConfig'
;
xuất khẩu {
mặc định
như createNativeComponent } từ
'./createNativeComponent'
;
xuất khẩu {
mặc định
như createHostComponent } từ
'./createHostComponent'
;
xuất {createPortal} từ
'./Cổng thông tin phản hồi'
;
xuất { RuntimeOptions, PluginDriver } từ
'@remax/khung-chia-sẻ'
;
xuất khẩu * từ
'./móc'
;
nhập { ReactReconcilerInst } từ
'./kết xuất'
;
xuất const unstable_batchedUpdates = ReactReconcilerInst.batchedUpdates;
xuất khẩu
mặc định
{
không ổn định_batchedUpdates,
};
|
2. Mẫu bộ điều hợp liên quan đến applet remax-wechat có liên quan đến mẫu mẫu. Để biết các nguyên tắc xử lý và nguyên tắc liên quan đến mẫu, bạn có thể xem mẫu này http://www.zzvips.com/article/145552.htm / / Các mẫu liên quan đến hiển thị src/api Thích ứng với các API toàn cầu khác nhau liên quan đến các chương trình mini WeChat và một số đã được hứa hẹn.
?
1
2
3
4
5
6
7
8
9
|
nhập {promisify} từ
'@remax/khung-chia-sẻ'
;
khai báo const wx: WechatMiniprogram.Wx;
xuất const canIUse = wx.canIUse;
xuất const base64ToArrayBuffer = wx.base64ToArrayBuffer;
xuất const arrayBufferToBase64 = wx.arrayBufferToBase64;
xuất khẩu const getSystemInfoSync = wx.getSystemInfoSync;
xuất khẩu const getSystemInfo = promisify(wx.getSystemInfo);
|
src/types/config.ts Điều chỉnh nội dung cấu hình liên quan đến Trang và Ứng dụng của chương trình mini.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
xuất giao diện PageConfig {
navigationBarBackgroundColor?: chuỗi;
Kiểu văn bản thanh điều hướng?:
'đen'
|
'trắng'
;
xuất giao diện AppConfig {
trang: string[];
cửa sổ?: {
navigationBarBackgroundColor?: chuỗi;
Kiểu văn bản thanh điều hướng?:
'trắng'
|
'đen'
;
|
src/types/comComponent.ts Điều chỉnh các thuộc tính công khai, sự kiện và các thuộc tính khác liên quan đến các thành phần tích hợp của WeChat.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
nhập * như React từ
'phản ứng'
;
giao diện xuất khẩu BaseProps {
tập dữ liệu chỉ đọc?: DOMStringMap;
id?: chuỗi;
className?: chuỗi;
phong cách?: React.CSSProperties;
ẩn?: boolean;
hoạt hình?: Mảng>;
onTap?: (sự kiện: TouchEvent) => void;
onClick?: (sự kiện: TouchEvent) => void;
onTouchStart?: (sự kiện: TouchEvent) => void;
|
src/hostComponents là cách đóng gói và điều chỉnh các thành phần máy chủ chương trình mini WeChat. node.ts là thông số kỹ thuật để điều chỉnh các thuộc tính liên quan đến chương trình mini cho React.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
xuất khẩu const alias = {
nhận dạng:
'nhận dạng'
,
Tên lớp:
'lớp học'
,
phong cách:
'phong cách'
,
hoạt hình:
'hoạt hình'
,
nguồn:
'nguồn'
,
vòng lặp:
'vòng lặp'
,
điều khiển:
'điều khiển'
,
áp phích:
'áp phích'
,
tên:
'tên'
,
tác giả:
'author'
,
onError:
'ràng buộc'
,
trênPlay:
'trò chơi ràng buộc'
,
onPause:
'phá vỡ ràng buộc'
,
onTimeCập Nhật:
'cập nhật thời gian liên kết'
,
đã kết thúc:
'bị ràng buộc'
,
};
xuất const props = Object.values(alias);
|
Nhiều thành phần khác nhau cũng được tạo bằng createHostComponent.
?
1
2
3
4
5
|
nhập * như React từ
'phản ứng'
;
nhập {createHostComponent} từ
'@remax/thời gian chạy'
;
xuất khẩu const Âm thanh: React.ComponentType = createHostComponent(
'âm thanh'
);
|
createHostComponent tạo Phần tử của React.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
nhập * như React từ
'phản ứng'
;
nhập { RuntimeOptions } từ
'@remax/khung-chia-sẻ'
;
xuất khẩu
mặc định
chức năng
createHostComponent(tên: chuỗi, thành phần?: React.ComponentType ) {
nếu như
(thành phần) {
trở lại
thành phần;
}
const Thành phần = React.forwardRef((props, ref: React.Ref) => {
const { trẻ em = [] } = đạo cụ;
hãy để phần tử = React.createElement(tên, { ...props, ref }, children);
phần tử = RuntimeOptions.get(
'pluginDriver'
).onCreateHostComponentElement(phần tử) là React.DOMElement;
trở lại
yếu tố;
});
trở lại
Tùy chọn thời gian chạy.get(
'pluginDriver'
).onCreateHostComponent(Thành phần);
}
|
3. Theo mô tả chính thức, remax-macro là một macro dựa trên babel-plugin-macro; cái gọi là macro là sự thay thế tĩnh của các chuỗi trong quá trình biên dịch và Javascript không có quy trình biên dịch như cách babel triển khai macro. là biên dịch mã thành cây ast Sau đó, cây cú pháp ast được vận hành để thay thế mã gốc. Bạn có thể tìm thấy các bài viết chi tiết tại đây https://zhuanlan.zhihu.com/p/64346538; remax ở đây sử dụng macro để thay thế một số macro, chẳng hạn như useAppEvent và usePageEvent, v.v., được nhập từ remax/runtime.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
nhập {createMacro} từ
'babel-plugin-macro'
;
nhập createHostComponentMacro từ
'./createHostComponent'
;
nhập requirePluginComponentMacro từ
'./requirePluginComponent'
;
nhập requirePluginMacro từ
'./yêu cầuPlugin'
;
nhập usePageEventMacro từ
'./usePageEvent'
;
nhập useAppEventMacro từ
'./useAppEvent'
;
chức năng
remax({ tham chiếu, trạng thái }: { tham chiếu: { [tên: chuỗi]: NodePath[] }; trạng thái: bất kỳ }) {
tham chiếu.createHostComponent?.forEach(đường dẫn => createHostComponentMacro(đường dẫn, trạng thái));
tham chiếu.requirePluginComponent?.forEach(đường dẫn => requirePluginComponentMacro(đường dẫn, trạng thái));
tham khảo.requirePlugin?.forEach(đường dẫn => requirePluginMacro(đường dẫn));
const importer = dấu gạch chéo (state.file.opts.filename);
Cửa hàng.appEvents.
delete
(người nhập khẩu);
Lưu trữ.pageEvents.
delete
(người nhập khẩu);
tham khảo.useAppEvent?.forEach(đường dẫn => useAppEventMacro(đường dẫn, trạng thái));
tham khảo.usePageEvent?.forEach(đường dẫn => usePageEventMacro(đường dẫn, trạng thái));
}
xuất khẩu khai báo
chức năng
createHostComponent(
tên: chuỗi,
props: Mảng
xuất khẩu khai báo
chức năng
requirePluginComponent(pluginName: chuỗi): React.ComponentType ;
xuất khẩu khai báo
chức năng
requirePlugin(pluginName: chuỗi): P;
xuất khẩu khai báo
chức năng
usePageEvent(eventName: PageEventName, gọi lại: (...params: any[]) => any): void;
xuất khẩu khai báo
chức năng
useAppEvent(eventName: AppEventName, gọi lại: (...params: any[]) => any): void;
xuất khẩu
mặc định
tạoMacro(remax);
|
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
nhập * như t từ
'@babel/loại'
;
nhập { dấu gạch chéo } từ
'@remax/chia sẻ'
;
nhập { NodePath } từ
'@babel/traverse'
;
nhập Cửa hàng từ
'@remax/xây dựng cửa hàng'
;
nhập khẩu insertImportDeclaration từ
'./utils/insertImportDeclaration'
;
const GÓI_TÊN =
'@remax/thời gian chạy'
;
const TÊN_CHỨC_NĂNG =
'sử dụngAppEvent'
;
chức năng
getArguments(callExpression: NodePath, nhập khẩu: chuỗi) {
const args = callExpression.node.arguments;
const eventName = args[0] là t.StringLiteral;
const gọi lại = args[1];
Store.appEvents.set(người nhập khẩu, Store.appEvents.get(người nhập khẩu)?.add(eventName.value) ??
mới
Đặt([eventName.value]));
trở lại
[eventName, gọi lại];
}
xuất khẩu
mặc định
chức năng
useAppEvent(đường dẫn: NodePath, trạng thái: bất kỳ) {
const program = state.file.path;
const importer = dấu gạch chéo (state.file.opts.filename);
const functionName = insertImportDeclaration(chương trình, TÊN_CHỨC_NĂNG, TÊN_GÓI);
const callExpression = path.findParent(p => t.isCallExpression(p)) là NodePath;
const [eventName, callback] = getArguments(callExpression, trình nhập);
callExpression.replaceWith(t.callExpression(t.identifier(functionName), [eventName, callback]));
}
|
Cá nhân tôi cảm thấy thiết kế này hơi phức tạp, có thể liên quan đến thiết kế của remax/runtime, useAppEvent thực sự được xuất từ remax-framework-shared; nhưng nó cũng dạy tôi cách xử lý các sửa đổi mã. .
4. remax-cli Phần dàn dựng của remax, toàn bộ dự án remax và quá trình biên dịch tạo ra các chương trình nhỏ cũng được xử lý ở đây. Trước tiên, chúng ta hãy xem cách tệp React dưới dạng Trang được liên kết với hàm tạo Trang gốc của applet. Giả sử mã trang gốc trông như thế này, .
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
nhập * như React từ
'phản ứng'
;
nhập {Xem, Văn bản, Hình ảnh} từ
'remax/wechat'
;
nhập kiểu từ
'./index.css'
;
xuất khẩu
mặc định
() => {
trở lại
(
src=
"https://gw.alipayobjects.com/mdn/rms_b5fcc5/afts/img/A*OGyZSI087zkAAAAAAAAAAABkARQnAQ"
className={styles.logo}
mọi thứ=
"biểu tượng"
/>
Chỉnh sửa src/pages/index/index.js để bắt đầu
);
};
|
Phần này được xử lý trong mã remax-cli/src/build/entries/PageEntries.ts. Bạn có thể thấy rằng mã nguồn đã được sửa đổi và hàm createPageConfig trong thời gian chạy đã được giới thiệu để căn chỉnh các thuộc tính mà thành phần React yêu cầu. và Page gốc của applet và gọi hàm tạo Trang gốc để khởi tạo trang.
?
1
2
3
4
5
6
7
8
9
10
11
12
|
nhập * làm đường dẫn từ
'con đường'
;
nhập VirtualEntry từ
'./VirtualEntry'
;
xuất khẩu
mặc định
lớp PageEntry mở rộng VirtualEntry {
đầu raNguồn() {
trở lại
`
nhập {createPageConfig} từ
'@remax/thời gian chạy'
;
nhập mục từ
'./${path.basename(this.filename)}'
;
Trang(createPageConfig(Mục nhập,
'${tên này}'
));
`;
}
}
|
createPageConfig chịu trách nhiệm gắn thành phần React vào vùng chứa kết xuất tùy chỉnh của remax, đồng thời liên kết các vòng đời khác nhau của Trang chương trình mini với các hook khác nhau do remax cung cấp.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
xuất khẩu
mặc định
chức năng
createPageConfig(Trang: React.ComponentType, tên: chuỗi) {
const app = getApp() như bất kỳ;
const cấu hình: bất kỳ = {
dữ liệu: {
gốc: {
những đứa trẻ: [],
},
Phương thức gốc: {
những đứa trẻ: [],
},
},
wrapperRef: React.createRef(),
lifecycleCallback: {},
đang tải(
cái này
: bất kỳ, truy vấn: bất kỳ) {
const PageWrapper = createPageWrapper(Trang, tên);
cái này
.pageId = generatePageId();
cái này
.lifecycleCallback = {};
cái này
.dữ liệu = {
gốc: {
những đứa trẻ: [],
},
Phương thức gốc: {
những đứa trẻ: [],
},
};
cái này
.query = truy vấn;
cái này
. thùng chứa =
mới
Thùng chứa(
cái này
,
'gốc'
);
cái này
.modalContainer =
mới
Thùng chứa(
cái này
,
'modalRoot'
);
const pageElement = React.createElement(PageWrapper, {
trang:
cái này
,
truy vấn,
modalContainer:
cái này
.modalContainer,
tham khảo:
cái này
.wrapperRef,
});
nếu như
(ứng dụng && ứng dụng._mount) {
cái này
.element = createPortal(pageElement,
cái này
. thùng chứa,
cái này
.pageId);
ứng dụng._mount(
cái này
);
}
khác
{
cái này
.element = render(pageElement,
cái này
. thùng chứa);
}
trở lại
cái này
.callLifecycle(Lifecycle.load, truy vấn);
},
khiUnload(
cái này
: bất kì) {
cái này
.callLifecycle(Lifecycle.unload);
cái này
.dỡ bỏ =
ĐÚNG VẬY
;
cái này
.container.clearUpdate();
ứng dụng._unmount(
cái này
);
},
|
Vùng chứa là vùng chứa gốc được xác định theo đặc tả hiển thị tùy chỉnh của React. Cuối cùng, phương thức setData gốc của chương trình mini được gọi trong phương thức applyUpdate để cập nhật chế độ xem hiển thị.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
áp dụngCập Nhật() {
nếu như
(
cái này
.stopCập Nhật ||
cái này
.updateQueue.length === 0) {
trở lại
;
}
const thời gian bắt đầu =
mới
Ngày(). lấy thời gian();
nếu như
(
loại của
cái này
.context.$spliceData ===
'chức năng'
) {
hãy để $batchedUpdates = (gọi lại: () => void) => {
gọi lại();
};
nếu như
(
loại của
cái này
.context.$batchedUpdates ===
'chức năng'
) {
$batchedUpdates =
cái này
.context.$batchedUpdates;
}
$batchedUpdates(() => {
cái này
.updateQueue.map((cập nhật, chỉ mục) => {
hãy gọi lại = không xác định;
nếu như
(chỉ số + 1 ===
cái này
.updateQueue.length) {
gọi lại = () => {
nativeEffector.run();
nếu như
(Tùy chọn Runtime.get(
'gỡ lỗi'
)) {
console.log(`setData => Thời gian gọi lại: ${
mới
Ngày().getTime() - thời gian bắt đầu}ms`);
}
};
}
nếu như
(cập nhật.type ===
'nối'
) {
cái này
.bối cảnh.$spliceData(
{
[
cái này
.normalizeUpdatePath([...update.path,
'những đứa trẻ'
])]: [
cập nhật.bắt đầu,
cập nhật.deleteCount,
...cập nhật.mục,
],
},
gọi lại
);
}
nếu như
(cập nhật.type ===
'bộ'
) {
cái này
.bối cảnh.setData(
{
[
cái này
.normalizeUpdatePath([...update.path, update.name])]: update.value,
},
gọi lại
);
}
});
});
cái này
.updateQueue = [];
trở lại
;
}
const updatePayload =
cái này
.updateQueue.reduce<{ [key: chuỗi]: bất kỳ }>((acc, cập nhật) => {
nếu như
(cập nhật.node.isDeleted()) {
trở lại
theo;
}
nếu như
(cập nhật.type ===
'nối'
) {
theo[
cái này
.normalizeUpdatePath([...update.path,
'nút'
, update.id.toString()])] = update.items[0] ||
vô giá trị
;
nếu như
(cập nhật.trẻ em) {
theo[
cái này
.normalizeUpdatePath([...update.path,
'những đứa trẻ'
])] = (cập nhật. trẻ em || []).map(c => c.id);
}
}
khác
{
theo[
cái này
.normalizeUpdatePath([...update.path, update.name])] = update.value;
}
trở lại
theo;
}, {});
cái này
.context.setData(updatePayload, () => {
nativeEffector.run();
nếu như
(Tùy chọn Runtime.get(
'gỡ lỗi'
)) {
console.log(`setData => Thời gian gọi lại: ${
mới
Date().getTime() - startTime}ms`, updatePayload);
}
});
cái này
.updateQueue = [];
}
|
Việc cập nhật vùng chứa được thực hiện trong phương thức kết xuất trong tệp kết xuất.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
chức năng
getPublicRootInstance(container: ReactReconciler.FiberRoot) {
const containerFiber = container.current;
nếu như
(!containerFiber.child) {
trở lại
vô giá trị
;
}
trở lại
containerFiber.child.stateNode;
}
xuất khẩu
mặc định
chức năng
render(rootElement: React.ReactElement |
vô giá trị
, container: Container | AppContainer) {
nếu như
(!container._rootContainer) {
container._rootContainer = ReactReconcilerInst.createContainer(container,
SAI
,
SAI
);
}
ReactReconcilerInst.updateContainer(rootElement, container._rootContainer,
vô giá trị
, () => {
});
trở lại
lấyPublicRootInstance(container._rootContainer);
}
|
Ngoài ra, các thành phần được hiển thị ở đây thực sự được bao bọc bằng một lớp createPageWrapper, chủ yếu để xử lý một số thao tác liên quan đến chuyển tiếp-ref. Giờ đây, thành phần React cấp trang đã được liên kết với Trang gốc của chương trình mini. Quá trình xử lý Component cũng tương tự như thế này, các bạn có thể xem file remax-cli/src/build/entries/ComponentEntry.ts.
?
1
2
3
4
5
6
7
8
9
10
11
12
|
nhập * làm đường dẫn từ
'con đường'
;
nhập VirtualEntry từ
'./VirtualEntry'
;
xuất khẩu
mặc định
lớp ComponentEntry mở rộng VirtualEntry {
đầu raNguồn() {
trở lại
`
nhập {createComponentConfig} từ
'@remax/thời gian chạy'
;
nhập mục từ
'./${path.basename(this.filename)}'
;
Thành phần(createComponentConfig(Entry));
`;
}
}
|
Vì vậy, đối với các thành phần thông thường, remax sẽ biên dịch chúng thành các thành phần tùy chỉnh. Các thành phần tùy chỉnh của chương trình mini bao gồm json wxml wxss js. Quá trình xử lý các tệp này từ các thành phần React nằm trong remax-cli/src/build/webpack /plugins. /ComponentAsset được xử lý để tạo các tệp wxml, wxss và js.
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
xuất khẩu
mặc định
lớp ComponentAssetPlugin {
người xây dựng: Người xây dựng;
bộ nhớ đệm: SourceCache =
mới
Bộ nhớ đệm nguồn();
constructor(người xây dựng: Người xây dựng) {
cái này
.builder = người xây dựng;
}
áp dụng(trình biên dịch: Trình biên dịch) {
biên dịch.hooks.emit.tapAsync(PLUGIN_NAME, async (biên dịch, gọi lại) => {
const { tùy chọn, api } =
cái này
.người xây dựng;
const meta = api.getMeta();
const { mục nhập } =
cái này
.builder.entryCollection;
chờ Promise.all(
Mảng.from(entries.values()).map(thành phần không đồng bộ => {
nếu như
(!(thành phần
trường hợp của
Thành phần nhập)) {
trở lại
Hứa hẹn. giải quyết();
}
const chunk = biên dịch.chunks.find(c => {
trở lại
c.name === thành phần.tên;
});
const modules = [...getModules(chunk), thành phần.tên tệp];
hãy để templatePromise;
nếu như
(tùy chọn.turboRenders) {
templatePromise = createTurboTemplate(
cái này
.builder.api, tùy chọn, thành phần, mô-đun, meta, biên dịch);
}
khác
{
templatePromise = createTemplate(thành phần, tùy chọn, meta, biên dịch,
cái này
. bộ nhớ đệm);
}
chờ Promise.all([
chờ đợi templatePromise,
chờ đợi createManifest(
cái này
.builder, thành phần, biên dịch,
cái này
.bộ nhớ đệm),
]);
})
);
gọi lại();
});
}
}
|
Một loạt file của Page được xử lý trong remax-cli/src/build/webpack/plugins/PageAsset. Đồng thời, mối quan hệ phụ thuộc giữa Page và các thành phần tùy chỉnh sẽ được phân tích trong createMainifest và mối quan hệ liên kết của useComponents sẽ được phân tích. được tạo tự động.
Đến đây là kết thúc bài viết về phân tích quá trình biên dịch (được khuyến nghị) của Remax framework sử dụng React để viết các chương trình nhỏ. Để biết thêm thông tin về cách viết các chương trình nhỏ trong React, vui lòng tìm kiếm các bài viết trước của tôi hoặc tiếp tục duyệt các bài viết liên quan bên dưới. tương lai! .
Liên kết gốc: https://www.cnblogs.com/dojo-lzz/archive/2021/04/21/14686861.html.
Cuối cùng, bài viết này về phân tích quy trình biên dịch (được khuyến nghị) của khung Remax để viết các chương trình nhỏ bằng React sẽ kết thúc tại đây. nội dung, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .
Tôi là một lập trình viên xuất sắc, rất giỏi!