2017-08-31 15 views
11

Tôi đang sử dụng các mô-đun css với các thành phần AngularJS 1.5 ngay bây giờ. Ngăn xếp là webpack + css-loader?modules=true + angular 1.5 components + pug.Cách tốt hơn để áp dụng các mô-đun css vào AngularJS

Hiện tại tôi phải thực hiện các bước sau để sử dụng các mô-đun css trong mẫu pug của tôi.

// my-component.js 

import template from 'my-component.pug'; 
import styles from 'my-component.css'; 

class MyComponent { 
    constructor($element) { 
     $element.addClass('myComponent');  // ------ (1) 
     this.styles = styles;     // ------ (2) 
    } 
} 

angular.module(name, deps) 
    .component('my-component', { 
     controller: MyComponent, 
     template: template, 
    }); 

// my-component.pug 
div(class={{ ::$ctrl.styles.fooBar }}) FooBar // ----- (3) 

// my-component.css 
.myComponent { background: green; } 
.fooBar { color: red; } 

Có hai vấn đề:

  1. Mỗi thành phần có phải tiêm $element và đặt tên lớp của nó bằng tay. Lý do để làm điều này là, thẻ thành phần AngularJS tồn tại trong kết quả HTML mà không có bất kỳ lớp nào, điều này làm cho CSS trở nên khó khăn. Ví dụ, nếu tôi sử dụng MyComponent trên như thế này:

    <div> 
        <my-component></my-component> 
    </div> 
    

    nó sẽ tạo ra mã HTML sau đây:

    <div> 
        <my-component> 
        <div class="my-component__fooBar__3B2xz">FooBar</div> 
        </my-component> 
    </div> 
    

    So với ReactJS, <my-component> trong HTML kết quả trên là một phụ, đôi khi nó làm cho CSS khó khăn viết. Vì vậy, giải pháp của tôi là (1), để thêm một lớp vào nó.

  2. Lớp học trong mẫu quá dài (3). Tôi biết đó là cách chính xác để tham khảo $ctrl.styles.fooBar nhưng đây là cách quá dài.

giải pháp lý tưởng của tôi sẽ là như thế này:

// my-component.js 
angular.module(name, deps) 
    .component('my-component', { 
     controller: MyComponent, 
     template: template, 
     styles: styles, 
    }); 

// my-component.css 
div(css-class="fooBar") FooBar 

Ý tưởng là:

  1. làm angular.module().component hỗ trợ thêm một styles thuộc tính, mà sẽ tự động làm (2) this.styles = styles; trong bộ điều khiển và áp dụng (1) $element.addClass().
  2. chỉ thị css-class để áp dụng $ctrl.styles cho phần tử.

Câu hỏi của tôi là, tôi không biết cách triển khai ý tưởng 1 ở trên (2 thật dễ dàng). Tôi đánh giá cao nếu có ai có thể chia sẻ một số ánh sáng về điều này.

Trả lời

5

Tôi đã đưa ra một giải pháp mà tôi không hoàn toàn hài lòng với.

Thành phần góc có thể chấp nhận một chức năng làm mẫu và tiêm với $element. doc

Nếu mẫu là một chức năng, sau đó nó được tiêm với người dân địa phương sau:

  • $ nguyên tố - yếu tố hiện tại
  • $ attrs - thuộc tính hiện tại đối tượng cho các phần tử

Vì vậy, chúng tôi có thể đính kèm lớp chính cho thành phần (.myComponent) vào mẫu thú vị ction, sau đó regex thay thế tất cả các sự xuất hiện của tên lớp với tên lớp được biên dịch.

// utils.js 
function decorateTemplate(template, styles, className) { 
    return ['$element', $element => { 
     $element.addClass(styles[className]); 
     return template.replace(/\$\{(\w+)\}/g, (match, p1) => styles[p1]); 
    }]; 
} 

// my-component.js 
import style from './my-component.css'; 
import template from './my-component.pug'; 
import { decorateTemplate } from 'shared/utils'; 

class MyComponent { 
    // NO NEED to inject $element in constructor 
    // constructor($element) { ... 
} 

angular.module(name, deps) 
    .component('myComponent', { 
     // decorate the template with styles 
     template: decorateTemplate(template, styles, 'myComponent'), 
    }); 

// my-component.pug, with special '${className}' notation 
div(class="${fooBar}") FooBar 

Hiện vẫn còn một nơi để được cải thiện mà decorateTemplate sử dụng thay thế regex và mẫu có sử dụng một ký hiệu đặc biệt ${className} để xác định tên css mô-đun lớp.

Mọi đề xuất đều được hoan nghênh.

CẬP NHẬT

tôi cập nhật chức năng decorateTemplate() tôi để tận dụng các tính năng pug, do đó tên lớp địa phương có thể được viết như ._localClassName.

// utils.js 
function decorateTemplate(template, styles, className) { 

    return ['$element', ($element) => { 
     $element.addClass(styles[className]); 

     return template.replace(/\sclass="(.+?)"/g, (match, p1) => { 
      let classes = p1.split(/\s+/); 
      classes = classes.map(className => { 
       if (className.startsWith('_')) { 
        let localClassName = className.slice(1); 
        if (styles[localClassName]) { 
         return styles[localClassName]; 
        } else { 
         console.warn(`Warning: local class name ${className} not found`); 
         return className; 
        } 

       } else { 
        return className; 
       } 
      }); 
      return ' class="' + classes.join(' ') + '"'; 
     }); 
    }]; 
} 

// my-component.pug 
._fooBar FooBar 

Mặc dù đây là dễ dàng hơn nhiều nó không loại bỏ các ký hiệu kỳ quặc (bắt đầu với _ cho tên lớp địa phương) và regex thay thế.

Mọi đề xuất đều được hoan nghênh.

Các vấn đề liên quan