มีวิธีง่ายๆในการโหลด css ใหม่โดยไม่ต้องโหลดหน้าซ้ำหรือไม่?


90

ฉันกำลังพยายามสร้างโปรแกรมแก้ไข css ในหน้าพร้อมฟังก์ชั่นการแสดงตัวอย่างที่จะโหลดสไตล์ชีทซ้ำและนำไปใช้โดยไม่จำเป็นต้องโหลดหน้าซ้ำ วิธีที่ดีที่สุดในการดำเนินการนี้คืออะไร?


1
2014 และคำถามนี้อยู่ในโฮมเพจ ...
Kroltan

1
2019 เกือบปี 2020 และคำถามนี้ยังคง popping ในหน้าแรก ...
zer0

คำตอบ:


51

ในหน้า "แก้ไข" แทนที่จะรวม CSS ด้วยวิธีปกติ (ด้วย<link>แท็ก) ให้เขียนทั้งหมดลงใน<style>แท็ก การแก้ไขinnerHTMLคุณสมบัติของสิ่งนั้นจะอัปเดตเพจโดยอัตโนมัติแม้ว่าจะไม่มีการเดินทางไป - กลับที่เซิร์ฟเวอร์ก็ตาม

<style type="text/css" id="styles">
    p {
        color: #f0f;
    }
</style>

<textarea id="editor"></textarea>
<button id="preview">Preview</button>

Javascript โดยใช้ jQuery:

jQuery(function($) {
    var $ed = $('#editor')
      , $style = $('#styles')
      , $button = $('#preview')
    ;
    $ed.val($style.html());
    $button.click(function() {
        $style.html($ed.val());
        return false;
    });
});

และที่ควรจะเป็น!

หากคุณอยากเป็นแฟนซีรีส์ให้แนบฟังก์ชั่นนี้เข้ากับคีย์ดาวน์บน textarea แม้ว่าคุณจะได้รับผลข้างเคียงที่ไม่ต้องการ (หน้าจะเปลี่ยนไปเรื่อย ๆ เมื่อคุณพิมพ์)

แก้ไข : ทดสอบและใช้งานได้ (ใน Firefox 3.5 อย่างน้อยก็ควรใช้ได้กับเบราว์เซอร์อื่น ๆ ) ดูการสาธิตที่นี่: http://jsbin.com/owapi


3
IE barfs innerHTMLสำหรับ<style>องค์ประกอบ (และ<script>)
JPot

3
เกิดอะไรขึ้นถ้ามันถูก href'ed?
allenhwkim

Btw คุณสามารถแนบฟังก์ชั่นกับ keydown บน textarea แต่เค้นด้วย lo-dash (ตัวอย่าง)
Camilo Martin

109

อาจใช้ไม่ได้กับสถานการณ์ของคุณ แต่นี่คือฟังก์ชั่น jQuery ที่ฉันใช้สำหรับการโหลดสไตล์ชีตภายนอกใหม่:

/**
 * Forces a reload of all stylesheets by appending a unique query string
 * to each stylesheet URL.
 */
function reloadStylesheets() {
    var queryString = '?reload=' + new Date().getTime();
    $('link[rel="stylesheet"]').each(function () {
        this.href = this.href.replace(/\?.*|$/, queryString);
    });
}

3
คุณสามารถทำให้เป็นบุ๊กมาร์กโดยใช้ted.mielczarek.org/code/mozilla/bookmarklet.html
Luke Stanley

37
หนึ่งซับที่ไม่ใช่ jquery นี้ใช้ได้กับฉันใน chrome:var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") {link.href += "?"; }}
Claude

ฉันไม่แน่ใจว่าเป็นเพราะฉันเพิ่งเปิดหน้าบน chrome จากดิสก์ แต่สิ่งนี้ไม่ได้ผลสำหรับฉัน
Joao Carlos

14

ไม่จำเป็นต้องใช้ jQuery สำหรับสิ่งนี้อย่างแน่นอน ฟังก์ชัน JavaScript ต่อไปนี้จะโหลดไฟล์ CSS ทั้งหมดของคุณซ้ำ:

function reloadCss()
{
    var links = document.getElementsByTagName("link");
    for (var cl in links)
    {
        var link = links[cl];
        if (link.rel === "stylesheet")
            link.href += "";
    }
}

1
ฉันใช้สิ่งนี้ในคอนโซลดังนั้นฉันจึงไม่จำเป็นต้องเพิ่มอะไรอีกในโค้ดของฉัน
loco.loop

@ วงเล็บปีกกาเป็นทางเลือก รหัสใช้งานได้ดี
Dan Bray

1
คำตอบที่ดีเนื่องจากไม่ต้องพึ่งพา jQuery! :)
Gustavo Straube

9

ดูโปรเจ็กต์ Vogue สุดเก๋ของ Andrew Davey - http://aboutcode.net/vogue/


นี่คือสิ่งที่ฉันค้นหา มันโหลด CSS ใหม่ทันทีที่เปลี่ยนสไตล์ชีทโดยไม่จำเป็นต้องรีเฟรชหน้าด้วยตนเอง ขอบคุณมากสำหรับการแบ่งปัน :)
Devner

Vogue สามารถรันบน wamp ได้หรือไม่?
chrisdillon

ฉันลองโหลดสคริปต์ซ้ำเช่น Vogue แต่ใน Chrome มีปัญหาเนื่องจากไฟล์สไตล์ชีตที่มากที่สุดยังคงอยู่ในเบราว์เซอร์และใช้งานได้ ตัวอย่างเช่นในองค์ประกอบหนึ่งฉันเปลี่ยนพื้นหลังจากสีแดงเป็นสีขาวและฉันต้องปิดการใช้งานสีสุดท้ายสีแดง
ปีเตอร์

8

เวอร์ชันที่สั้นกว่าใน Vanilla JS และอยู่ในบรรทัดเดียว:

for (var link of document.querySelectorAll("link[rel=stylesheet]")) link.href = link.href.replace(/\?.*|$/, "?" + Date.now())

หรือขยาย:

for (var link of document.querySelectorAll("link[rel=stylesheet]")) {
  link.href = link.href.replace(/\?.*|$/, "?" + Date.now())
}

6

อีกหนึ่งโซลูชัน jQuery

สำหรับสไตล์ชีตเดียวที่มี id "css" ให้ลองทำดังนี้

$('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');

รวมไว้ในฟังก์ชันที่มี Global scrope และคุณสามารถใช้งานได้จาก Developer Console ใน Chrome หรือ Firebug ใน Firefox:

var reloadCSS = function() {
  $('#css').replaceWith('<link id="css" rel="stylesheet" href="css/main.css?t=' + Date.now() + '"></link>');
};

1
สวัสดีฉันมีสิ่งนี้ซึ่งบางอย่างใช้งานได้ดีเท่านั้น :( แม้ว่าฉันจะมีเวลาเพิ่มเพื่อให้ไม่ซ้ำกัน (นี่คือบน firefox): <code> function swapStyleSheet (แผ่น) {var sheet = sheet + '? t =' + Date.now (); $ ('# pagestyle') แทนที่ด้วย ('<link id = "css" rel = "stylesheet" href = "' + sheet + '"> </link>');} $ (" # stylesheet1 "). on (" click ", function (event) {swapStyleSheet (" <c: url value = 'site.css' /> ");}); $ (" # stylesheet2 ") on (" click ", function (เหตุการณ์) {swapStyleSheet (" <c: url value = 'site2.css' /> ");}); </code>
tibi

3

จากวิธีแก้ปัญหาก่อนหน้านี้ฉันได้สร้างบุ๊กมาร์กด้วยรหัส JavaScript:

javascript: { var toAppend = "trvhpqi=" + (new Date()).getTime(); var links = document.getElementsByTagName("link"); for (var i = 0; i < links.length;i++) { var link = links[i]; if (link.rel === "stylesheet") { if (link.href.indexOf("?") === -1) { link.href += "?" + toAppend; } else { if (link.href.indexOf("trvhpqi") === -1) { link.href += "&" + toAppend; } else { link.href = link.href.replace(/trvhpqi=\d{13}/, toAppend)} }; } } }; void(0);

ภาพจาก Firefox:

ป้อนคำอธิบายภาพที่นี่

มันทำอะไร?

มันโหลด CSS ใหม่โดยการเพิ่มพารามิเตอร์สตริงการสืบค้น (ดังวิธีแก้ปัญหาด้านบน):


1

ง่ายๆถ้าคุณใช้ php เพียงต่อท้ายเวลาปัจจุบันที่ส่วนท้ายของ css เช่น

<link href="css/name.css?<?php echo 
time(); ?>" rel="stylesheet">

ดังนั้นทุกครั้งที่คุณโหลดซ้ำไม่ว่าจะเป็นอะไรก็ตามเวลาเปลี่ยนไปและเบราว์เซอร์คิดว่ามันเป็นไฟล์ที่แตกต่างกันตั้งแต่บิตสุดท้ายยังคงเปลี่ยนไป .... คุณสามารถทำสิ่งนี้กับไฟล์ใดก็ได้คุณบังคับให้เบราว์เซอร์รีเฟรชโดยใช้ภาษาสคริปต์ที่คุณต้องการ


0

ใช่โหลดแท็ก css ซ้ำ และอย่าลืมทำให้ URL ใหม่ไม่ซ้ำกัน (โดยปกติจะต่อท้ายพารามิเตอร์การสืบค้นแบบสุ่ม) ฉันมีรหัสที่จะทำสิ่งนี้ แต่ไม่ใช่กับฉันในตอนนี้ จะแก้ไขในภายหลัง ...

แก้ไข: สายเกินไป ... harto และ nickf เอาชนะฉันไปได้ ;-)


0

ตอนนี้ฉันมีสิ่งนี้:

    function swapStyleSheet() {
        var old = $('#pagestyle').attr('href');
        var newCss = $('#changeCss').attr('href');
        var sheet = newCss +Math.random(0,10);
        $('#pagestyle').attr('href',sheet);
        $('#profile').attr('href',old);
        }
    $("#changeCss").on("click", function(event) { 
        swapStyleSheet();
    } );

สร้างองค์ประกอบใด ๆ ในหน้าของคุณด้วย id changeCss โดยมีแอตทริบิวต์ href พร้อมด้วย css url ใหม่ และองค์ประกอบลิงก์ที่มี css เริ่มต้น:

<link id="pagestyle" rel="stylesheet" type="text/css" href="css1.css?t=" />

<img src="click.jpg" id="changeCss" href="css2.css?t=">

0

คำตอบอื่น: มี bookmarklet ที่เรียกว่าเป็นReCSS ฉันไม่ได้ใช้มันมากนัก แต่ดูเหมือนจะใช้ได้ผล

มี bookmarklet ในหน้านั้นเพื่อลากและวางลงบนแถบที่อยู่ของคุณ (ดูเหมือนจะสร้างไม่ได้ที่นี่) ในกรณีที่เกิดปัญหานี่คือรหัส:

javascript:void(function()%7Bvar%20i,a,s;a=document.getElementsByTagName('link');for(i=0;i%3Ca.length;i++)%7Bs=a[i];if(s.rel.toLowerCase().indexOf('stylesheet')%3E=0&&s.href)%20%7Bvar%20h=s.href.replace(/(&%7C%5C?)forceReload=%5Cd%20/,'');s.href=h%20(h.indexOf('?')%3E=0?'&':'?')%20'forceReload='%20(new%20Date().valueOf())%7D%7D%7D)();

0

พูดง่ายๆคือคุณสามารถใช้rel = "preload"แทนrel = "stylesheet"ได้

<link rel="preload" href="path/to/mystylesheet.css" as="style" onload="this.rel='stylesheet'">

คุณบอกว่าจะใช้แต่ตัวอย่างที่กล่าวว่าrel="reload" rel="preload"
haykam

ขอบคุณ @haykam สำหรับการแก้ไขฉันได้อัปเดตแล้ว
Gagan

0

เนื่องจากคำถามนี้ปรากฏใน stackoverflow ในปี 2019 ฉันจึงต้องการเพิ่มการมีส่วนร่วมของฉันโดยใช้ JavaScript ที่ทันสมัยกว่า

โดยเฉพาะอย่างยิ่งสำหรับ CSS Stylesheet ที่ไม่ได้อยู่ในบรรทัด - เนื่องจากมันครอบคลุมจากคำถามเดิมอยู่แล้ว

ก่อนอื่นโปรดสังเกตว่าเรายังไม่มีออบเจ็กต์สไตล์ชีตที่สร้างได้ อย่างไรก็ตามเราหวังว่าจะได้ขึ้นเครื่องเร็ว ๆ นี้

ในระหว่างนี้สมมติว่ามีเนื้อหา HTML ต่อไปนี้:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link id="theme" rel="stylesheet" type="text/css" href="./index.css" />
    <script src="./index.js"></script>
  </head>
  <body>
    <p>Hello World</p>
    <button onclick="reload('theme')">Reload</button>
  </body>
</html>

เราสามารถมีได้ในindex.js:

// Utility function to generate a promise that is 
// resolved when the `target` resource is loaded,
// and rejected if it fails to load.
//
const load = target =>
  new Promise((rs, rj) => {
    target.addEventListener("load", rs, { once: true });
    target.addEventListener(
      "error",
      rj.bind(null, `Can't load ${target.href}`),
      { once: true }
    );
  });


// Here the reload function called by the button.
// It takes an `id` of the stylesheet that needs to be reloaded
async function reload(id) {
  const link = document.getElementById(id);

  if (!link || !link.href) {
    throw new Error(`Can't reload '${id}', element or href attribute missing.`);
  }

  // Here the relevant part.
  // We're fetching the stylesheet from the server, specifying `reload`
  // as cache setting, since that is our intention.
  // With `reload`, the browser fetches the resource *without* first looking
  // in the cache, but then will update the cache with the downloaded resource.
  // So any other pages that request the same file and hit the cache first,
  // will use the updated version instead of the old ones.
  let response = await fetch(link.href, { cache: "reload" });

  // Once we fetched the stylesheet and replaced in the cache,
  // We want also to replace it in the document, so we're
  // creating a URL from the response's blob:
  let url = await URL.createObjectURL(await response.blob());

  // Then, we create another `<link>` element to display the updated style,
  // linked to the original one; but only if we didn't create previously:
  let updated = document.querySelector(`[data-link-id=${id}]`);

  if (!updated) {
    updated = document.createElement("link");
    updated.rel = "stylesheet";
    updated.type = "text/css";
    updated.dataset.linkId = id;
    link.parentElement.insertBefore(updated, link);

    // At this point we disable the original stylesheet,
    // so it won't be applied to the document anymore.
    link.disabled = true;
  }

  // We set the new <link> href...
  updated.href = url;

  // ...Waiting that is loaded...
  await load(updated);

  // ...and finally tell to the browser that we don't need
  // the blob's URL anymore, so it can be released.
  URL.revokeObjectURL(url);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.