Hai phần tử HTML có cùng thuộc tính id: Nó thực sự tệ đến mức nào?


122

Chỉ cần duyệt mã nguồn google maps. Trong tiêu đề của họ, họ có 2 div với id = "search" cái này chứa cái kia và cũng có thuộc tính jstrack = "1". Có một hình thức phân tách chúng như vậy:

<div id="search" jstrack="1">
    <form action="/maps" id="...rest isn't important">
        ...
        <div id="search">...

Vì đây là google, tôi cho rằng nó không phải là một sai lầm.

Vì vậy, làm thế nào xấu thực sự có thể vi phạm quy tắc này? Miễn là bạn cẩn thận trong việc lựa chọn css và dom, tại sao không sử dụng lại các lớp giống như id? Có ai làm điều này trên mục đích, và nếu vậy, tại sao?


102
"Vì đây là google, tôi cho rằng nó không phải là một sai lầm." -> Google không thể sai được. Họ mắc lỗi như phần còn lại của chúng ta.
Joeri Sebrechts

43
Trên thực tế, những người ở google đã TÌM KIẾM trong tâm trí họ để họ không nghĩ về bất kỳ id nào khác: P
Pankaj Upadhyay

10
Tôi có cảm giác rằng trang đó được hiển thị từ các đoạn html khác nhau nên một nhà phát triển trong một đoạn đã sử dụng id đó và điều tương tự cũng xảy ra với nhà phát triển khác trong đoạn khác.
Luciano

10
Toàn bộ câu hỏi "thực sự tệ đến mức nào" chỉ khiến tôi nhớ về điều này: xkcd.com/292
Daniel Roseman

3
@DanielRoseman xkcd không nó là tốt: what-if.xkcd.com/23/#question
SQB

Câu trả lời:


140

Thông số kỹ thuật cho biết ĐỘC ĐÁO

Đặc tả HTML 4.01 cho biết ID phải là tài liệu duy nhất trên toàn tài liệu.

Đặc tả HTML 5 nói điều tương tự nhưng nói cách khác. Nó nói rằng ID phải là duy nhất trong cây con nhà của nó , về cơ bản là tài liệu nếu chúng ta đọc định nghĩa của nó .

Tránh trùng lắp

Nhưng vì trình kết xuất HTML rất dễ tha thứ khi kết xuất HTML nên họ cho phép các ID trùng lặp. Điều này nên tránh nếu có thể và tuyệt đối tránh khi lập trình truy cập các phần tử bằng ID trong JavaScript. Tôi không chắc getElementByIdhàm nào sẽ trả về khi tìm thấy một số phần tử phù hợp? Nên nó:

  • trả lại một lỗi?
  • trả lại yếu tố phù hợp đầu tiên?
  • trả lại yếu tố phù hợp cuối cùng?
  • trả về một tập hợp các yếu tố phù hợp?
  • Trả lại cái gì?

Nhưng ngay cả khi các trình duyệt hoạt động đáng tin cậy trong những ngày này, không ai có thể đảm bảo hành vi này trong tương lai vì điều này trái với đặc điểm kỹ thuật. Đó là lý do tại sao tôi khuyên bạn không bao giờ trùng lặp ID trong cùng một tài liệu.


1
@missingno: Tôi đã thêm một liên kết đến đặc tả HTML 5 nói về cùng một thứ nhưng theo cách diễn đạt khác nhau.
Robert Koritnik

6
Theo thông số DOM , "Nếu có nhiều hơn một thành phần có thuộc tính ID với giá trị đó, thì giá trị được trả về là không xác định" (điều đó có nghĩa là không có kết quả "chính xác" được xác định, thay vì giá trị thực undefined). Rất hiếm khi dựa vào hành vi không xác định.
lonesomeday

1
Đáng chú ý với HTML5, data-thuộc tính này có ích khi người ta có thể muốn gán nhiều thứ cho cùng một ID. Điều này cho phép bạn có nhiều ID khác nhau với một data-somethingthuộc tính chung. Tuy nhiên, tất cả các trình duyệt mà tôi biết đều bỏ qua các thuộc tính không xác định, vì vậy chúng có thể an toàn trong mọi trình duyệt hiện đại thiếu hỗ trợ HTML đầy đủ.
Tim Post

2
@JoachimSauer: Khi bạn sử dụng các thuộc tính dữ liệu, bạn có thể có các cặp khóa-giá trị không đúng khi bạn sử dụng các lớp CSS. Trong trường hợp đó, tất cả chúng đều giống như các thuộc tính boolean. Một phần tử có lớp CSS hoặc không. Nếu bạn muốn các giá trị với các lớp CSS thì bạn phải kết hợp chúng thành tên lớp CSS và phân tích cú pháp sau đó. Tôi hy vọng bây giờ bạn có thể thấy lợi ích của việc sử dụng datacác thuộc tính. Và họ cũng được jQuery hỗ trợ trực tiếp ra khỏi hộp khi bạn chỉ cần tham khảo data-something="123"thuộc tính $(elem).data("something").
Robert Koritnik

1
@RobertKoritnik: Tất nhiên rồi! Tôi đã không nghĩ về trường hợp sử dụng đó. Tôi chỉ nghĩ về trường hợp id="search".
Joachim Sauer

30

Bạn hỏi "thật tệ". Vì vậy, để xác thịt trả lời @ RobertKoritnik (hoàn toàn chính xác) một chút ...

Mã đó không chính xác. Không chính xác không có màu xám. Mã này vi phạm tiêu chuẩn và do đó không chính xác. Nó sẽ không kiểm tra xác nhận, và nó nên.

Điều đó nói rằng, không có trình duyệt hiện tại trên thị trường sẽ phàn nàn về nó, hoặc có bất kỳ vấn đề với nó. Các trình duyệt sẽ có quyền khiếu nại về vấn đề này, nhưng không có phiên bản hiện tại nào trong số chúng hiện đang làm. Điều đó không có nghĩa là các phiên bản trong tương lai có thể không đối xử tệ với mã này.

Hành vi của bạn khi cố gắng sử dụng ID đó làm công cụ chọn, trong css hoặc javascript, là không thể chấp nhận được và có thể thay đổi tùy theo trình duyệt. Tôi cho rằng một nghiên cứu có thể được thực hiện để xem mỗi trình duyệt phản ứng với điều đó như thế nào. Tôi nghĩ trong trường hợp tốt nhất, nó sẽ coi nó giống như "class =" và chọn danh sách của chúng. (Tuy nhiên, điều đó có thể gây nhầm lẫn cho các thư viện JavaScript - nếu tôi là tác giả của jQuery, tôi có thể đã tối ưu hóa mã bộ chọn của mình để nếu bạn đến với tôi với bộ chọn bắt đầu bằng "#", tôi mong đợi một đối tượng và nhận được một đối tượng danh sách có thể bork tôi hoàn toàn.)

Nó cũng có thể chọn cái đầu tiên, hoặc có thể là cái cuối cùng, hoặc không chọn cái nào trong số chúng, hoặc làm hỏng hoàn toàn trình duyệt. Không có cách nào để nói mà không thử nó.

"Làm thế nào xấu" sau đó phụ thuộc hoàn toàn vào mức độ nghiêm trọng của một trình duyệt cụ thể thực hiện thông số HTML và những gì nó làm khi đối mặt với vi phạm thông số kỹ thuật đó.

EDIT: TÔI CHỈ tình cờ bắt gặp điều này ngày hôm nay. Tôi đang sử dụng các thành phần khác nhau từ các biểu mẫu tìm kiếm trên nhiều loại thực thể khác nhau để tạo ra một tiện ích báo cáo tất cả trong một lớn cho trang web này, tôi đang tải lên các biểu mẫu tìm kiếm của các trang từ xa trong các div ẩn và đưa chúng vào trình tạo báo cáo khi loại thực thể phù hợp được chọn làm nguồn cho báo cáo. Vì vậy, có một phiên bản ẩn của biểu mẫu và một phiên bản được hiển thị trong trình tạo báo cáo. Trong tất cả các trường hợp, JavaScript đi kèm với các phần tử bằng ID, trong đó hiện có HAI trên trang - một ẩn và một được hiển thị.

Điều mà jQuery dường như đang làm là chọn cho tôi cái đầu tiên, mà trong mọi trường hợp chính xác là cái tôi không muốn.

Tôi đang giải quyết vấn đề này bằng cách viết các công cụ chọn để chỉ định vùng của trang mà tôi muốn đưa trường của mình vào (ví dụ: $ ('# containerDiv #specificEuity')). Nhưng có một câu trả lời cho câu hỏi của bạn - jQuery trên Chrome chắc chắn hành xử theo một cách cụ thể khi đối mặt với vi phạm thông số kỹ thuật này.


... một câu hỏi liên quan: stackoverflow.com/q/29295824/287948 về nghĩa vụ của ID trong hồ sơ nhanh CSS.
Peter Krauss

3
"Không chính xác không có màu xám." Tôi thấy điều này rất nhiều và đó là một trong những điều đúng về mặt kỹ thuật nhưng không "đúng" trong cuộc sống hoặc trong lập trình. Bạn gián tiếp bao quát điều đó khá kỹ trong câu trả lời của bạn và tôi có thể giải thích nhưng cảnh này từ Lý thuyết Big Bang thực hiện công việc tốt đến nỗi tôi sẽ để nó nói cho tôi và hy vọng sẽ khiến ai đó cười ... Stuart vs Sheldon youtube.com/ xem? v = F_1zoX5Ax9U
Cú đêm

Đây là một câu trả lời 8 năm tuổi, nhưng tôi nghĩ rằng nó rất mất cân bằng về cách bạn cường điệu hóa câu hỏi của OP nhưng không phàn nàn nhiều về hành vi nguy hiểm và dễ dãi của trình duyệt về các id lặp đi lặp lại, tệ hơn nhiều so với những gì OP đang cố gắng làm.
xóa sổ

20

Làm thế nào là nó thực sự xấu?

  1. Nó làm tôi khóc
  2. Nó không hợp lệ
  3. Nhiều thư viện javascript sẽ không hoạt động như mong đợi
  4. Nó làm cho mã của bạn khó hiểu

Kinh nghiệm nói rằng getEuityById trong các trình duyệt chính sẽ trả về phần tử phù hợp đầu tiên trong tài liệu. Nhưng điều này có thể không phải luôn luôn là trường hợp trong tương lai.

Khi jQuery được cung cấp một id, ví dụ #foo, nó sử dụng getEuityById và bắt chước hành vi đó. Nếu bạn phải giải quyết vấn đề này (thật đáng buồn), bạn có thể sử dụng $ (" * #foo") để thuyết phục jQuery sử dụng getElementsByTagName và trả về danh sách tất cả các yếu tố phù hợp.

Tôi thường phải viết mã cho các trang web khác và tôi phải giải quyết vấn đề này. Trong một thế giới công bằng, tôi sẽ không phải thiết kế lại các chức năng để bắt đầu bằng cách kiểm tra xem ID có phải là duy nhất không. ID phải luôn là duy nhất. Thế giới thật tàn khốc và đó là lý do tại sao tôi khóc.


5
Câu trả lời này làm tôi khóc ... cười!
A1rPun

8

Bạn có thể làm rất nhiều thứ - nhưng điều đó không có nghĩa là bạn nên làm.

Là một lập trình viên (nói chung), chúng tôi xây dựng cuộc sống của mình dựa trên chính xác và tuân theo các quy tắc - đây là một quy tắc đơn giản để tuân theo, nó khá cơ bản với những gì chúng tôi làm - chúng tôi thích (phụ thuộc vào) các định danh duy nhất trong một phạm vi nhất định ...

Phá vỡ quy tắc là điều chúng ta có thể làm vì trình duyệt quá phù hợp - nhưng thực sự tất cả chúng ta sẽ tốt hơn nếu các trình duyệt nghiêm ngặt về việc cần HTML được hình thành tốt và hợp lệ, nỗi đau nhỏ mà nó sẽ gây ra từ lâu được hoàn trả!

Vì vậy, nó thực sự là xấu? Là một lập trình viên, làm thế nào bạn có thể hỏi? Đó là một tội ác chống lại nền văn minh (-:


Phụ lục:

Bạn viết rằng các trình duyệt quá sức chứa như nó là điều xấu

Tôi làm, bởi vì đó là - chúng tôi không nói về các quy tắc phức tạp, chúng tôi đang nói về việc làm cho mọi thứ được hình thành tốt và áp dụng các quy tắc có thể được kiểm tra một cách máy móc và từ đó giúp cho kết quả được xử lý một cách dễ dàng hơn. Nếu các trình duyệt nghiêm ngặt thì các công cụ sẽ rất nhanh chóng thích nghi để hỗ trợ điều đó - không phải vì vậy mà chúng không làm như vậy, một số đến mức chúng khai thác thất bại thay thế. Chỉ cần nghĩ về điều này - email sẽ là một phương tiện đẹp hơn nhiều nếu MS và Netscape không làm hỏng nó bằng cách cho phép HTML không bị hạn chế khi một "ngôn ngữ đánh dấu email" ít phức tạp hơn với sự hỗ trợ rõ ràng cho văn bản được trích dẫn sẽ cung cấp cho chúng tôi một công cụ tốt hơn nhiều ... nhưng con tàu đó đã đi thuyền và tương tự như vậy chúng ta có thể 'nên có ) nhưng chúng ta không thể


Bạn viết rằng các trình duyệt quá sức chứa như điều đó là điều xấu, nhưng chắc chắn bạn không tin điều đó?
KaptajnKold

4
Tôi không thể nói cho Murph, nhưng tôi chắc chắn nghĩ rằng đó là một điều thực sự tồi tệ. Sau đó, một lần nữa, không có mức độ tha thứ này, web có thể không có sự thúc đẩy để phát triển như chúng ta biết.
Andrea

1
@Andrea: Internet sẽ không phát triển như chúng ta biết. Nó sẽ phát triển chậm hơn. Nhưng nó cũng đã có một cơ sở vững chắc hơn về những gì là và không đúng mã. Nhanh nhưng cẩu thả có thể hoạt động, nhưng tôi thích chậm hơn nhưng đúng. Đặc biệt là vì không giống như chúng ta chỉ nói về một vài năm tăng trưởng.
Nicol Bolas

3
@Andrea Tôi cá rằng nó sẽ phát triển gần như nhanh chóng - các công cụ đơn giản sẽ phát triển để giải quyết vấn đề. Trong khi đó, trong nhiều trường hợp, các công cụ là nguyên nhân gốc rễ của việc đánh dấu kém. Thực tế là mọi người có xu hướng làm ít nhất là cần thiết - bước để "hình thành tốt" là một bước tương đối nhỏ và đủ dễ dàng để kiểm tra và thực thi và mọi người sẽ chấp nhận điều đó mà không bị căng thẳng đáng kể
Murph

1
Không có gì ghê gớm khi các trình duyệt có sức chứa. Thật kinh khủng khi tất cả họ đều có sức chứa theo những cách khác nhau .
Dan Ray

7

Trong Scripting: getElementByIDsẽ chỉ trả lại trận đấu đầu tiên. Trong CSS: #idsẽ ảnh hưởng đến TẤT CẢ các yếu tố với ID đó. Trong Trình duyệt Kết xuất sẽ không có hiệu lực.

Đây là hành vi của tiêu chuẩn w3c. Không phải là một điều có thể, đó là thực tế được xác định.

https://dom.spec.whatwg.org/#interface-nonelementparentnode


7
Đây là một hành vi có thể. getElementByIdhoàn toàn có thể trả về bất kỳ phần tử nào, hoặc thậm chí là một đối tượng null. Hiệu ứng CSS có thể là trên bất kỳ yếu tố nào, hoặc không có hoặc tất cả chúng. Hoặc trình duyệt có thể bị sập. Ngoài tiêu chuẩn, hành vi không
rds

2
Nó không nằm ngoài tiêu chuẩn vì tiêu chuẩn chỉ định phải làm gì trong những tình huống đó. Vì vậy, không, getEuityById không thể trả về bất kỳ phần tử nào, tiêu chuẩn nói rõ ràng rằng tôi sẽ trả lại trận đấu đầu tiên. Tôi đồng ý rằng hành vi ngoài tiêu chuẩn là không xác định, điều bạn không hiểu là tất cả những trường hợp đó là một phần của tiêu chuẩn.
Bart Calixto

1
Câu trả lời này sẽ tốt hơn một chút nếu nó thực sự bao gồm, như một tài liệu tham khảo, một trích dẫn về phần có liên quan của tiêu chuẩn (hoặc ít nhất là một số phần).
yoniLavi

2
@yoniLavi cập nhật.
Bart Calix đến

2
Cảm ơn @Bart. Bạn hoàn toàn đúng :) Tiêu chuẩn cho biết "Trả về phần tử đầu tiên bên trong hậu duệ của nút có ID là ElementId."
yoniLavi
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.