NavigationLink — nó là gì, nút chuyển đổi trong SwiftUI

Tác giả: IT Sectr Đã đăng: 2026-06-25 Thời gian đọc: 6 phút

NavigationLink là một phần tử điều khiển trong SwiftUI được thiết kế để chuyển đổi sang màn hình khác trong NavigationStack hoặc NavigationView. Theo Apple Developer Documentation, 2024, NavigationLink tạo một nút mà khi nhấn vào sẽ đặt View mục tiêu vào ngăn xếp điều hướng. Trong iOS 16+, nên sử dụng NavigationLink với value và NavigationDestination thay vì destination trực tiếp để tránh khởi tạo sớm các View mục tiêu.

Những điểm chính

  • NavigationLink — nút điều hướng đến màn hình khác trong SwiftUI
  • Hai dạng — với destination:label: và với value:label:
  • Dạng value được khuyến nghị trong iOS 16+ (NavigationStack)
  • Dạng destination gây khởi tạo View sớm
  • Mũi tên tự động tiết lộ trong List

NavigationLink là một View bắt đầu chuyển đổi điều hướng khi được nhấn. Bên trong NavigationStack, nhấn NavigationLink sẽ đặt màn hình mục tiêu lên ngăn xếp và hiển thị nút Quay lại của hệ thống. NavigationLink đã tồn tại từ iOS 13 và là phương pháp điều hướng chính của người dùng trong SwiftUI.

NavigationLink không kế thừa từ UIButton — nó là một View SwiftUI tự động thích ứng với ngữ cảnh. Bên trong List, NavigationLink hiển thị với một chỉ báo tiết lộ. Bên ngoài danh sách, NavigationLink hoạt động như một nút thông thường nhưng có hành vi điều hướng.

Theo SwiftUI Lab (2024), NavigationLink là một trong những View được sử dụng nhiều nhất trong các ứng dụng SwiftUI, chỉ sau Text, Image và VStack. Hiểu sự khác biệt giữa các dạng khởi tạo là rất quan trọng đối với hiệu suất và hành vi điều hướng có thể dự đoán được.

NavigationLink hoạt động bên trong như thế nào

Khi được nhấn, NavigationLink thêm một giá trị (hoặc destination) vào ngăn xếp điều hướng liên kết với NavigationStack hoặc NavigationView gần nhất. SwiftUI sử dụng EnvironmentValue để truyền đường dẫn điều hướng qua hệ thống phân cấp View. NavigationLink đọc đường dẫn này từ Environment và sửa đổi nó khi được nhấn.

NavigationLink có hai dạng chính: với destination (chỉ định trực tiếp View mục tiêu) và với value (giá trị cho NavigationDestination). Việc chọn dạng phụ thuộc vào phiên bản iOS và kiến trúc điều hướng.

DạngBộ khởi tạoiOS 13–15iOS 16+
DestinationNavigationLink(destination:label:)Được khuyến nghịKhông được khuyến nghị
ValueNavigationLink(value:label:)Không khả dụngĐược khuyến nghị
IsActiveNavigationLink(isActive:destination:label:)Điều hướng lập trìnhKhông được khuyến nghị

Dạng destination (iOS 13+): NavigationLink(destination: DetailView(), label: { Text("Open") }). Dạng này tạo DetailView ngay lập tức khi hiển thị NavigationLink, ngay cả khi người dùng chưa nhấp vào liên kết. Điều này dẫn đến khởi tạo View sớm và các vấn đề hiệu suất tiềm ẩn nếu View mục tiêu thực hiện các thao tác nặng trong bộ khởi tạo của nó.

Dạng value (iOS 16+): NavigationLink(value: "detail_42", label: { Text("Open") }). View mục tiêu chỉ được tạo khi liên kết được nhấn, khi SwiftUI tìm thấy .navigationDestination tương ứng. Điều này ngăn chặn khởi tạo sớm và làm cho điều hướng dễ dự đoán hơn.

NavigationLink với NavigationStack trong iOS 16+ yêu cầu chuyển sang dạng value. Bạn xác định một kiểu dữ liệu cho điều hướng (String, Int, enum Route) và đăng ký đích đến thông qua .navigationDestination. NavigationLink chỉ đặt giá trị lên ngăn xếp và SwiftUI tạo View mục tiêu khi nhấn.

swift
struct CatalogView: View {
    let categories: [String]

    var body: some View {
        List(categories, id: \.self) { category in
            NavigationLink(value: category) {
                Text(category)
            }
        }
        .navigationDestination(for: String.self) { category in
            CategoryView(name: category)
        }
    }
}

// Programmatic navigation:
struct DeepLinkView: View {
    @State private var path: [AppRoute] = []

    var body: some View {
        NavigationStack(path: $path) {
            HomeView()
                .navigationDestination(for: AppRoute.self) { route in
                    switch route {
                    case .detail(let id): DetailView(id: id)
                    case .settings: SettingsView()
                    }
                }
                .toolbar {
                    Button("Open Settings") {
                        path.append(AppRoute.settings)
                    }
                }
        }
    }
}

Điều hướng lập trình: thêm một giá trị vào đường dẫn (thông qua path.append) tương đương với việc nhấn một NavigationLink có cùng giá trị. Điều này cho phép triển khai điều hướng từ ViewModel, Coordinator hoặc để phản hồi thông báo push.

Dạng IsActive (NavigationLink(isActive:destination:label:)) có sẵn để tương thích nhưng không được khuyến nghị trong iOS 16+. Sử dụng dạng value với Binding đến một mảng đường dẫn hoặc NavigationPath.

NavigationLink trong List tự động hiển thị một chỉ báo tiết lộ (chevron) ở phía bên phải của hàng, báo hiệu cho người dùng rằng nhấn sẽ dẫn đến một màn hình khác. List quản lý việc hiển thị mũi tên tự động — không giống như NavigationLink thông thường bên ngoài danh sách, nơi không có mũi tên.

Với iOS 16, List với NavigationLink tự động sử dụng dạng value bên trong List(data:rowContent:). Khi sử dụng ForEach bên trong List, chỉ báo tiết lộ cũng được thêm tự động. Hành vi này không thể bị tắt thông qua các bộ sửa đổi — chỉ thay thế NavigationLink bằng Button mới có thể loại bỏ mũi tên.

Vấn đề với dạng destination trong List: nếu bạn sử dụng NavigationLink(destination:label:) bên trong List, tất cả các View đích được tạo ngay lập tức khi tải danh sách, bất kể người dùng đã nhấp vào liên kết hay chưa. Đối với danh sách có số lượng hàng lớn, điều này có thể làm chậm đáng kể quá trình tải ban đầu và tăng mức tiêu thụ bộ nhớ. Dạng value với NavigationStack giải quyết vấn đề này.

Theo WWDC 2022 (Session 10054), Apple khuyến nghị sử dụng NavigationStack và dạng value của NavigationLink cho các dự án mới. Điều này đặc biệt quan trọng đối với List có dữ liệu động, nơi số lượng hàng có thể lớn.

Mẫu 1: Giao diện tùy chỉnh của NavigationLink. NavigationLink chấp nhận bất kỳ View nào làm nhãn, cho phép tạo các thiết kế tùy chỉnh cho liên kết. Bên trong List, điều này đặc biệt thuận tiện — bạn nhận được chỉ báo tiết lộ tự động khi sử dụng NavigationLink.

swift
NavigationLink(value: ProductRoute.detail(product)) {
    HStack {
        AsyncImage(url: product.imageURL)
            .frame(width: 60, height: 60)
        VStack(alignment: .leading) {
            Text(product.name).font(.headline)
            Text(product.price) .foregroundColor(.secondary)
        }
    }
    .padding(8)
}

Mẫu 2: NavigationLink không có mũi tên (nút tùy chỉnh). Nếu bạn không cần chỉ báo tiết lộ, hãy sử dụng Button để điều hướng lập trình: path.append(value). Điều này hữu ích cho các phần tử giao diện tùy chỉnh nơi NavigationLink trông không tự nhiên.

Mẫu 3: Điều hướng có điều kiện. Bạn có thể chặn NavigationLink bằng cách sử dụng destination trống hoặc không thêm .navigationDestination cho các giá trị nhất định. Điều hướng lập trình thông qua đường dẫn cho phép kiểm tra điều kiện trước khi thêm giá trị.

Theo Hacking with Swift (2024), hầu hết các vấn đề với NavigationLink liên quan đến việc sử dụng dạng destination trong các dự án cũ. Khi di chuyển sang NavigationStack, hãy thay thế tất cả NavigationLink(destination:label:) bằng NavigationLink(value:label:) và thêm .navigationDestination ở cấp gốc.

Các câu hỏi thường gặp

NavigationLink trong SwiftUI là gì?

NavigationLink là một View để chuyển đổi sang màn hình khác trong SwiftUI. Khi được nhấn, nó đặt màn hình mục tiêu vào ngăn xếp điều hướng NavigationStack hoặc NavigationView. Nó hỗ trợ hai dạng: với destination (View mục tiêu) và với value (giá trị định tuyến).

Dạng NavigationLink nào tốt hơn: destination hay value?

Dạng value (iOS 16+) được ưa chuộng hơn: View mục tiêu chỉ được tạo khi nhấn, không phải khi hiển thị liên kết. Dạng destination tạo View ngay lập tức, có thể gây ra vấn đề hiệu suất. Đối với các dự án iOS 16+, hãy sử dụng value + NavigationDestination.

Tại sao NavigationLink tạo mũi tên trong List?

SwiftUI tự động thêm một chỉ báo tiết lộ (mũi tên) vào NavigationLink bên trong List, báo hiệu khả năng điều hướng. Hành vi này không thể bị tắt. Nếu không cần mũi tên, hãy sử dụng Button với điều hướng lập trình thông qua path.append().

Làm thế nào để thực hiện điều hướng lập trình qua NavigationLink?

Sử dụng NavigationStack với một Binding đường dẫn và thêm giá trị qua path.append(value). Điều này tương đương với việc nhấn một NavigationLink có cùng value. Điều hướng lập trình cho phép triển khai deep link, thông báo push và mẫu Coordinator.

NavigationLink có ảnh hưởng đến hiệu suất không?

Dạng destination có thể ảnh hưởng đến hiệu suất nếu các View mục tiêu thực hiện các thao tác nặng trong bộ khởi tạo của chúng — tất cả các đích đến được tạo khi hiển thị danh sách. Dạng value với NavigationStack giải quyết vấn đề này bằng cách chỉ tạo View khi nhấn. Đối với danh sách có 50+ hàng, sự khác biệt là đáng kể.

Tổng kết

  • NavigationLink — nút chuyển đổi điều hướng giữa các màn hình SwiftUI
  • Dạng value được khuyến nghị trong iOS 16+ với NavigationStack
  • Dạng destination tạo View sớm — tránh cho danh sách lớn
  • Chỉ báo tiết lộ — mũi tên tự động trong List (không thể tắt)
  • Điều hướng lập trình qua path.append() cho deep link và Coordinator
  • NavigationDestination đăng ký màn hình mục tiêu theo kiểu dữ liệu
  • Dạng IsActive — không được dùng nữa, sử dụng dạng value trên iOS 16+

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm