Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. React Native
Code

Bắt đầu với bố cục của React Native

by
Difficulty:BeginnerLength:LongLanguages:

Vietnamese (Tiếng Việt) translation by Thai An (you can also view the original English article)

Trong hướng dẫn này, bạn sẽ tìm hiểu cách bố cục ứng dụng React Native và cách triển khai bố cục thường được sử dụng trong các ứng dụng. Bài này bao gồm bố cục stack, bố cục grid và bố cục absolute. Tôi sẽ giả sử rằng bạn đã biết những điều cơ bản về tạo kiểu ứng dụng React Native và cách sử dụng CSS nói chung, vì vậy tôi sẽ không lưu trữ quá nhiều vào StyleSheet.create và cách thêm kiểu dáng cho các phần tử khác nhau.

Bạn có thể tìm code đầy đủ cho hướng dẫn này trên GitHub.

Thiết lập dự án

Để mọi việc dễ dàng, chúng tôi sẽ sử dụng React Native cho Web. Với React Native cho Web Starter, chúng ta có thể dễ dàng tạo ra một dự án React Native mới có thể chạy trên trình duyệt. Code này tương thích 100% với dự án React Native. Chúng tôi sẽ tạo một component riêng biệt cho mỗi bố cục mà chúng tôi sẽ triển khai để bạn có thể dễ dàng nhập chúng vào một dự án React Native bình thường nếu bạn muốn. Chúng tôi chỉ sử dụng React Native cho Web vì nó giúp chúng ta bắt đầu dễ dàng hơn.

Bạn có thể thực hiện các lệnh sau để thiết lập dự án:

Sau khi cài đặt xong, hãy di chuyển đến thư mục app/components. Chúng ta chủ yếu sẽ làm việc với các file chứa trong thư mục này.

Mở file App.js và thay thế code mặc định bằng code sau đây:

Sau đó, bạn có thể import các component mà chúng tôi sẽ tạo ra và sau đó hiển thị chúng từ file này. Chỉ cần nhớ rằng bất kỳ component nào mà chúng tôi lưu bên trong thư mục layouts sẽ không được hiển thị cùng bất kỳ thứ gì khác. Ví dụ: nếu chúng tôi có layouts/StackLayout.js, hãy làm như sau trong App.js:

Bạn có thể bắt đầu dự án bằng cách lệnh sau đây:

Điều này cho phép bạn truy cập nó trong trình duyệt bằng cách truy cập http://localhost:3000. Quá trình tải lại toàn bộ trang sẽ được kích hoạt nếu bạn thực hiện thay đổi với bất kỳ file đang được import từ file App.js.

Làm sao để tạo các bố cục khác nhau

Bố cục trong React Native sử dụng một tập con của Flexbox. (Tôi nói "subset" - tập con vì sẽ không bao gồm tất cả tính năng trong mô tả chi tiết về Flexbox. Vì vậy nếu bạn biết Flexbox rồi, thì bạn có thể nhanh chóng áp dụng những kỹ năng này vào React Native. Cũng cần lưu ý rằng không có các đơn vị nổi hoặc phần trăm dựa trên React Native. Điều này có nghĩa là chúng ta chỉ có thể thực hiện bố cục bằng cách sử dụng Flexbox và CSS position (định vị trí).

Bố cục stack

Loại bố cục đầu tiên mà chúng tôi sẽ triển khai là Bố cục stack. Đối với phương thẳng đứng, bố cục này xếp chồng các phần tử lên trên nhau, trong khi đối với phương ngang, các phần tử được đặt cạnh nhau. Chúng ta hãy xem xét phương thẳng đứng trước tiên:

Vertical Stack Layout

Đây là code để hoàn thành bố cục ở trên:

Chia nhỏ code phía trên, trước tiên chúng ta có được chiều cao của khoảng trống có sẵn cho ứng dụng để sử dụng. Sau đó, chúng tôi tính toán chiều cao của mỗi box (hộp) sẽ là bao nhiêu. Vì có ba box nên chúng tôi chia nó thành ba.

Đối với markup, các box nên được bao bọc bên trong một container. Các style phổ biến được khai báo trong đối tượng box và các màu nền duy nhất được áp dụng cho các đối tượng được đặt tên duy nhất (box1, box2, box3):

Để sử dụng Flexbox, bạn phải sử dụng thuộc tính flex áp dụng cho container. Giá trị là không gian nó sẽ sử dụng. Nếu đó là 1, nó có nghĩa là nó sẽ sử dụng tất cả không gian đang có, miễn là phần tử không có sibling (phần tử họ hàng) nào. Chúng ta sẽ xét một ví dụ sử dụng flex với các sibling sau.

flexDirection cho phép bạn chỉ định trục (axis) chính của bố cục. Mặc định thì thuộc tính này được xét giá trị column. Thiết lập flexDirection thành column có nghĩa là các thành phần con của container sẽ được xếp theo phương thẳng đứng (xếp chồng lên nhau) trong khi thiết lập là row tức là các thành phần con sẽ được xếp đặt theo phương ngang (nằm cạnh nhau). Để đạt được chiều cao bằng nhau, hãy xét chiều cao của box bằng với giá trị mà ta đã tính được trước đó.

Dưới đây là hình ảnh để giúp bạn hình dung làm thế nào nội dung được dàn trải dựa trên flexDirection mà bạn đã xác định.

Illustration of flexDirection row and column

Phương pháp tôi vừa cho bạn xem là cách làm thủ công mọi việc. Sử dụng Dimensions để tính toán chiều rộng hoặc chiều cao của các thành phần sẽ không hữu hiệu nếu ứng dụng của bạn hỗ trợ cả phương dọc và phương ngang của thiết bị. Đó là bởi vì ngay sau khi người dùng lật thiết bị của họ, chiều rộng hoặc chiều cao mà bạn tính trước đó sẽ sai. React Native sẽ không tự động tính toán lại cho bạn, vì vậy ứng dụng sẽ trở nên kỳ dị.

Flexbox thực sự có thể giúp bạn tính toán nếu bạn cung cấp các giá trị chính xác. Để đạt được một bố cục như trên mà không sử dụng Dimensions, tất cả những gì bạn phải làm là xét flex: 1 cho tất cả các box thay vì cố xác định height:

Đây là một ví dụ về sử dụng flex với các sibling. Bây giờ chúng tôi có ba sibling với cùng một giá trị flex. Điều này có nghĩa rằng cả ba phần tử trong số đó sẽ chia sẻ không gian bằng nhau vì giá trị flex giống nhau. (Bạn thực sự có thể sử dụng bất kỳ giá trị flex nào miễn là các phần tử con đều có cùng giá trị.)

Sử dụng kiến ​​thức này, bây giờ bạn có thể đạt được bố cục với header (tiêu đề), content (nội dung) và footer (chân trang):

Nó sẽ trông giống như thế này:

Stack Layout header content footer

Chú ý rằng đây là bố cục tĩnh Vì vậy, nếu nội dung chính của bạn cao hơn chiều cao tối đa cho sẵn, thì phần còn lại của nội dung của bạn sẽ bị ẩn đi. Nếu bạn hy vọng nội dung của bạn vượt qua giới hạn đó, bạn có thể sử dụng component dựng sẵn tên ScrollView để tự động tạo thanh cuộn dọc giống như trong các trang web.

Bố cục stack theo phương ngang

Để thực hiện bố cục stack theo chiều ngang, tất cả những gì bạn phải làm là xét flexDirection thành row.

Nếu chúng ta thay đổi giá trị box flex trở về 1, việc này dẫn đến kết quả như sau:

Thay đổi duy nhất là flexDirection, hiện đã được xét giá trị là row. Vì các box được xét giá trị là flex: 1, chúng sẽ có cùng chiều rộng và chiều cao. Tất cả các khái niệm của bố cục stack theo phương dứng đều có thể áp dụng cho bố cục này.

Căn đều nội dung

Nếu bạn muốn kiểm soát việc dàn trải phần tử con trong một container, thì bạn sử dụng thuộc tính justifyContent trong container.

Dưới đây là 5 giá trị khả dụng có thể áp dụng cho thuộc tính này. Trong những ví dụ sau đây, chiều cao của mỗi phần tử con được giảm bớt để minh hoạ cho việc mỗi phần tử sẽ trông như thế nào. Bạn sẽ không thể thấy bất kỳ sự khác biệt nào nếu giá trị flex1 cho mỗi phần tử con, bởi vì chúng sẽ sử dụng tất cả không gian có sẵn.

  • flex-start: các phần tử con được căn chỉnh hướng về điểm bắt đầu. Chú ý nền màu trắng ngay bên dưới phần tử con cuối cùng. Đó là cách nhận biết flex-start đang được sử dụng bởi vì tất cả các phần tử con được liên kết với điểm khởi đầu. Điều này làm phía sau cùng xuất hiện một khoảng trống.
Flex Start
  • flex-end: các phần tử con được căn chỉnh về phía dòng cuối. Lưu ý rằng lần này khoảng trống nằm ở điểm bắt đầu.
  • center: các phần tử con được hướng về phía trung tâm. Lần này khoảng trống được chia đều giữa điểm bắt đầu và điểm kết thúc.
Flex Center
  • space-around: các phần tử con được dàn trải sao cho xung quanh mỗi phần từ đều có khoảng trống bằng nhau. Có nghĩa là các phần tử ở phần bên ngoài sẽ có ít khoảng trống hơn ở bên ngoài và khoảng cách giữa hai phần tử con sẽ tăng gấp đôi.
Flex Space Around
  • space-between: các phần tử con được dàn trải sao cho có một khoảng trống bằng nhau giữa chúng.
Flex Space Between

Như bạn có thể thấy, mỗi thuộc tính cho style phụ thuộc vào chiều cao hoặc chiều rộng của các phần tử con. Phụ thuộc vào chiều rộng nếu flexDirectionrow, và vào chiều cao nếu flexDirectioncolumn.

Ví dụ, space-between sẽ không thực có hiệu quả trên bố cục stack theo phương đứng nếu mỗi phần tử con sử dụng flex để kiểm soát chiều cao. Bởi vì sẽ không có nhiều không gian còn lại cho khoảng cách giữa mỗi phần tử con để sử dụng.

Căn chỉnh các thành phần

Thoạt nhìn, justifyContentalignItems có thể trông giống như cho cùng một kết quả. Hai thuộc tính này cùng sử dụng ba giá trị: flex-start, flex-end, và center, và bổ sung thêm giá trị stretch.

Sự khác biệt chính giữa justifyContentalignItems là trục (axis) mà các thành phần con được phân phối. Như bạn đã thấy trước đó, justifyContent luôn sử dụng trục chính khi phân phối các phần tử con. Nhưng alignItems sử dụng trục đối diện với trục chính.

Chúng ta đã biết rằng trục được xác định bởi flexDirection đã được thiết lập. Vì vậy, nếu flexDirectionrow, trục chính tính từ trái sang phải. Điều này có nghĩa là trục băng qua sẽ tính từ trên xuống dưới. Mặt khác, nếu flexDirectioncolumn thì trục băng qua sẽ tính từ trái sang phải.

Dưới đây là một số ví dụ về justifyContentalignItems được áp dụng kế bên với flexDirection của row. Ví dụ đầu tiên sử dụng justifyContent trong khi ví dụ thứ hai sử dụng alignItems.

  • flex-start: vị trí của các phần tử như nhau, đó là lý do tại sao việc triển khai alignItems trông giống hệt như justifyContent.
justifyContent and alignItems flex-start
  • flex-end: bây giờ chúng ta bắt đầu thấy sự khác biệt. Trong trường hợp đầu tiên, nó nằm ở phía cuối hàng của dòng đầu tiên, trong khi trường hợp thứ hai xuất hiện ở điểm bắt đầu của hàng cuối cùng.
justifyContent and alignItems flex-end
  • center: center có cùng khái nghiệm với phần còn lại của các giá trị mà chúng ta đã sử dụng cho đến giờ. Trong trường hợp đầu tiên, các thành phần được căn giữa trên trục x trong khi ở phần thứ hai, các mục được căn giữa trên trục y.

justifyContent and alignItems center

  • stretch: sử dụng giá trị này để giúp các phần tử con trải dài để lấp đầy container. Đây là giá trị mặc định cho alignItems, vì vậy việc xác định giá trị này là tuỳ ý. Bạn đã thấy hiểu hoạt động này khi chúng tôi triển khai bố cục stack theo chiều dọc và ngang.

Đây là code được sử dụng trong các ví dụ trên. Hãy thử trải nghiệm với các giá trị của flexDirection, justifyContentalignItems nếu bạn muốn xem chúng cho kết quả thế nào:

Nếu bạn muốn xác định phần căn chỉnh của từng phần tử trong một container, bạn có thể sử dụng thuộc tính alignSelf. Tất cả các giá trị khả dụng cho align-items đều có thể áp dụng cho thuộc tính này. Vậy ví dụ như bạn có thể căn chỉnh một phần tử duy nhất ở bên phải container của nó, trong khi tất cả phần còn lại được căn chỉnh sang bên trái.

Bố cục Grid

React Native không thực sự có hệ thống bố cục grid (lưới), nhưng Flexbox đủ linh hoạt để tạo một thứ như thế. Bằng cách áp dụng những điều chúng ta đã học, chúng ta có thể tạo lại các bố trí Grid bằng Flexbox. Đây là một ví dụ:

Grid Layout

Và đây là code tạo bố cục đó:

Từ code trên, bạn có thể thấy rằng chúng tôi đang mô phỏng những gì thường thấy trong các framework CSS Grid. Mỗi hàng được bao bọc trong một view riêng biệt và các phần tử của grid nằm bên trong nó. Giá trị flex mặc định là 1 được áp dụng cho từng mục để chúng chia sẻ không gian bằng nhau trên mỗi hàng. Nhưng đối với các thành phần cần dùng không gian lớn hơn, giá trị lớn hơn của flex được áp dụng. Điều này tự động điều chỉnh chiều rộng của các thành phần khác để nó đủ sức chứa tất cả các thành phần.

Nếu bạn muốn thêm khoảng trắng giữa mỗi thành phần trong một hàng, bạn có thể thêm padding (phần đệm) vào từng thành phần và sau đó tạo một box nằm bên trong mỗi thành phần.

Kết quả của điều chỉnh này sẽ giống như bên dưới:

Grid Layout With Spaces

Bố cục Absolute

React Native chỉ hỗ trợ định vị absoluterelative. Tuy nhiên, điều này không nên hạn chế bạn bởi vì bạn luôn có thể kết hợp chúng với Flexbox để định vị các phần tử khác nhau ở bất cứ đâu bạn muốn.

Hãy xem cách chúng tôi sẽ thực hiện những điều sau đây:


Chúng ta có thể thực hiện được điều này một cách dễ dàng nếu chúng ta có điều khiển đầy đủ trên các giá trị định vị có sẵn trong trình duyệt. Nhưng khi chúng tôi làm việc với React Native, chúng ta cần phải nghĩ theo cách của Flexbox đầu tiên và sau đó sử dụng định vị CSS cho các box nhỏ.

Bằng việc dùng Flexbox, có thể đạt được việc này theo 2 cách. Bạn có thể sử dụng row hoặc column cho flexDirection cho container chính. Cách bạn sắp xếp các thành phần khác nhau sẽ phụ thuộc vào phương pháp mà bạn chọn. Ở đây chúng ta sẽ sử dụng row cho flexDirection để màn hình được chia thành ba cột. Cột đầu tiên sẽ chứa box màu cam, cột thứ hai sẽ chứa các box đen, xám và xanh lục và cột thứ ba sẽ chứa các box nhỏ có màu tía màu xanh.

Nếu bạn đã biết mỗi thành phần sẽ được bố trí thế nào, thì giờ chỉ là vấn đề áp dụng những điều chúng ta đã học được. Sau tất cả, chúng ta thực sự không cần phải áp dụng định vị CSS cho các box lớn mà chỉ cần cho những box nhỏ.

Cột đầu tiên chỉ có box màu cam, do đó, việc áp dụng justifyContent: 'center' vào container của nó sẽ mang lại kết quả như ý. Giá trị flexDirection mặc định là column. Có nghĩa là nếu bạn đặt justifyContent thành center, các phần tử con sẽ được căn chỉnh ở giữa Y-axis.

Cột thứ hai về cơ bản có cùng ý tưởng như cột đầu tiên, chỉ là lần này chúng ta không muốn căn chỉnh tất cả các box ở trung tâm. Điều chúng ta muốn là để chúng có khoảng trống ở giữa bằng nhau và justifyContent: 'space-between' đáp ứng được yêu cầu này. Nhưng đồng thời chúng tôi cũng muốn căn giữa tất cả các phần tử con trên trục X vì vậy chúng tôi sử dụng alignItems: 'center'.

Phần khó khăn duy nhất ở đây là bạn không nên áp dụng bất kỳ thuộc tính width vào box màu xám vì chúng tôi muốn nó trải dài trên tất cả để sử dụng toàn bộ chiều rộng của thành phần cha mẹ của nó. Vì chúng tôi không áp dụng bất kỳ width nào, nên chúng tôi áp dụng alignSelf: 'stretch' vào box màu xám để sử dụng toàn bộ chiều rộng của phần tử cha của nó.

Tiếp theo, để định vị box nhỏ màu đỏ cách xa vị trí tương đối của nó, chúng ta sử dụng position: relative và sau đó áp dụng các giá trị topleft vì vị trí tương đối của nó nằm quanh góc trên bên trái của phần tử cha của nó.

Đối với box nhỏ màu cam nhỏ, chúng tôi sử dụng position: 'absolute'; vì chúng ta cần căn chỉnh nó với góc trên bên phải của phần tử cha của nó. Cách này hữu hiệu bởi vì các phần tử được định vị hoàn toàn trong React Native được gắn liền với phần tử cha của chúng.

Cột thứ ba về cơ bản áp dụng cùng một ý tưởng vì vậy tôi sẽ không giải thích thêm nữa.

Tiếp theo, hãy thử triển khai một bố cục có header và footer cố định. Điều này thường được thấy trong các ứng dụng có điều hướng tab; các tab được cố định ở cuối màn hình trong khi nội dung chính có thể xem bằng thao tác cuộn.

Để thực hiện điều này, chúng tôi cần sử dụng component ScrollView để nếu nội dung chính vượt quá chiều cao của container, React Native sẽ tự động tạo thanh cuộn dọc. Component này cho phép chúng tôi thêm marginTopmarginBottom vào container nội dung chính sao cho header và footer trở thành cố định và sẽ không cản trở nội dung chính. Ngoài ra, lưu ý rằng giá trị leftright của header và footer được xét là 0 vì vậy chúng sẽ sử dụng toàn bộ chiều rộng của thiết bị.

Kết quả trông như thế này:

Fixed header and footer

Các thư viện của bên thứ ba

React Native có một cộng đồng lớn sau lưng, do đó, không có gì lạ khi vài thư viện đã được tạo ra để hỗ trợ cho việc thực hiện bố cục được dễ dàng: Trong phần này, tôi sẽ giới thiệu cho bạn một thư viện có tên React Native Easy Grid. Bạn có thể sử dụng nó để mô tả cách bạn muốn bố trí ứng dụng của mình bằng cách tận dụng các component Grid, RowCol.

Bạn có thể cài đặt bằng lệnh sau:

Import thư viện và extract các component khác nhau trong file của bạn.

Component Grid được sử dụng để bao bọc mọi thứ. Col được sử dụng để tạo một cột và Row được sử dụng để tạo các hàng. Bạn có thể xác định thuộc tính size cho cả RowCol, dù chúng ta chỉ sử dụng nó trong Row bên dưới. Nếu kích thước không được chỉ định, nó sẽ chia đều không gian có sẵn giữa các đối tượng Col.

Trong trường hợp này, chỉ có hai đối tượng, vì vậy toàn bộ màn hình được chia thành hai cột. Cột đầu tiên sau đó được chia thành hai hàng. Ở đây chúng tôi đã xác định size, nhưng bạn thực sự có thể bỏ qua nó nếu bạn chỉ cần các hàng có kích thước bằng nhau, như chúng tôi đã làm bên dưới.

Khi đã xong, tất cả những gì bạn phải làm là thêm style cho các hàng và cột:

Như bạn đã thấy, React Native Easy Grid có một API rất trực quan.

Tổng kết

Trong hướng dẫn này, bạn đã học cách bố cục các ứng dụng React Native. Cụ thể, bạn đã học cách sử dụng Flexbox của React Native để sắp xếp vị trí cho mọi thứ. Bạn cũng đã học cách sử dụng React Native Easy Grid, giúp việc triển khai Flexbox dễ dàng hơn.

Trong hướng dẫn sắp tới, chúng tôi sẽ kết hợp những điều bạn được học vào thực tế bằng cách tạo lại các phần tử UI thường thấy trong các ứng dụng: những thứ như lịch, các danh sách và điều hướng kiểu tab.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.