Angular2 - các biến riêng tư có thể truy cập được trong mẫu không?


143

Nếu một biến được khai báo privatetrên một lớp thành phần, tôi có thể truy cập nó trong khuôn mẫu của thành phần đó không?

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>{{title}}</h2>
      <h2>Hello {{userName}}</h2> // I am getting this name
    </div>
  `,
})
export class App {
  public title = 'Angular 2';
  private userName = "Test Name"; //declared as private
}

Câu trả lời:


226

Không, bạn không nên sử dụng các biến riêng tư trong các mẫu của mình.

Mặc dù tôi thích câu trả lời của drewmoore và thấy logic khái niệm hoàn hảo trong đó, nhưng thực tế nó đã sai. Các mẫu không tồn tại trong các lớp thành phần, nhưng bên ngoài chúng. Hãy xem repo này cho bằng chứng.

Lý do duy nhất khiến nó hoạt động là vì privatetừ khóa của TypeScript không thực sự khiến thành viên riêng tư. Quá trình biên dịch đúng lúc xảy ra trong một trình duyệt trong thời gian chạy và JS không có bất kỳ khái niệm nào về các thành viên riêng tư (chưa?). Tín dụng đến Sander Elias vì đã đưa tôi đi đúng hướng.

Với quá ngctrình biên dịch trước và trước, bạn sẽ gặp lỗi nếu bạn thử truy cập các thành viên riêng của thành phần từ mẫu. Sao chép bản trình diễn repo, thay đổi MyComponentmức độ hiển thị của thành viên thành riêng tư và bạn sẽ gặp lỗi biên dịch khi chạy ngc. Đây cũng là câu trả lời cụ thể cho việc biên soạn trước thời gian.


6
Đây là bình luận tốt nhất và imo nên là câu trả lời được chấp nhận. Không phải là bạn có thể sử dụng các biến riêng tư sau khi được dịch mã, mà bạn nên .. Giữ sạch mã!
Sam Vloeberghs

2
Đây là câu trả lời duy nhất hợp lệ! Codelyzer hiện cảnh báo bạn khi bạn sử dụng var riêng trong mẫu của bạn.
maxime1992

7
Vấn đề duy nhất của tôi với vấn đề này là, làm thế nào để bạn phân biệt giữa các thành viên tiếp xúc công khai thực tế như @Inputs và Đầu ra cho các thành viên mà chúng tôi muốn chỉ hiển thị với mẫu của chúng tôi chứ không phải thế giới bên ngoài. Nếu bạn đang xây dựng các thành phần có thể sử dụng lại, nơi bạn muốn các phương thức / thành viên có thể truy cập vào mẫu nhưng không phải với các thành phần khác. Tôi nghĩ rằng câu trả lời ban đầu là chính xác. Mẫu là một phần của thành phần.
Ashg

1
Tôi đồng ý với @Ashg - và không chỉ viết Đầu vào và Đầu ra. Điều gì về khi tôi muốn giao tiếp giữa các thành phần, ví dụ như bằng cách tiêm một thành phần cha mẹ vào con của nó. Thành phần con sau đó có thể thấy mọi thứ mà cha mẹ đang phơi bày ra khuôn mẫu của nó, thay vì chỉ các phương thức mà cha mẹ muốn đưa ra thế giới bên ngoài. Trong các ràng buộc của Angular, câu trả lời này vẫn là câu trả lời đúng, nhưng tôi không nghĩ rằng thiết kế này đã được suy nghĩ kỹ.
Dan King

Đây là một câu trả lời tốt vì nó giải quyết các hạn chế trong quá trình biên dịch AoT của Angular và cách khắc phục chúng. Tuy nhiên, IMO câu hỏi là khái niệm (cố ý hay không). Về mặt khái niệm, các mẫu là một phần của định nghĩa lớp. Các mẫu không mở rộng cũng không kế thừa các lớp và chúng không truy cập vào các đối tượng được khởi tạo bên ngoài ... đó là cách khác. Các mẫu được định nghĩa trong chính lớp đó, về mặt khái niệm, chúng là một phần của lớp và về mặt khái niệm nên có quyền truy cập vào các thành viên tư nhân.
A-Diddy

85

Chỉnh sửa: Câu trả lời này bây giờ không chính xác. Không có hướng dẫn chính thức nào về chủ đề khi tôi đăng nó, nhưng như đã giải thích trong câu trả lời (xuất sắc và chính xác) của @ Yaroslov, đây không còn là trường hợp nữa: Codelizer hiện cảnh báo và trình biên dịch AoT sẽ thất bại trong các tham chiếu đến các biến riêng tư trong các mẫu thành phần . Điều đó nói rằng, ở mức độ khái niệm, mọi thứ ở đây vẫn còn hiệu lực, vì vậy tôi sẽ để lại câu trả lời này vì nó có vẻ hữu ích.


Vâng, điều này được mong đợi.

Hãy nhớ rằng privatevà các công cụ sửa đổi truy cập khác là các cấu trúc Bản mô tả, trong khi Thành phần / bộ điều khiển / mẫu là các cấu trúc góc mà Bản mô tả không biết gì về. Bộ điều chỉnh truy cập kiểm soát mức độ hiển thị giữa các lớp: Tạo một trường privatengăn các lớp khác có quyền truy cập vào nó, nhưng các mẫu và bộ điều khiển là những thứ tồn tại trong các lớp.

Điều đó không đúng về mặt kỹ thuật, nhưng (thay vì hiểu cách các lớp liên quan đến trang trí và siêu dữ liệu của họ), có thể hữu ích khi nghĩ về nó theo cách này, bởi vì điều quan trọng (IMHO) là chuyển từ suy nghĩ về khuôn mẫu và bộ điều khiển như tách biệt các thực thể nghĩ về chúng như là các phần thống nhất của cấu trúc Thành phần - đây là một trong những khía cạnh chính của mô hình tinh thần ng2.

Nghĩ về nó theo cách đó, rõ ràng chúng ta mong đợi privatecác biến trên một lớp thành phần sẽ hiển thị trong khuôn mẫu của nó, với cùng lý do chúng ta mong đợi chúng sẽ hiển thị trong các privatephương thức trên lớp đó.


3
Đầu tiên, tôi nghĩ giống như bạn đã vẽ. Nhưng tôi đã nâng cấp tslint lên 4.02 và codelyzer lên 2.0.0-beta.1 và tôi gặp lỗi khi nói rằng tôi không thể sử dụng riêng tư khi truy cập các biến trong chế độ xem. Vì vậy, câu trả lời của @ Yaroslav có vẻ phù hợp hơn.
maxime1992

8
Tôi đồng ý rằng mô hình thành phần không có nghĩa là không thể nhìn thấy các biến riêng tư của nó, có lẽ chúng nên được trộn vào cùng một lớp trong quá trình biên dịch, ý tôi là, bạn phải phơi bày các đặc điểm, đối tượng và chức năng cụ thể của thành phần tất cả các thành phần khác để bạn có thể sử dụng các thành phần trong mẫu của mình, không đề cập đến các chỉnh sửa bên ngoài hoặc các cuộc gọi đến chúng có thể gây ra hành vi bất ngờ tiềm ẩn trên thành phần đã hoàn thành
Felype

1
@drewmoore, xin chào, tôi đã mã hóa góc cạnh chỉ trong một vài tháng. Tôi đã phải đối mặt với vấn đề này. Có bất kỳ tranh luận thêm về điều này? Như tôi không tìm thấy bất cứ điều gì cụ thể về mô hình để làm theo. Imo, vì nó đáng giá như vậy, nó dường như vi phạm phân tách mã.
Edgar

2
@drewmoore, tôi phải nói rằng tôi hoàn toàn đồng ý với logic anser của bạn. và tôi sợ đội Angular đã gây rối một chút. trong chế độ AOT, họ không cho phép các thành viên riêng tư, trong khi trên các tài liệu họ yêu cầu khác, trong trường hợp thành viên tư nhân hoàn toàn củng cố quan điểm của bạn và chỉ thêm sự hỗn loạn vào chủ đề này. Từ Docs: "Angular coi mẫu của thành phần là thuộc về thành phần. Thành phần và mẫu của nó hoàn toàn tin tưởng lẫn nhau. Do đó, mẫu riêng của thành phần có thể liên kết với bất kỳ thuộc tính nào của thành phần đó, có hoặc không có trang trí đầu vào * @ *. "
Orel Eraki

@drewmoore, Liên kết cho các tài liệu: angular.io/guide/attribution-directives#appcill-why-add-input (Tôi biết chủ yếu tập trung vào Trình trang trí đầu vào, nhưng rất nhiều điều họ đang nói về không liên quan đến nó)
Orel Eraki

16

Mặc dù ví dụ mã cho biết câu hỏi là về TypeScript nhưng nó không có nhãn. Angular2 cũng có sẵn cho Dart và đây là một sự khác biệt đáng chú ý với Dart.

Trong Dart , mẫu không thể tham chiếu các biến riêng tư của lớp thành phần, bởi vì Dart trái ngược với TypeScript ngăn chặn hiệu quả sự truy cập của các thành viên riêng từ bên ngoài.

Tôi vẫn quay lại đề xuất @drewmoores để suy nghĩ về thành phần và mẫu của nó là một đơn vị mặc dù.

Cập nhật (TS) Dường như việc truy cập biên dịch ngoại tuyến vào các thuộc tính riêng tư sẽ bị hạn chế hơn trong Angular2 TS cũng như https://github.com/angular/angular/issues/11422


2
Có thể có trình biên dịch typecript để hạn chế các biến riêng tư có thể truy cập được vào khung nhìn không?
Matthew Harwood

Tôi không biết. Tôi đoán là không.
Günter Zöchbauer

2
Tôi nghĩ rằng để chúng riêng tư có thể ảnh hưởng đến việc thành phần có thể kiểm tra được như thế nào? Ví dụ: nếu tôi tạo một thành phần trong ngữ cảnh của thử nghiệm, tôi sẽ không thể gọi các phương thức riêng tư đó từ thử nghiệm của mình để xác nhận tương tác mẫu / lớp đang hoạt động. Tôi chưa thử điều này, vì vậy hãy tha thứ cho tôi nếu điều này là hiển nhiên :)
Sam Storie

Trong Dart bạn không thể truy cập các thành viên tư nhân trong các bài kiểm tra. Có rất nhiều cuộc thảo luận (độc lập với ngôn ngữ) liệu điều này có nên được hỗ trợ hay không và liệu API riêng có nên được kiểm tra hay không. Kiểm tra API công khai sẽ có thể tiếp cận từng đường dẫn mã. Tôi nghĩ rằng điều này là hợp lý nói chung. Trong Dart private là mỗi thư viện (có thể bao gồm một số tệp) làm cho API công khai khá rộng - IMHO quá rộng để kiểm tra đơn vị.
Günter Zöchbauer

3

Các biến riêng tư có thể được sử dụng trong khuôn mẫu của thành phần. Xem hướng dẫn sử dụng angular2 để biết hướng dẫn: https://angular.io/docs/ts/latest/cookbook/component-c truyền thông.html #! #Parent-to-child-setter

Một lời giải thích chi tiết hơn về các thành viên công cộng / tư nhân của các lớp trong bản thảo có thể được tìm thấy ở đây: https://www.typescriptlang.org/docs/handbook/groupes.html .

Tất cả các thành viên theo mặc định là công khai. Các thành viên công cộng có thể được truy cập từ bên ngoài lớp thành phần cùng với thể hiện của lớp. Nhưng các thành viên riêng tư chỉ có thể được truy cập trong các hàm thành viên của lớp.


Tôi đã xem liên kết đầu tiên ( angular.io/guide/component-interaction#!#parent-to-child-setter ) và tôi không thấy bất cứ nơi nào nó gợi ý rằng sử dụng các biến riêng tư trong các mẫu là ok. Ngược lại, họ sử dụng getters và setters để truy cập các biến riêng tư từ mẫu.
Sebastien Chartier

3

Một cách giải quyết có thể là sử dụng các biến riêng tư trong tệp ts và sử dụng getters.

private _userName = "Test Name";
get userName() {
  return this._userName;
}

Đây là một cách tiếp cận tốt vì tệp ts và html vẫn độc lập. Ngay cả khi bạn thay đổi tên biến _userName trong tệp ts, bạn không phải thực hiện bất kỳ thay đổi nào trong tệp mẫu.


Tôi nghĩ rằng nếu bạn thay đổi _userName thành _clientName, ví dụ, để thống nhất, bạn cần thay đổi getter để lấy clientName ... vì vậy không có chiến thắng
LeagueOfJava

Đó là một thực tế xấu cho người dùng gạch dưới cho các biến riêng tư.
Florian Leit Quay

1
@FlorianLeitride Đó là lý do tại sao các tài liệu Angular chính thức làm điều đó ? private _name = '';
ruffin

Sau đó đoạn mã này đã không được xem xét đúng. Họ theo một quy ước phong cách, được tuyên bố trong hướng dẫn phong cách ở đây . Và cũng trong phần Các lớp đánh máy trên trang của họ ở đây không sử dụng dấu gạch dưới.
Florian Leit Quay

1
@FlorianLeitride Vậy đâu là giải pháp được đề xuất cho việc ngăn chặn các phương thức setter như trong liên kết được đăng bởi ruffin? tức là bạn gọi trường sao lưu riêng của setter là gì?
El Ronnoco

1

Câu trả lời ngắn gọn là không nên bạn không thể truy cập các thành viên riêng tư từ mẫu vì nó được tách biệt về mặt kỹ thuật với tệp TS.


0

Trong tsconfig.app.json nếu bạn cung cấp tùy chọn 'fullTemplateTypeCheck' trong các tùy chọn trình biên dịch, bạn có thể thấy tất cả các tham chiếu không hợp lệ trong các tệp html của dự án của bạn tại thời điểm xây dựng dự án.

"angularCompilerOptions": {
"enableIvy": true,
"fullTemplateTypeCheck": true

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.