โซลูชั่นสำหรับสร้างจาวาสคริปต์ / CSS แบบไดนามิก


15

สมมติว่าคุณต้องสร้างจาวาสคริปต์หรือโค้ด CSS ที่ขึ้นอยู่กับบริบทปัจจุบัน

ตัวอย่างเช่นคุณมีแบบฟอร์มในหน้าแรกที่ส่งคำขอ ajax เมื่อส่งและแบบฟอร์มอื่นในหน้าเดียว หรือในกรณีของ CSS คุณต้องการสร้างธีมที่อนุญาตให้ผู้ใช้สร้างเลย์เอาต์ของตนเองเปลี่ยนสี ฯลฯ

วิธีแก้ปัญหาฉันเห็นแล้ว:

  1. รวมรหัสในส่วนหัวของเอกสาร (หรือท้ายในกรณีของ JS)

  2. ทำคำขอพิเศษที่ผลรหัสเช่นsite.com?get_assets สิ่งนี้ช้าเพราะโหลด WP สองครั้ง

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

  4. Javascript เท่านั้น - ทำให้เป็นแบบคงที่โดยใส่ลงในไฟล์ปกติที่โหลดทุกครั้ง ในกรณีนี้คุณจะต้องทำให้รหัสของคุณจัดการกับสถานการณ์ใด ๆ

คุณรู้จักคนอื่นหรือไม่ คุณจะไปทางไหน


ปัญหาหนึ่งที่ฉันพบกับโซลูชันที่ 1 คือการเบราว์เซอร์แคชรหัสไม่ได้รับการรีเฟรชเมื่อโหลดหน้าเว็บอีกครั้ง
Aurovrata

คำตอบ:


9

หนึ่งตัวเลือกเพิ่มเติมขึ้นอยู่กับชนิดของพารามิเตอร์ที่คุณต้องผ่านเข้าไปเรียกมันว่า (2a) คุณยังสามารถสร้างสคริปต์ PHP ที่สร้างผลลัพธ์แบบไดนามิกtext/cssหรือtext/javascriptมากกว่าtext/htmlและให้ข้อมูลที่ต้องการโดยใช้พารามิเตอร์ GET แทนการโหลด WordPress แน่นอนว่าใช้งานได้เฉพาะในกรณีที่คุณต้องผ่านพารามิเตอร์ที่มีขนาดค่อนข้างเล็ก ตัวอย่างเช่นสมมติว่าคุณต้องส่งเฉพาะ URL ของโพสต์หรือไดเรกทอรีของไฟล์หรือสิ่งที่คล้ายกันคุณสามารถทำสิ่งนี้:

ใน header.php:

 <script type="text/javascript" src="<?php print get_stylesheet_directory_uri(); 
 ?>/fancy-js.php?foo=bar&amp;url=<?php print urlencode(get_permalink($post->ID)); ?>"></script>

ใน fancy-js.php:

 <?php
 header("Content-type: text/javascript");
 ?>
 foo = <?php print json_encode($_GET['foo']); ?>;
 url = <?php print json_encode($_GET['url']); ?>;

เป็นต้น

แต่สิ่งนี้อนุญาตให้คุณเข้าถึงข้อมูลที่ส่งผ่านโดยตรงในพารามิเตอร์ GET เท่านั้น และมันจะใช้ได้ก็ต่อเมื่อจำนวนของสิ่งที่คุณต้องผ่านมีขนาดค่อนข้างเล็กและการแสดงสิ่งเหล่านั้นค่อนข้างกะทัดรัด (โดยทั่วไปจะมีสตริงหรือค่าตัวเลขจำนวนหนึ่ง - ชื่อผู้ใช้พูดหรือไดเรกทอรีไม่ใช่รายการโพสต์ล่าสุดของผู้ใช้ทั้งหมดหรืออะไรทำนองนั้น)

สำหรับตัวเลือกใดตัวเลือกหนึ่งที่ดีที่สุด - ฉันไม่รู้ ขึ้นอยู่กับกรณีการใช้งานของคุณ ตัวเลือก (1) มีข้อดีของความเรียบง่ายและชัดเจนช่วยให้คุณเข้าถึงข้อมูล WordPress ใด ๆ ที่คุณอาจต้องการโดยไม่ต้องโหลดประสิทธิภาพการโหลด WordPress สองครั้ง มันเกือบจะแน่นอนว่าคุณควรทำอะไรเว้นแต่คุณจะมีเหตุผลที่ดีที่จะไม่ทำ (เช่นเนื่องจากขนาดของสไตล์ชีทหรือสคริปต์ที่คุณต้องใช้)

หากขนาดใหญ่พอที่จะทำให้เกิดปัญหาในแง่ของน้ำหนักหนึ่งหน้าของคุณคุณสามารถลอง (2) หรือ (2a)

หรืออย่างอื่น - นี่อาจเป็นความคิดที่ดีกว่า - คุณสามารถลองแยกส่วนต่าง ๆ ของสคริปต์หรือสไตล์ชีทที่ใช้ประโยชน์จากข้อมูลไดนามิกจากส่วนที่สามารถระบุได้แบบสแตติก บอกว่าคุณมีสไตล์ชีทที่ต้องส่งผ่านไดเรกทอรีจาก WordPress เพื่อตั้งค่าพารามิเตอร์พื้นหลังสำหรับองค์ประกอบ # my-fancy คุณสามารถใส่ทั้งหมดนี้ลงในองค์ประกอบส่วนหัว:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */
 </style>

แต่ทำไมคุณต้องทำเช่นนั้น? บรรทัดเดียวเท่านั้นที่นี่ซึ่งขึ้นอยู่กับข้อมูลจาก WordPress ดีกว่าที่จะแยกเฉพาะบรรทัดที่ขึ้นอยู่กับ WordPress:

 <style type="text/css">
 #my-fancy-element {
      background-image: url(<?php print get_stylesheet_directory_uri(); ?>images/fancy.png);
 }
 </style>

ใส่ทุกอย่างไว้ในสไตล์ชีทคงที่ที่คุณโหลดด้วยองค์ประกอบลิงก์มาตรฐาน (style.css หรืออะไรก็ตาม):

 #my-fancy-element {
      /* background-image provided dynamically */
      padding: 20px;
      margin: 20px;
      font-weight: bold;
      text-transform: uppercase;
      font-size: 12pt;
      /* ... KB and KB of additional styles ... */
 }
 #another-fancy-element {
     /* ... KB and KB of additional styles ... */
 }
 /* ... KB and KB of additional styles ... */

และปล่อยให้น้ำตกทำงาน

เช่นเดียวกับ JavaScript: แทนที่จะทำสิ่งนี้:

 <script type="text/javascript">
 // Here comes a huge function that uses WordPress data:
 function my_huge_function () {
     // Do a million things ...

     jQuery('#my-fancy').append('<a href="'+<?php json_encode(get_permalink($GLOBALS['post']->ID)); ?>+'">foo</a>);

     // Do a million more things ...

     my_other_function(<?php print json_encode(get_userdata($GLOBALS['post']->post_author); ?>);
 }

 function my_other_function (user) {
     // Do a million things ...
 }
 </script>

แทนที่จะใส่สิ่งนี้ในองค์ประกอบของหัว:

 <script type="text/javascript">
 var WordPressPostData = {
 url: <?php print json_encode(get_permalink($GLOBALS['post']->ID)); ?>,
 author: <?php print json_encode(get_userdata($GLOBALS['post']->post_author)); ?>
 }
 </script>

จากนั้นวางส่วนที่เหลือลงในไฟล์ JavaScript แบบคงที่เขียนใหม่ my_huge_function () และ my_other_function () เพื่อใช้ประโยชน์ของ globals WordPressPostData.url และ WordPressPostData.author

40K ของ CSS หรือ 40K ของ JS สามารถแบ่งออกเป็น <1K ที่ขึ้นอยู่กับข้อมูลแบบไดนามิกและส่วนที่เหลือซึ่งสามารถระบุได้ในไฟล์ภายนอกแบบคงที่จากนั้นรวมอีกครั้งโดยใช้ cascade (สำหรับ CSS) หรือเข้าถึงได้ทั่วโลก ตัวแปร (กลม, องค์ประกอบ DOM หรืออะไรก็ตามที่คุณต้องการสำหรับ Cubby-hole)


คำตอบที่ยอดเยี่ยม!
scribu

2
เพิ่มเพียงเล็กน้อย: ในกรณีของ JS เราสามารถใช้wp_localize_sciprtเพื่อเพิ่มตัวแปรแบบไดนามิก
Anh Tran

6

กรณี CSS แบบไดนามิกค่อนข้างง่าย

เพียงแค่สร้างฟังก์ชั่นที่ผลคำจำกัดความแบบไดนามิก CSS ภายในของแท็กและแล้วเบ็ดฟังก์ชั่นที่เป็น<style type="text/css"></style> wp_print_stylesเช่น

<?php
function mytheme_dynamic_css() {
    $options = get_option( 'mytheme_options' );
    ?>
    <style type="text/css">
    /* Dynamic H1 font family */
    h1 { font-family: <?php echo $options['h1_font_family']; ?>;
    </style>
    <?php
}
add_action( 'wp_print_styles', 'mytheme_dynamic_css' );
?>

หรือสมมุติว่าคุณมีโครงร่างสีที่กำหนดค่าไว้ล่วงหน้า คุณสามารถจัดคิวสไตล์ชีทที่เหมาะสมตามการตั้งค่าผู้ใช้ปัจจุบัน:

<?php
function mytheme_enqueue_colorscheme_stylesheet() {
    $options = get_option( 'mytheme_options' );
    $color_scheme = $options['color_scheme'];
    wp_enqueue_style( $colorscheme, get_template_directory_uri() . '/css/' . $color_scheme . '.css' );
}
add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_colorscheme_stylesheet' );
?>

โปรดทราบว่าในกรณีนี้ฟังก์ชั่นจะเชื่อมต่อwp_enqueue_scriptsกันเนื่องจาก WordPress ไม่มีwp_enqueue_stylesแอคชั่นฮุค


1
เช่นเดียวกับ 1) นี่คือสิ่งที่ฉันกำลังทำอยู่ แต่ถ้าคุณมี CSS 40K คุณจะได้รับเอกสาร html ขนาดใหญ่
onetrickpony

1
แต่ CSS 40K นั้นจะต้องมีการส่งออกที่ไหนสักแห่งใช่ไหม และแน่นอนเช่นเดียวกับ # 1 แต่เป็นวิธีที่เหมาะสมในการฉีด CSS แบบไดนามิกใน WordPress :)
Chip Bennett

2

ฉันกำลังคิดอยู่พักหนึ่งแล้ว คำถามของคุณทำให้ฉันกลับไปที่มัน ไม่แน่ใจว่าเป็นความคิดที่ดีหรือไม่ดังนั้นฉันต้องการความคิดเห็นจากผู้เชี่ยวชาญเกี่ยวกับเรื่องนี้

ถ้าฉันเขียนไฟล์ javascript / css ผ่าน phpเมื่อผู้ดูแลระบบบันทึกข้อมูล มันจะเป็นการเขียนครั้งเดียวจนกว่าผู้ใช้จะเปลี่ยนเลย์เอาต์อีกครั้ง (ซึ่งผู้ใช้อาจไม่ทำบ่อยเกินไป) ด้วยวิธีนี้เรากำลังเข้าถึงฐานข้อมูลสำหรับการตั้งค่าผู้ใช้เพียงครั้งเดียวเมื่อผู้ใช้บันทึกข้อมูล

หลังจากเขียนไฟล์มันจะเป็นไฟล์ javascript / css ปกติดังนั้นเราไม่จำเป็นต้องโทรฐานข้อมูลทุกครั้งที่โหลดธีม

คำถามหนึ่งข้อที่ต้องการคำตอบ: จะเกิดอะไรขึ้นเมื่อผู้เข้าชมพยายามเข้าถึงไซต์ในทันทีเมื่อ php เขียนไฟล์

แจ้งให้เราทราบสิ่งที่คุณคิด.


หากคุณสร้างไฟล์เหล่านั้นในwp-content/uploads(ไดเรกทอรีเดียวที่รับประกันว่าสามารถเขียนได้จากรหัส WP) ก็อาจเป็นวิธีที่ทำงานได้ ฉันคิดว่า WP Core ใช้เทคนิคนี้สำหรับไฟล์ js หนึ่งไฟล์
scribu

ข้อเสียคือมันไม่ได้เป็นแบบไดนามิกจริงๆนั่นคือมันเหมือนกันสำหรับทุกคนในทุกหน้า สำหรับแต่ละรูปแบบคุณจะต้องสร้างไฟล์ใหม่ มันยังคงเป็นวิธีที่ดีสำหรับตัวเลือกชุดรูปแบบ / ปลั๊กอินตามที่คุณกล่าวถึง
scribu

@ Subsu: ใช่จริง มันอาจเป็นระเบียบสำหรับสิ่งที่ชอบ ถ้าเราให้หน้าโปรไฟล์ที่กำหนดเองแก่ผู้ใช้และต้องเขียนไฟล์แต่ละไฟล์ แต่มันอาจเป็นวิธีที่ดีสำหรับบางอย่างเช่นถ้าเราทำเว็บไซต์แบบเห็นภาพ (ลากและวาง) ที่ผู้ใช้เปลี่ยนสีและเพิ่มเอฟเฟ็กต์ต่าง ๆ (ตามคำถามนี้) ฯลฯ และอาจนำมารวมกับ WPMU;)
Sisir

1

สำหรับชิ้นเล็ก ๆ ของสคริปต์ซึ่งคุณอาจไม่ต้องการที่จะรวมอยู่ในแฟ้มที่แยกต่างหากเช่นเพราะพวกเขาจะสร้างแบบไดนามิก WordPress 4.5 wp_add_inline_scriptและข้อเสนอต่อไป ฟังก์ชั่นนี้โดยทั่วไปจะทำให้สคริปต์เข้ากับสคริปต์อื่น ตัวอย่างเช่นสมมติว่าคุณกำลังพัฒนาธีมและต้องการให้ลูกค้าของคุณสามารถแทรกสคริปต์ของตัวเอง (เช่น Google Analytics หรือ AddThis) ผ่านหน้าตัวเลือก ตัวอย่าง

สำหรับสไตล์มีwp_add_inline_styleซึ่งโดยทั่วไปแล้วทำงานเหมือนกัน ตัวอย่างเช่นคุณจะใช้มันเพื่อวนรอบตัวปรับแต่งปรับแต่งทั้งหมดของคุณและรวบรวมไว้ในสตริงที่เรียกว่า$all_modsซึ่งคุณจะเพิ่มเช่นนี้ในสไตล์ชีทหลักของคุณ:

if (!empty($all_mods)) wp_add_inline_style ('main-style', $all_mods);

-2

สร้างไฟล์ JS.php แบบไดนามิกและฟีด query_vars สำคัญให้กับมัน ตัวแปรเหล่านั้น$_GETจะช่วยให้ไฟล์กำหนดบริบทและในนั้นคุณสามารถแคชและใช้readfile()สำหรับการร้องขอในอนาคต ... ทำอะไรก็ได้

เพียงตรวจสอบให้แน่ใจว่าไฟล์โหลดwp-load.phpมาก่อนสิ่งอื่นดังนั้นคุณจึงสามารถเข้าถึงฟังก์ชัน WP ได้ ใช้เส้นทางสัมพัทธ์ไปยังโฟลเดอร์ปัจจุบัน(dirname(__FILE__))หรือเพียงแค่ขุดลงในโครงสร้างโฟลเดอร์เพื่อค้นหาwp-load.phpโดยไม่คำนึงถึงการวางปลั๊กอิน

รหัสเพื่อค้นหา wp-load.php จากที่ใดก็ได้

// Ensure single declaration of function!
if(!function_exists('wp_locate_loader')):
    /**
     * Locates wp-load.php looking backwards on the directory structure.
     * It start from this file's folder.
     * Returns NULL on failure or wp-load.php path if found.
     * 
     * @author EarnestoDev
     * @return string|null
     */
    function wp_locate_loader(){
        $increments = preg_split('~[\\\\/]+~', dirname(__FILE__));
        $increments_paths = array();
        foreach($increments as $increments_offset => $increments_slice){
            $increments_chunk = array_slice($increments, 0, $increments_offset + 1);
            $increments_paths[] = implode(DIRECTORY_SEPARATOR, $increments_chunk);
        }
        $increments_paths = array_reverse($increments_paths);
        foreach($increments_paths as $increments_path){
            if(is_file($wp_load = $increments_path.DIRECTORY_SEPARATOR.'wp-load.php')){
                return $wp_load;
            }
        }
        return null;
    }
endif;
// Now try to load wp-load.php and pull it in
$mt = microtime(true);
if(!is_file($wp_loader = wp_locate_loader())){
    header("{$_SERVER['SERVER_PROTOCOL']} 403 Forbidden");
    header("Status: 403 Forbidden");
    echo 'Access denied!'; // Or whatever
    die;
}
require_once($wp_loader); // Pull it in
unset($wp_loader); // Cleanup variables

ไชโย Scribu!

PS : สำหรับโครงสร้างที่ซับซ้อนที่โฟลเดอร์ไม่ปฏิบัติตามโครงสร้างการลดลงของ WP ปกติปลั๊กอินพาเรนต์สามารถแบ่งปันข้อมูลกับไฟล์ที่สามารถเข้าถึงได้โดยตรง ปลั๊กอินหลักที่มาพร้อมกับไฟล์ PHP แบบไดนามิกที่ทำให้ CSS / JS สามารถเขียนลงในไฟล์realpath()ของwp-load.phpและไฟล์แบบสแตนด์อโลนสามารถใช้งานได้ นี่จะเป็นปัญหาสำหรับผู้ใช้ WP 0.1% ฉันคิดว่าคนที่ย้ายโฟลเดอร์และไม่ปฏิบัติตามโครงสร้างปกติรู้ว่าพวกเขากำลังทำอะไรและอาจเป็นปลั๊กอิน PIMP ที่ต้องโหลดwp-load.phpโดยตรง


น่ารัก! เกลียดชังโปรดผนวกคำอธิบาย สอนฉัน ขอบคุณ;) xoxo
EarnestoDev

เป็นการปฏิบัติที่ไม่ถูกต้องที่จะรวมไว้wp-load.phpในชุดรูปแบบหรือไฟล์ปลั๊กอินเนื่องจากwp-contentและ / หรือplugins ไดเรกทอรีอาจอยู่ที่ใดก็ได้ที่สัมพันธ์กับรูต WP dir จำ WP_CONTENT_DIR และ WP_PLUGINS_DIR
นักเขียน

1
@criu และไฟล์แบบสแตนด์อโลนสามารถทำงานร่วมกับปลั๊กอินหลักได้ ปลั๊กอินหลักสามารถเก็บ wp-load.php ในโฟลเดอร์ที่ตั้งอยู่และตัวสร้าง js แบบไดนามิกสามารถอ่านได้จากที่นั่น ง่าย ...
EarnestoDev

1
ใช่วิธีการปลั๊กอินผู้ปกครองสามารถทำงานได้ เขียนขึ้นในคำตอบของคุณและฉันจะลบ downvote ของฉัน PS: เว็บไซต์นี้เป็นภาษาอังกฤษ คุณอาจมีปัญหาหากคุณยังคงพูดในภาษาโรมาเนียต่อไป
scribu

5
ตัดทัศนคติ โหลดคอร์ด้วยตนเองเป็นเทคนิคที่ใช้งานได้ แต่อยู่ไกลจากการเลือกที่ดีก่อนสำหรับสิ่งต่างๆ ไม่มีใครสงสัยว่าคุณจะสามารถทำงานได้ คะแนนโหวตเกี่ยวกับคุณภาพของคำตอบไม่ใช่สมองของคุณ
Rarst
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.