코드스피츠 css rendering 3회차 part3 (step 41) - rule 클래스 생성

KHW·2021년 6월 19일
0

js-study

목록 보기
31/39
post-custom-banner

Rule 클래스 코드

const Rule = class{
    constructor(rule){
        this._rule = rule;
        this._style = new Style(rule.style);
    }
    get(key){
        return this._style.get(key);
    }
    set(key,val){
        this._style.set(key,val);
        return this;
    }

}

const el = document.querySelector('#s');
const sheet = el.sheet;
const rules = sheet.cssRules;
const rule = new Rule(rules[0])

rule.set('borderRadius','20px')
    .set('boxShadow','0 0 0 10px red')

실행이되면 Style클래스에 의해 다시 생성한 this._style에서 set 메소드를 진행하여 처리한다. (set에서 return this를 하는 이유는 set을 병렬로 연결하기 때문)

전체코드

<html>
  <head lang="en">
    <meta charset="UTF-8">     
    <style id='s'>
    .test{background:#ff0; }
    </style>
<body>
    <div class="test">a</div>
</body>
<script>
const Style = ((_) => {
    const prop = new Map, prefix = 'webkt,moz,ms,chrome,o,khtml'.split(',');
  const NONE = Symbol();
  const BASE = document.body.style;
  const getKey = (key) => {
    if(prop.has(key)) return prop.get(key);
    if(key in BASE) prop.set(key, key);
    else if(!prefix.some(v =>{
  // prefix를 붙인 속성은 존재하는가?를 알아볼 차례
  // 메소드 some의 인수인 callback 함수 부분이다.
  // webkitBackground 이런식으로 속성명 첫글자가 대문자이므로 표준 key인 background의 앞에 vendor prefix를 붙이고 대문자로 바꾸고 나머지 뒤인 'ackground'를 붙여주는 작업이 필요하다.
  const newKey = v + key[0].toUpperCase() + key.substr(1);
  if(newKey in BASE){ // prefix붙인 속성이 body에 있다면,
    prop.set(key, newKey); // border-radius 부르면 prefix를 붙인 진짜 이름을 캐시에 저장
    key = newKey; // 리턴할 key는 더이상 원래 키가 아니라 newKey
    return true; // 진짜 이름을 찾았으니 여기서 끊어 라는것. some을 더 돌지 않아도 된다고 끊어버리는 것이다.
  } else return false;
})){
  // some의 결과가 false일 경우에만 여기에 들어온다.
  prop.set(key, NONE);
  key = NONE;
}
return key; // 그냥 key가 리턴되든지, newKey가 리턴되든지, NONE이 리턴될 것임
  }; // end of getKey()
  return class {
    constructor(style) {
      this._style = style;
    } // 생성자에 style객체를 준다. 이 클래스는 style 객체를 안고 태어난다.
    // 키를 얻기(스타일 시트에 있는 background라는 값을 얻고싶다면?)
    get(key) {
      key = getKey(key); // 반드시 getKey에 보내서 진짜 이름을 얻어야 한다.
      if (key === NONE) return null; // 브라우저가 지원하지 않는 경우 부드럽게 null을 리턴하기 // Unsupported Property 문제 해결!
      return this._style[key]; // 이름이 있다면 진짜 이름으로 style객체에 해당 속성값을 가져오자
    }
    set(key, val) {
      key = getKey(key);
      // key가 NONE이 아니면
      if (key !== NONE) this._style[key] = val; // 값을 설정
      // NONE이면 스타일을 아예 건들지 않는다(Graceful Fail)
      return this; // set을 계속 호출하는 경우가 많아서 set을 쓸 수 있게 this를 리턴
    }
  };
})();

const Rule = class{
    constructor(rule){
        this._rule = rule;
        this._style = new Style(rule.style);
    }
    get(key){
        return this._style.get(key);
    }
    set(key,val){
        this._style.set(key,val);
        return this;
    }

}

const el = document.querySelector('#s');
const sheet = el.sheet;
const rules = sheet.cssRules;
const rule = new Rule(rules[0])

rule.set('borderRadius','20px')
    .set('boxShadow','0 0 0 10px red')



</script>
</html>
profile
나의 하루를 가능한 기억하고 즐기고 후회하지말자
post-custom-banner

0개의 댓글