2017-08-31 39 views
11

için css modüllerini uygulamanın daha iyi bir yolu Şu an AngularJS 1.5 bileşenlerine sahip css modülleri kullanıyorum. Yığın webpack + css-loader?modules=true + angular 1.5 components + pug'dur.AngularJS

Şu anda, pug şablonumda css modüllerini kullanmak için aşağıdaki adımları izlemeliyim.

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

iki sorun vardır:

  1. Her bileşen $element enjekte ve elle sınıf adını ayarlamak zorundadır. Bunun nedeni, AngularJS bileşen etiketinin, herhangi bir sınıf içermeyen sonuç HTML'sinde bulunmasıdır, bu da CSS'yi zorlaştırır. Örneğin, böyle yukarıda MyComponent kullanıyorsanız:

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

    aşağıdaki HTML üretecektir: Yukarıdaki sonuç HTML ReactJS karşılaştırıldığında

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

    , <my-component> ekstra olup, bazen CSS zorlaştırır yazmak. Bu yüzden benim çözümüm bir sınıf eklemek için (1).

  2. Şablondaki sınıf çok uzun (3). $ctrl.styles.fooBar'a başvurmanın doğru yolu olduğunu biliyorum, ancak bu çok uzun.

Benim ideal çözüm böyle olacağını:

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

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

fikri şudur:

  1. yapmak angular.module().component destek otomatik olarak (2) this.styles = styles; yapacak ekstra styles nitelik, kontrolörü ve (1) $element.addClass()'u da uygulayın. Öğeye $ctrl.styles uygulamak için
  2. yönergesi css-class.

Sorum şu ki, yukarıdaki 1 numaralı fikri nasıl uygulayacağımı bilmiyorum (2 tane kolay). Bu konuda biraz ışık tutabilirse memnun olurum.

cevap

5

Oldukça tatmin olmadığım bir çözüm buldum.

Açısal bileşen, bir işlevi şablon olarak kabul edebilir ve $element ile enjekte edebilirsiniz. doc

şablon bir işlevdir ise, o zaman şu halk ile enjekte edilir:

  • $ elemanı - Güncel eleman
  • $ attrs - Güncel nitelikler eleman
için itiraz

Bu nedenle, şablon eğlencesinde ana bileşen (.myComponent) ekleyebiliriz ction, daha sonra regex sınıf isimlerinin tüm derlemelerini derlenmiş sınıf isimleriyle değiştirir.

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

hala decorateTemplate regex değiştirme kullanır ve şablon css-modülleri sınıf isimleri belirtmek için özel bir gösterim ${className} kullanmak zorunda olduğu iyileştirilmelidir bir yer vardır.

Herhangi bir öneri kabul edilir.

GÜNCELLEME

yerel sınıf isimleri ._localClassName olarak yazılabilir, böylece boksör özelliklerden yararlanarak benim decorateTemplate() fonksiyonu güncellendi. Bu rağmen

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

o ilginç notasyonu ortadan kaldırmak ve regex yerine (yerel sınıf adları için _ ile başlar) gelmez çok daha kolaydır.

Herhangi bir öneri kabul edilir.