Giải pháp tạo javascript / CSS động


15

Giả sử bạn cần tạo mã javascript hoặc CSS phụ thuộc vào ngữ cảnh hiện tại.

Ví dụ: bạn có một biểu mẫu trên trang chủ thực hiện yêu cầu ajax khi gửi và một biểu mẫu khác trên một trang. Hoặc trong trường hợp CSS, bạn muốn tạo một chủ đề cho phép người dùng xây dựng bố cục của riêng họ, thay đổi màu sắc, v.v.

Các giải pháp tôi thấy cho đến nay:

  1. Bao gồm mã trong phần đầu của tài liệu (hoặc ở cuối trong trường hợp JS)

  2. Thực hiện một yêu cầu đặc biệt xuất ra mã, như site.com?get_assets . Điều này là chậm vì WP được tải hai lần.

  3. Lưu trữ nó trong các tệp tạm thời trong một khoảng thời gian nhất định và tải nó từ đó. Không đáng tin cậy cho các chủ đề công cộng hoặc plugin.

  4. Chỉ Javascript - làm cho nó tĩnh bằng cách đặt nó vào một tệp bình thường được tải mỗi lần. Trong trường hợp này, bạn sẽ phải làm cho mã của mình xử lý mọi tình huống

Bạn có biết người khác? Con đường nào bạn sẽ đi?


Một vấn đề tôi gặp phải với giải pháp 1 là bộ nhớ đệm của trình duyệt, mã không được làm mới khi tải lại trang.
Aurovrata

Câu trả lời:


9

Một tùy chọn bổ sung, tùy thuộc vào loại tham số bạn cần truyền vào. Hãy gọi nó (2a). Bạn cũng có thể tạo các tập lệnh PHP tạo ra động text/csshoặc được tạo động text/javascripthơn là text/htmlcung cấp cho chúng dữ liệu mà chúng cần bằng các tham số GET thay vì tải lên WordPress. Tất nhiên điều này chỉ hoạt động nếu bạn cần vượt qua trong một số lượng nhỏ các tham số tương đối nhỏ gọn. Vì vậy, ví dụ, giả sử bạn chỉ cần chuyển URL của bài đăng hoặc thư mục của tệp hoặc tương tự, bạn có thể làm một cái gì đó như thế này:

Trong tiêu đề.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>

Trong Fancy-js.php:

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

Vân vân.

Nhưng điều này chỉ cho phép bạn truy cập vào dữ liệu được truyền trực tiếp trong các tham số GET; và nó sẽ chỉ hoạt động nếu số lượng những thứ bạn cần phải vượt qua tương đối nhỏ, và đại diện của những thứ đó tương đối nhỏ gọn. (Về cơ bản có rất nhiều chuỗi hoặc giá trị số - tên người dùng, giả sử hoặc thư mục; không phải là danh sách tất cả các bài đăng gần đây của người dùng hoặc đại loại như thế.)

Đối với một trong những lựa chọn này là tốt nhất - tôi không biết; điều đó phụ thuộc vào trường hợp sử dụng của bạn. Tùy chọn (1) có ưu điểm là đơn giản và rõ ràng cho phép bạn truy cập vào bất kỳ dữ liệu WordPress nào bạn có thể cần, mà không cần hiệu năng của việc tải WordPress hai lần. Đó gần như chắc chắn là những gì bạn nên làm trừ khi bạn có lý do mạnh mẽ để không (ví dụ: do kích thước của biểu định kiểu hoặc tập lệnh mà bạn cần sử dụng).

Nếu kích thước đủ lớn để gây ra sự cố về trọng lượng của một trang của bạn, thì bạn có thể thử (2) hoặc (2a).

Hoặc nếu không - đây có lẽ là ý tưởng tốt hơn - bạn có thể thử tách các phần của tập lệnh hoặc biểu định kiểu thực sự sử dụng dữ liệu động từ các phần có thể được chỉ định tĩnh. Ssay bạn có một biểu định kiểu cần được thông qua một thư mục từ WordPress để đặt tham số nền cho phần tử # my-Fancy. Bạn có thể đặt tất cả những thứ này vào phần tử head:

 <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>

Nhưng tại sao bạn cần phải làm điều đó? Chỉ có một dòng ở đây phụ thuộc vào dữ liệu từ WordPress. Tốt hơn là chỉ tách ra các dòng phụ thuộc vào WordPress:

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

Đặt mọi thứ khác vào biểu định kiểu tĩnh mà bạn tải bằng phần tử liên kết chuẩn (style.css hoặc bất cứ thứ gì):

 #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 ... */

Và hãy để thác làm việc.

Điều tương tự cũng xảy ra với JavaScript: thay vì làm điều này:

 <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>

Thay vào đó hãy đặt một cái gì đó như thế này trong phần tử head:

 <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>

Và sau đó thả phần còn lại vào một tệp JavaScript tĩnh, viết lại my_huge_feft () và my_other_feft () để sử dụng toàn cầu WordPressPostData.url và WordPressPostData. Mượt.

40K CSS hoặc 40K của JS hầu như luôn có thể được chia thành <1K thực sự phụ thuộc vào dữ liệu động và phần còn lại, có thể được chỉ định trong tệp bên ngoài tĩnh và sau đó được kết hợp lại bằng cách sử dụng tầng (cho CSS) hoặc có thể truy cập toàn cầu các biến (toàn cục, các phần tử DOM hoặc bất kỳ lỗ khối nào khác mà bạn thích, cho JS).


Câu trả lời rực rỡ!
scribu

2
Chỉ cần một bổ sung nhỏ: trong trường hợp của JS, chúng ta có thể sử dụng wp_localize_sciprt để thêm các biến động.
Anh Trần

6

Trường hợp CSS động khá đơn giản.

Chỉ cần tạo một hàm xuất ra các định nghĩa CSS động bên trong các <style type="text/css"></style>thẻ và sau đó nối hàm đó vào wp_print_styles. ví dụ

<?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' );
?>

Hoặc giả sử bạn có các lược đồ màu được cấu hình sẵn; bạn có thể liệt kê biểu định kiểu thích hợp theo cài đặt người dùng hiện tại:

<?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' );
?>

Lưu ý rằng, trong trường hợp này, hàm móc vào wp_enqueue_scripts, vì WordPress không có wp_enqueue_stylesmóc hành động.


1
giống như 1). Đây là những gì tôi đang làm bây giờ, nhưng nếu bạn có 40K CSS, bạn sẽ nhận được một tài liệu html cồng kềnh
onetrickpony

1
Nhưng 40K CSS đó phải được xuất ra ở đâu đó , phải không? Và, chắc chắn giống như số 1, nhưng là cách phù hợp để tiêm CSS động trong WordPress. :)
Chip Bennett

2

Tôi đã suy nghĩ điều đó trong một thời gian. Câu hỏi của bạn làm cho tôi trở lại với nó.Không chắc nó có phải là một ý tưởng tốt hay không, vì vậy tôi muốn các chuyên gia nhận xét về điều đó.

Nếu tôi viết tệp javascript / css qua php khi quản trị viên lưu dữ liệu. Nó sẽ được viết một lần cho đến khi người dùng thay đổi bố cục một lần nữa (mà người dùng có thể không làm quá thường xuyên). Bằng cách đó, chúng tôi chỉ truy cập cơ sở dữ liệu cho các cài đặt người dùng một lần khi người dùng lưu dữ liệu.

Sau khi viết tệp, nó sẽ là một tệp javascript / css thông thường để chúng tôi không phải gọi cơ sở dữ liệu mỗi khi tải chủ đề.

Một câu hỏi cần được trả lời: Điều gì sẽ xảy ra khi khách truy cập cố gắng truy cập trang web ngay lập tức khi php viết tệp?

Cho tôi biết bạn nghĩ gì.


Nếu bạn tạo các tệp đó trong wp-content/uploads(thư mục duy nhất được đảm bảo có thể ghi được từ mã WP), đó có thể là một cách tiếp cận khả thi. Tôi nghĩ ngay cả WP Core cũng sử dụng kỹ thuật này cho một tệp js.
scribu

Hạn chế là nó không thực sự năng động, tức là nó giống nhau cho tất cả mọi người trên tất cả các trang. Đối với mỗi biến thể, bạn sẽ phải tạo một tệp mới. Đây vẫn là một cách tiếp cận tốt cho các tùy chọn chủ đề / plugin, như bạn đã đề cập.
scribu

@ fouu: đúng vậy nó có thể là một mớ hỗn độn cho một cái gì đó như. nếu chúng tôi cung cấp cho người dùng một trang hồ sơ tùy chỉnh và phải viết các tệp cho từng người trong số họ. Nhưng nó có thể là một cách tiếp cận tốt cho một cái gì đó như nếu chúng ta làm một nhà sản xuất trang web trực quan (kéo và thả) trong đó người dùng thay đổi màu sắc và thêm các hiệu ứng khác nhau (như câu hỏi này), v.v. và có thể được kết hợp với WPMU;)
Sisir

1

Ví dụ, đối với các đoạn script nhỏ mà bạn có thể không muốn đưa vào một tệp riêng vì chúng được tạo động, WordPress 4.5 và các ưu đãi khác wp_add_inline_script. Chức năng này về cơ bản chốt tập lệnh này sang tập lệnh khác. Ví dụ, giả sử bạn đang phát triển một chủ đề và muốn khách hàng của mình có thể chèn các tập lệnh của riêng mình (như Google Analytics hoặc Add This) thông qua trang tùy chọn. Ví dụ .

Đối với phong cách có wp_add_inline_style, về cơ bản hoạt động như nhau. Ví dụ, bạn sẽ sử dụng nó để lặp qua tất cả các mod tùy biến của mình và tập hợp chúng trong một chuỗi được gọi $all_mods, sau đó bạn sẽ thêm như thế này vào biểu định kiểu chính của mình:

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

-2

Tạo một tệp JS.php động và cung cấp các truy vấn quan trọng cho nó. Các biến đó $_GETsẽ giúp tệp xác định ngữ cảnh và trong đó bạn có thể lưu trữ và sử dụng readfile()cho các yêu cầu trong tương lai ... làm bất cứ điều gì.

Chỉ cần đảm bảo rằng tệp tải wp-load.phptrước bất cứ thứ gì khác, vì vậy bạn có quyền truy cập vào các chức năng WP. Sử dụng đường dẫn tương đối đến thư mục hiện tại (dirname(__FILE__))hoặc chỉ cần giảm dần trong cấu trúc thư mục để xác định vị trí wp-load.phpbất kể vị trí plugin.

Mã để tìm kiếm wp-load.php từ bất cứ đâu

// 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

Chúc mừng, Scribu!

PS : Đối với các cấu trúc phức tạp nơi các thư mục không tuân theo cấu trúc phân rã WP thông thường, các plugin cha mẹ có thể chia sẻ thông tin với các tệp có thể truy cập trực tiếp. Một plugin mẹ mà đi kèm với một tập tin PHP động mà ám CSS / JS có thể viết thành một file realpath()của wp-load.phpvà các tập tin độc lập có thể sử dụng. Đây sẽ là một vấn đề cho 0,1% người dùng WP. Tôi nghĩ rằng những người di chuyển các thư mục và không tuân theo cấu trúc bình thường sẽ biết họ đang làm gì và có thể các plugin PIMP có thể cần tải wp-load.phptrực tiếp.


Dễ thương! Người ghét, xin vui lòng nối giải thích. Soi sáng cho tôi. Cảm ơn;) xoxo
EarnestoDev

Đó là thực tế xấu khi bao gồm wp-load.phptừ một tệp chủ đề hoặc plugin, vì wp-contentvà / hoặc plugins thư mục có thể là bất cứ nơi nào có liên quan đến thư mục WP gốc. Hãy nhớ WP_CONTENT_DIR và WP_PLUGINS_DIR.
scribu

1
@ fouu Và tệp độc lập có thể cộng tác với một plugin cha. Plugin cha có thể lưu trữ wp-load.php trong thư mục chứa nó và trình tạo js động có thể đọc nó từ đó. Đơn giản ...
EarnestoDev

1
Có, cách tiếp cận plugin cha mẹ có thể làm việc. Viết nó lên trong câu trả lời của bạn và tôi sẽ xóa downvote của tôi. PS: Trang web này bằng tiếng Anh; bạn có thể gặp vấn đề nếu bạn tiếp tục để lại nhận xét bằng tiếng Romania.
scribu

5
Cắt thái độ. Tải lõi bằng tay là kỹ thuật khả thi, nhưng khác xa với lựa chọn đầu tiên cho hầu hết mọi thứ. Không ai nghi ngờ rằng bạn có thể làm cho nó hoạt động. Phiếu bầu là về chất lượng câu trả lời của bạn, không phải bộ não của bạn.
Rarst
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.