Chúng ta có thể sử dụng window.location.replace
để tránh lịch sử và nhắm mục tiêu các neo trên trang mà không cần tải lại trang, nhưng không phải trong iframe?
Vấn đề là vi phạm CSP (chính sách bảo mật nội dung), trạng thái script-src 'unsafe-inline'
phải được bật. Ngoại trừ tôi không có CSP được xác định và ngay cả khi tôi xác định một CSP và cho phép script-src 'unsafe-inline'
nó vẫn đưa ra lỗi vi phạm tương tự. Kết quả tương tự trong eg11 / chrome / ff.
Iframe trên cùng một tên miền (trong cùng thư mục).
- Nhắm mục tiêu iframe trong bàn điều khiển và sử dụng
window.location.replace('/samepage.html#onpage_anchor')
trong bàn điều khiển. - nó hoạt động Nó nhắm mục tiêu neo trên trang mà không cần tải lại trang và không có lịch sử.
- Đặt cùng mã nội tuyến trên các liên kết neo và nó hoạt động.
- Sử dụng cùng một mã trong tập lệnh bên ngoài, nhận được lỗi vi phạm csp. Điều này hoạt động tốt nếu không trong iframe.
Tôi đã cố gắng tạo ra một CSP để cho phép các hành động, nhưng thậm chí không những dễ dãi nhất chính sách bảo mật nội dung có thể sẽ cho phép nó.
Chỉnh sửa: vì vậy tôi tập hợp các ví dụ trên plunker cho phép nhiều tệp để tôi có thể sử dụng href href tham chiếu các trang cha / con.
Ghi chú về các ví dụ về plunker:
Vấn đề không được sao chép trong các ví dụ này. Kịch bản hoạt động hoàn hảo, ngay cả trong iframe. Tuy nhiên, cùng một mã không hoạt động trên máy chủ cục bộ của tôi hoặc khi tôi chạy nó trực tiếp trên VPS.
Tôi nghi ngờ vi phạm CSP không được kích hoạt trên plunker vì plunker đang trình bày nội dung cho trình duyệt thông qua một loại lớp trừu tượng nào đó.
Lần đầu tiên bạn nhấp vào các liên kết accordion trong cha mẹ, nó gây ra một sự làm mới. Điều này là do cách trang ban đầu tải nó không tham chiếu index.html. Các lần nhấp tiếp theo hoạt động như mong đợi mà không cần tải lại trang. Không phải là vấn đề trong iframe vì ban đầu nó tham chiếu child.html
Đây là những ví dụ tốt để hiển thị mã mà không yêu cầu thay đổi để làm cho nó hoạt động (vì cần phải thay đổi href để làm cho chúng hoạt động trong đoạn trích stackoverflow, được đề cập bên dưới). Nó cũng tốt vì nó cho thấy javascript hoạt động như bình thường. Nhưng nó không hiển thị vấn đề thực sự. Bạn vẫn sẽ cần tải nó lên trong trình soạn thảo của mình và chạy nó trên máy chủ cục bộ hoặc môi trường lưu trữ trực tiếp để xem vấn đề thực sự.
Ví dụ về Plunker
Với kịch bản: Không có lịch sử
Không có kịch bản: Với lịch sử
Ví dụ mã đơn giản
Accordion đơn giản với một mục. Đủ để tái tạo vấn đề.
Nhấp vào mở / đóng sẽ mở rộng / thu gọn accordion, không yêu cầu JS. JS nên làm điều tương tự chính xác nhưng không có lịch sử. Hoạt động tốt, nhưng không trong iframe.
Đoạn mã ghi chú:
Bạn có thể chạy đoạn trích để có ý tưởng về những gì tôi đang mô tả, nhưng nó không thực sự chứng minh vấn đề.
Đoạn mã không hoạt động như trong trình duyệt thực, javascript không hoạt động.
Đoạn mã hiển thị mã, nhưng nó phải được chạy trong iframe để xem vấn đề. Chạy nó bên ngoài iframe để thấy sự khác biệt và cách nó hoạt động.
- Do cách các liên kết hoạt động với JS (thay thế toàn bộ url), chúng thực sự phải giống như thế này
href="https://stackoverflow.com/thispage.html#ac1"
thay vì chỉhref="#ac1"
xuất hiện trong đoạn trích (không thể nhắm mục tiêu trang html thực tế trong đoạn trích). Vì vậy, nếu bạn thử điều này trong trình chỉnh sửa của mình (vui lòng làm), thì hãy nhớ thay đổi các liên kết thành định dạng nàythis_document.html#anchor
để chúng vẫn là các neo trang giống nhau, nhưng page.html được bao gồm trong liên kết.
Kịch bản
$(document).ready(function() {
// anchor links without history
$.acAnch = function(event) {
event.preventDefault();
var anchLnk = $(event.target);
var anchTrgt = anchLnk.attr('href');
window.location.replace(anchTrgt);
}
// listen for anchor clicks
$('.accordion').on('click', 'a', $.acAnch);
});
Điều này rất đơn giản:
1. Hàm acAnch lấy href
thuộc tính và thả nó vào window.location.replace()
.
2. Lắng nghe các nhấp chuột trên các neo trong accordion để chạy chức năng acAnch.
Vì vậy, tất cả các kịch bản làm là chạy window.location.replace('/this_same_page.html#on_page_anchor')
Nếu bạn đặt nó trong bàn điều khiển thì nó hoạt động, không vi phạm CSP. Nhưng chạy nó từ kịch bản bên ngoài không hoạt động.
Nội tuyến trên các liên kết hoạt động tốt:
onclick="event.preventDefault();window.location.replace('/thispage.html#acc0');"
onclick="event.preventDefault();window.location.replace('/thispage.html#acc1');"
Đặt nó trên các liên kết tương ứng hoạt động hoàn hảo , nhưng tôi thực sự không thích sử dụng tập lệnh nội tuyến như thế. Phải có một cách để làm điều này với một kịch bản bên ngoài.
Tôi đã thử chạy javascript trên cha mẹ thay vì trong iframe (với các sửa đổi để chọn các liên kết trong khóa con). Kết quả lỗi CSP tương tự.
Tại sao tôi làm điều này?
Vâng, trang web phức tạp hơn nhiều so với ví dụ. Các neo trong iframe hoạt động tốt nhưng chúng thêm lịch sử. Nếu bạn chạy mã ở trên mà không có javascript, (hoặc chỉ chạy đoạn mã), hãy mở và đóng accordion một vài lần và sử dụng nút quay lại, nó sẽ quay trở lại qua trạng thái đóng mở.
Tôi sẽ không quan tâm đến lịch sử, nhưng nếu nó nằm trong iframe, khi bạn rời khỏi trang mẹ và sau đó quay lại nó, lịch sử trong iframe bị phá vỡ. Quay trở lại không quay trở lại qua các trạng thái accordion nữa, mà thay vào đó chỉ tiếp tục tải lại iframe. Ban đầu, các neo không gây ra tải lại iframe mà chỉ bước qua lịch sử trạng thái accordion, hoạt động tốt, cho đến khi bạn rời khỏi trang và quay lại. Sau đó trở lại không còn đi qua các trạng thái accordion, mà chỉ đi qua một đống iframe giống nhau tải lại. Đó là hành vi rất thân thiện với người dùng.
Tôi không cần sử dụng location.replace nếu có một phương pháp khác sẽ hoạt động. Mặc dù vậy, tôi đã thử nhiều cách tiếp cận khác và tôi thấy rằng các phương pháp có thể đạt được kết quả tương tự, thường dẫn đến cùng một lỗi.
Mục tiêu chỉ đơn giản là kích hoạt các liên kết neo trên trang mà không cần tải lại và không có lịch sử bên trong iframe.
Kịch bản nội tuyến hoạt động. Chúng ta có thể làm cho nó hoạt động trong một tệp .js bên ngoài không?
<a href="#ac0" class="ac-close">Close</a>
nên làm việc.