프론트엔드/Javascript

Tagged 템플릿 리터럴

syleemomo 2022. 7. 16. 08:25
728x90

 

const theme = {
  brandColor1: "#BE2525",
  brandColor2: "#BE0000",
};
const backcolor = {
  bgColor1: 'orange',
  bgColor2: 'yellow'
}
const params = [theme, backcolor]

// strings 는 문자열이 있는 부분만 추출해서 배열에 저장함
// values 는 함수나 객체가 있는 부분만 추출해서 배열에 저장함
function css(strings, ...values) {
  console.log(strings)
  console.log(values)
  return strings.reduce((res, str, i) => {
    // 문자열이 있는 부분은 그냥 연결하고 함수나 객체가 있는 부분은 함수를 실행해서 얻은 반환값이나 객체의 프로퍼티 값을 연결함
                    return res + str + (values[i] ? values[i](params[i]) : ""); 
                  }, "");
}
const styles = css`
font-size: 1.2em;
color: ${(theme) => theme.brandColor2};
background: ${(backcolor) => backcolor.bgColor1}
`;
console.log(styles);

/* font-size: 1.2em;
color: #BE0000;
background: orange */const theme = {
  brandColor1: "#BE2525",
  brandColor2: "#BE0000",
};
const backcolor = {
  bgColor1: 'orange',
  bgColor2: 'yellow'
}
const params = [theme, backcolor]

// strings 는 문자열이 있는 부분만 추출해서 배열에 저장함
// values 는 함수나 객체가 있는 부분만 추출해서 배열에 저장함
function css(strings, ...values) {
  console.log(strings)
  console.log(values)
  return strings.reduce((res, str, i) => {
    // 문자열이 있는 부분은 그냥 연결하고 함수나 객체가 있는 부분은 함수를 실행해서 얻은 반환값이나 객체의 프로퍼티 값을 연결함
                    return res + str + (values[i] ? values[i](params[i]) : ""); 
                  }, "");
}
const styles = css`
font-size: 1.2em;
color: ${(theme) => theme.brandColor2};
background: ${(backcolor) => backcolor.bgColor1}
`;
console.log(styles);

/* font-size: 1.2em;
color: #BE0000;
background: orange */

app.js 파일을 위와 같이 작성하자!

 

const theme = { // font color
  brandColor1: "#BE2525",
  brandColor2: "#BE0000",
};
const backcolor = { // background color
  bgColor1: '#eee',
  bgColor2: '#bbb'
}
const props = { theme, backcolor } // props for styling

// strings 는 문자열이 있는 부분만 추출해서 배열에 저장함
// values 는 함수나 객체가 있는 부분만 추출해서 배열에 저장함
function cssWithProps(props, strings, ...values) {
  return strings.reduce((res, str, i) => {
    return res + str + (values[i] ? values[i](props) : ""); // 문자열이 있는 부분은 그냥 연결하고 함수나 객체가 있는 부분은 함수를 실행해서 얻은 반환값이나 객체의 프로퍼티 값을 연결함
  }, "");
}

// build library like styled components with tag template literal and css function
const styled = {}
const tags = [
  "div", "h1", "h2", "h3", "h4", "h5", "h6",
  "a", "p", "button", "input", "span", "img",
]

setPropertiesOfStyledObject(styled, tags, props, buildStyledElement)

function setPropertiesOfStyledObject(styled, tags, props, buildStyledElement){
  for(let tag of tags){
    styled[tag] = (strings, ...values) => buildStyledElement(tag, props, strings, ...values) // closure: wrapping with tag and props
  }
}
console.log(styled)

function buildElement(tag, style){
  const el = document.createElement(tag)
  el.style = style
  return el 
}
function buildStyledElement(tag, props, strings, ...values) {
  const style = strings.reduce((res, str, i) => {  
                  return res + str + (values[i] ? values[i](props) : "");  // props: { theme, backcolor }
                }, "");
  
  return buildElement(tag, style)
}


const divEl = styled.div`
  width: 100%;
  height: 500px;
  font-size: 1.2em;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  
  ${props => {
    if(props.theme && props.backcolor){
      const css = (strings, ...values) => cssWithProps(props, strings, ...values) // closure: wrapping with props
      return css`
        color: ${props => props.theme.brandColor2};
        background: ${props => props.backcolor.bgColor1};
      `
    }
  }}
`
console.log(divEl)

const buttonEl = styled.button`
  width: 150px;
  height: 50px;
  outline: none;
  border: none;
  border-radius: 15px;
  cursor: pointer;
  content: "버튼";
  color:#eee;
  font-size: 1.5rem;
  
  ${props => {
    if(props.backcolor){
      const css = (strings, ...values) => cssWithProps(props, strings, ...values) // closure: wrapping with props
      return css`
        background: ${props => props.backcolor.bgColor2};
      `
    }
  }}
`
console.log(buttonEl)
buttonEl.innerText = "click"
buttonEl.addEventListener('click', (e) => alert("you clicked this button !"))

const inputEl = styled.input`
  width: 500px;
  height: 50px;
  outline: none;
  border: 2px solid #bbb;
  border-radius: 20px;
  margin-top: 20px;
  padding-left: 20px;
  font-size: 1.5rem;
  
  ${props => {
    if(props.theme && props.backcolor){
      const css = (strings, ...values) => cssWithProps(props, strings, ...values) // closure: wrapping with props
      return css`
        color: ${props => props.theme.brandColor1};
        background: ${props => props.backcolor.bgColor1};
      `
    }
  }}
`
console.log(inputEl)
inputEl.autofocus = true 
inputEl.placeholder = "Type something..."

document.body.appendChild(divEl)
divEl.append(buttonEl, inputEl)

app.js 파일을 위와 같이 작성하자! 

728x90