<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>두잉애니띵</title>
    <link>https://seungstory.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 6 Apr 2026 09:32:20 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>공부하는 승승</managingEditor>
    <item>
      <title>리팩토링 Payment 컴포넌트 분리(feat. reduce())</title>
      <link>https://seungstory.tistory.com/549</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;reduce()&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;map() 대신 사용&lt;/li&gt;
&lt;li&gt;array의 모든 요소를 체크하고 누적된 값을 리턴하기 좋은듯&lt;/li&gt;
&lt;li&gt;반복문이나 값을 계산하기 위한 변수를 따로 선언하지 않아도 결과 값을 출력할 수 있어서 코드가 깔끔해보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1692882101223&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;array.reduce(callback, 초기값);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;array: 콜백함수를 돌리는데 사용할 인수를 가진 배열&lt;/li&gt;
&lt;li&gt;callback: 배열의 각 요소에 대해 실행될 함수
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용가능 한 인수들&lt;/li&gt;
&lt;li&gt;accumulator: 누적된 값&lt;/li&gt;
&lt;li&gt;currentValue: 현재 처리 중인 요소&lt;/li&gt;
&lt;li&gt;currentIndex: (선택사항) 현재 처리 중인 인덱스&lt;/li&gt;
&lt;li&gt;array: (선택사항) reduce()가 호출된 원본 배열&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;초기값: 생략시 array의 첫 번째 요소가 초기 누적값이 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시&lt;/p&gt;
&lt;pre id=&quot;code_1692882504846&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const array = [1, 2, 3, 4, 5];

// reduce를 사용하여 array의 모든 요소의 합을 계산

const sum = array.reduce((accumulator, currentValue) =&amp;gt; {
  return accumulator + currentValue);
}, 0); // 초기값 : 0

console.log(sum) // 15

const sum = array.reduce((accumulator, currentValue) =&amp;gt; {
  return accumulator + currentValue);
}, 100); // 초기값 : 100

console.log(sum) // 115&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 이제 reduce()를 사용해서 map()을 걷어내보자.&lt;/p&gt;
&lt;pre id=&quot;code_1692883070400&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 전
function Payment() {
    const state = useSelector((state) =&amp;gt; state.cartItem);
    let [sumPrice, setSumPrice] = useState(0);
    let priceArr = [];

    if (state.length &amp;gt; 0) {
        state &amp;amp;&amp;amp;
            state.map((a, i) =&amp;gt; {
                let amountPrice;
                if (state[i].checked) {
                    amountPrice = state[i].price * state[i].count;
                } else {
                    amountPrice = 0;
                }
                return priceArr.push(amountPrice);
            });
    } else {
        sumPrice = 0;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1692883088660&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 후
function Payment({ cartItem }) {
    const [sumPrice, setSumPrice] = useState(0);

    const calculateSumPrice = () =&amp;gt; {
        if (!cartItem) return;

        const totalAmount = cartItem.reduce((sum, item) =&amp;gt; {
            if (item.checked) {
                return sum + item.price * item.count;
            }
            return sum;
        }, 0);
        setSumPrice(totalAmount);
    };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 불필요하게 두번 계산하던 것도 calculateSumPrice란 변수에 담아서 재사용하기 + setTimeout 제거&lt;/p&gt;
&lt;pre id=&quot;code_1692883268519&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 전
useEffect(() =&amp;gt; {
    setTimeout(() =&amp;gt; {
        if (priceArr.length &amp;gt; 0) {
            let a = priceArr.reduce((sum, itemPrice) =&amp;gt; sum + itemPrice);
            setSumPrice(a);
        }
    }, 100);
});&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1692883301311&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 후
useEffect(() =&amp;gt; {
    calculateSumPrice();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. return()에서 직접 연산하던 부분도 추상화하기&lt;/p&gt;
&lt;pre id=&quot;code_1692883466364&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 전
return (
    ...
    &amp;lt;dl className=&quot;amount&quot;&amp;gt;
        &amp;lt;dt className=&quot;amount-item&quot;&amp;gt;총 상품금액&amp;lt;/dt&amp;gt;
        &amp;lt;dd className=&quot;amount-price&quot;&amp;gt;{sumPrice.toLocaleString()}원&amp;lt;/dd&amp;gt;
        &amp;lt;dt&amp;gt;배송비&amp;lt;/dt&amp;gt;
        &amp;lt;dd&amp;gt;+{sumPrice === 0 ? 0 : sumPrice &amp;gt;= 30000 ? 0 : SHIPPING}원&amp;lt;/dd&amp;gt;
    &amp;lt;/dl&amp;gt;
    &amp;lt;dl className=&quot;total&quot;&amp;gt;
        &amp;lt;dt&amp;gt;결제예상금액&amp;lt;/dt&amp;gt;
        &amp;lt;dd&amp;gt;
            {sumPrice === 0
                ? 0
                : sumPrice &amp;gt;= 30000
                ? sumPrice.toLocaleString()
                : (sumPrice + shipping).toLocaleString()}
            원
        &amp;lt;/dd&amp;gt;
    &amp;lt;/dl&amp;gt;
    ...
)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1692883534395&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 후
const calculateSumPrice = () =&amp;gt; {
    ...
    const renderShippingCost = () =&amp;gt; {
        if (sumPrice &amp;gt;= 30000) {
            return 0;
        }
        return SHIPPING_COST;
    };

    const estimatedPayment = () =&amp;gt; {
        if (sumPrice === 0) {
            return 0;
        }
        const totalPrice = sumPrice + (sumPrice &amp;gt;= 30000 ? 0 : SHIPPING_COST);
        return totalPrice.toLocaleString();
    };
    ...
    return (
        ...
        &amp;lt;dl className=&quot;amount&quot;&amp;gt;
            &amp;lt;dt className=&quot;amount-item&quot;&amp;gt;총 상품금액&amp;lt;/dt&amp;gt;
            &amp;lt;dd className=&quot;amount-price&quot;&amp;gt;{sumPrice.toLocaleString()}원&amp;lt;/dd&amp;gt;
            &amp;lt;dt&amp;gt;배송비&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;+{renderShippingCost()}원&amp;lt;/dd&amp;gt;
        &amp;lt;/dl&amp;gt;
        &amp;lt;dl className=&quot;total&quot;&amp;gt;
            &amp;lt;dt&amp;gt;결제예상금액&amp;lt;/dt&amp;gt;
            &amp;lt;dd&amp;gt;{estimatedPayment()}원&amp;lt;/dd&amp;gt;
        &amp;lt;/dl&amp;gt;
        ...
    );
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Library | Framework/React JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/549</guid>
      <comments>https://seungstory.tistory.com/549#entry549comment</comments>
      <pubDate>Thu, 24 Aug 2023 01:31:34 +0900</pubDate>
    </item>
    <item>
      <title>리팩토링</title>
      <link>https://seungstory.tistory.com/548</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;장바구니 페이지 리팩토링하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트에서 가장 가독성 떨어지는 파일이다. 당시 디렉토리 구조를 아래와 같이 만들는데, pages 폴더에 웹 프로젝트에서 보여줄 각각의 페이지를 넣고 그 페이지를 구성하는 요소를 component 폴더에 담았다. 예컨데 메인페이지를 만든다고 가정했을 때, pages &amp;gt; main.js / component &amp;gt; header, footer, nav 이런식으로 쪼개서 만든 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;265&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qQGTC/btsrYzoDL12/q6atsTgrkiZ7tXSEUN84Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qQGTC/btsrYzoDL12/q6atsTgrkiZ7tXSEUN84Sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qQGTC/btsrYzoDL12/q6atsTgrkiZ7tXSEUN84Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqQGTC%2FbtsrYzoDL12%2Fq6atsTgrkiZ7tXSEUN84Sk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;265&quot; height=&quot;332&quot; data-origin-width=&quot;265&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당시에 컴포넌트란 개념에 대해 UI의 최소 단위, 재사용 가능한 가장 작은 조각이라고 이해했다. 이걸 HTML의 시멘틱 태그처럼 코드를 봤을 때 그 구조가 한눈에 보이게 짜면 되겠구나! 라고 생각한 것이다. 아주 틀린 말은 아니겠지만 실제 현업에서 프로젝트를 진행하면서 보았던 컴포넌트들은 저정도? 크기는 작은 것도 아니었다... (input, button, modal 하나하나 다 컴포넌트로 만들어두고 사용하는 것에 놀랐던 기억이 새록새록...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 리택토링 전 Cart 컴포넌트의 구조는 이렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1692799579360&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Cart(){

  return (
    &amp;lt;Container className='cart-container'&amp;gt;
      &amp;lt;header&amp;gt;
        &amp;lt;div className='cart-title'&amp;gt;
          &amp;lt;h4 className='active'&amp;gt;장바구니&amp;lt;/h4&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/header&amp;gt;
        &amp;lt;section className='cart-box'&amp;gt;
          {/* 선택한 상품 */}
          &amp;lt;article className=&quot;cart-content&quot;&amp;gt;
            &amp;lt;CartItem /&amp;gt;
          &amp;lt;/article&amp;gt;
          {/* 총 상품 금액 */}
          &amp;lt;Payment /&amp;gt;
        &amp;lt;/section&amp;gt;
    &amp;lt;/Container&amp;gt;
  )
}

function CartItem(){
  /* ... */
}

function Payment(){
  /* ... */
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 보고 일단 저 CartItem()과 Payment()부터 개별 컴포넌트로 빼야겠다는 생각이 만연했다. 이 파일을 열어보기 전까지 Payment()가 여기 있다는 사실도 잊고있었으니 당장 분리시켜야겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 컴포넌트를 분리시키면서 신경 썼던 부분은 크게 두가지다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가독성&lt;/li&gt;
&lt;li&gt;추상화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;return() 안에서 직접 연산하거나 state를 변경하지 말자.&lt;/p&gt;
&lt;pre id=&quot;code_1692800840414&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// CartItem() 리팩토링 전 input

&amp;lt;input type='checkbox' 
    id={checkId} 
    onClick={() =&amp;gt; {dispatch(checkItem(cartItemId))}} 
    checked={state[i].checked ? true &amp;amp;&amp;amp; checkArr.push(cartItemId) : false &amp;amp;&amp;amp; checkArr.drop(cartItemId)} readOnly
/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1692801133766&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// CartItem() 리팩토링 후 input
const handleCheckboxClick = () =&amp;gt; {
    dispatch(checkItem(id));
};

const isChecked = checked ? true : false;
if (isChecked) {
    checkArr.push(id);
} else {
    const indexToRemove = checkArr.indexOf(id);
    if (indexToRemove !== -1) {
        checkArr.splice(indexToRemove, 1);
    }
}

return (
    ...
    &amp;lt;input
        type=&quot;checkbox&quot;
        id={checkId}
        onClick={handleCheckboxClick}
        checked={isChecked}
        readOnly
    /&amp;gt;
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* splice()&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Library | Framework/React JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/548</guid>
      <comments>https://seungstory.tistory.com/548#entry548comment</comments>
      <pubDate>Wed, 23 Aug 2023 23:59:49 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 21. Composition API</title>
      <link>https://seungstory.tistory.com/544</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Options API: 지금까지 사용했던 문법&lt;/li&gt;
&lt;li&gt;Composition API: 관련 있는 코드를 한 곳에 모을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 컴포넌트마다 Options / Composition 선택 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보여줄 vue 만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 준비하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 보여줄 vue 만들기 - 마이페이지&lt;/p&gt;
&lt;pre id=&quot;code_1691395095387&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- Mypage.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div style=&quot;padding: 10px&quot;&amp;gt;
        &amp;lt;h4&amp;gt;팔로워&amp;lt;/h4&amp;gt;
        &amp;lt;input placeholder=&quot;?&quot; /&amp;gt;
        &amp;lt;div class=&quot;post-header&quot;&amp;gt;
            &amp;lt;div class=&quot;profile&quot;&amp;gt;&amp;lt;/div&amp;gt;
            &amp;lt;span class=&quot;profile-name&quot;&amp;gt;사용자명&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    name: 'Mypage-components',
};
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 데이터 준비하기 - public폴더 내 json 파일 생성&lt;/p&gt;
&lt;pre id=&quot;code_1691395155601&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// folowwer.json
[
    { &quot;id&quot;: 0, &quot;name&quot;: &quot;_Limvely&quot;, &quot;image&quot;: &quot;https://picsum.photos/200?r=0&quot; },
    { &quot;id&quot;: 1, &quot;name&quot;: &quot;salmon_X&quot;, &quot;image&quot;: &quot;https://picsum.photos/200?r=1&quot; },
    { &quot;id&quot;: 2, &quot;name&quot;: &quot;360noscope&quot;, &quot;image&quot;: &quot;https://picsum.photos/200?r=2&quot; },
    { &quot;id&quot;: 3, &quot;name&quot;: &quot;Jeony_1&quot;, &quot;image&quot;: &quot;https://picsum.photos/200?r=3&quot; },
    { &quot;id&quot;: 4, &quot;name&quot;: &quot;mihyeon&quot;, &quot;image&quot;: &quot;https://picsum.photos/200?r=4&quot; }
]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* public폴더에 생성한 건 빌드할 때 파일명 변경안됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setup()함수&lt;/p&gt;
&lt;pre id=&quot;code_1691396234100&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setup(){
    let 데이터이름 = ref(데이터);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ref()에 데이터 담는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue에서 실시간 데이터 재렌더링이 가능한 이유는 reference data 타입 덕분인데 setup()함수에서도 데이터의 실시간 재렌더링을 반영하기 위해 ref()에 데이터 담아서 사용함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;reactive()&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;reactive() - 보통 array, object 데이터 사용&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ref() - 숫자, 문자 등 나머지 자료형 사용&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1691395960621&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { onMounted, ref } from 'vue';
import axios from 'axios';

export default {
    name: 'Mypage-components',
    setup() {
        let follower = ref([]);
        // let follower = reactive({ name: 'kim' });
        
        // Composition API에서 Lifecycle Hook 사용
        onMounted(() =&amp;gt; {
            axios.get('/follower.json').then((res) =&amp;gt; {
                follower.value = res.data;
            });
        });
        return { follower };
    },
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API에서 props 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1691396813174&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 부모 컴포넌트 --&amp;gt;
&amp;lt;tmeplate&amp;gt;
    &amp;lt;Mypage :one=&quot;1&quot; :two=&quot;2&quot; /&amp;gt;
&amp;lt;/tmeplate&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691396892749&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 자식 컴포넌트 --&amp;gt;
&amp;lt;script&amp;gt;
import { onMounted, ref, toRefs } from 'vue';
import axios from 'axios';

export default {
    name: 'Mypage-components',
    props: {
        one: Number,
        two: Number,
    },
    setup(props, context) {
        ...
        // props 사용 방법
        let { one, two } = toRefs(props);
        one.value;
        two.value;
        ...
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API에서 watch 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1691397005308&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;watch(감시할것, () =&amp;gt; {실행할코드})&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691398080188&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { ref, watch } from 'vue'

export default {
  setup(props){
    let follower = ref([]);
    watch( 데이터명, ()=&amp;gt;{ 데이터 변화시 실행할 코드 } )
    return { follower }
  },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API에서 computed 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1691397079720&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;computed(() =&amp;gt; { return 연산결과 })&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691397263805&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default {
    name: 'Mypage-components',
    props: {
        one: Number,
        two: Number,
    },
    setup(props, context) {
        let result = computed(() =&amp;gt; {
        return follower.value.length;
    });
    console.log(result);
    ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API에서 vuex store 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1691397598080&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useStore } from 'vuex';
export default {
    name: 'Mypage-components',
    props: {
        one: Number,
        two: Number,
    },
    setup(props, context) {
        let follower = ref([]);
        let store = useStore();
        console.log(store.state.name);
        console.log(store.commit.addAge); // Composition API 안에서는 mapState 안됨
        return { follower }
    }
    ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Composition API에서 methods함수 사용하기&lt;/p&gt;
&lt;pre id=&quot;code_1691397912956&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    내함수()
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    name: 'Mypage-components',
    props: {
        one: Number,
        two: Number,
    },
    setup(props, context) {
        ...
        function 내함수(){
            코드작성
        }
    }
    return { 내함수 }
    ...
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 검색기능 구현하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*옛날 방식: s 입력시 s가 들어간 HTML을 보이게 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; Vue 방식: s 입력시 follower라는 데이터를 조작&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1691398544043&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;input placeholder=&quot;팔로워검색하기&quot; @input=&quot;search($event.target.value)&quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { onMounted, ref } from 'vue';
import axios from 'axios';

export default {
    name: 'Mypage-components',
    setup(props, context) {
        let follower = ref([]);
        let followerOriginal = ref([]);

        onMounted(() =&amp;gt; {
            axios.get('/follower.json').then((res) =&amp;gt; {
                follower.value = res.data;
                followerOriginal.value = [...res.data];
            });
        });

        function search(검색어) {
            let newFollower = followerOriginal.value.filter((res) =&amp;gt; {
                return res.name.indexOf(검색어) != -1;
            });
            follower.value = [...newFollower];
        }

        return { follower, search };
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/544</guid>
      <comments>https://seungstory.tistory.com/544#entry544comment</comments>
      <pubDate>Mon, 7 Aug 2023 21:09:39 +0900</pubDate>
    </item>
    <item>
      <title>[Vue] 20. PWA</title>
      <link>https://seungstory.tistory.com/542</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 리액트에서 PWA 설치 및 세팅&lt;/p&gt;
&lt;figure id=&quot;og_1691393616976&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[React] PWA&quot; data-og-description=&quot;PWA : Progressive Web App 안드로이드 / iOS 모바일 앱처럼 사용할 수 있게 만드는 웹개발 기술 iOS, Android 앱으로 발행하는게 아니라 웹사이트 자체를 스마트폰 홈화면에 설치 1. PWA 장점 설치 마케팅 비&quot; data-og-host=&quot;seungstory.tistory.com&quot; data-og-source-url=&quot;https://seungstory.tistory.com/396&quot; data-og-url=&quot;https://seungstory.tistory.com/396&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/AEjxM/hyTzc6Zn8x/YpBmNmB9Ki7wqZ4e295Nd1/img.png?width=501&amp;amp;height=72&amp;amp;face=0_0_501_72,https://scrap.kakaocdn.net/dn/iyfB6/hyTy9CqTiK/3xoik4KtMHj2oBVpCnLaG1/img.png?width=501&amp;amp;height=72&amp;amp;face=0_0_501_72,https://scrap.kakaocdn.net/dn/blofl8/hyTzkxbTdU/6EVMUrsYwtl7Um8j9d6Fik/img.png?width=909&amp;amp;height=874&amp;amp;face=0_0_909_874&quot;&gt;&lt;a href=&quot;https://seungstory.tistory.com/396&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seungstory.tistory.com/396&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/AEjxM/hyTzc6Zn8x/YpBmNmB9Ki7wqZ4e295Nd1/img.png?width=501&amp;amp;height=72&amp;amp;face=0_0_501_72,https://scrap.kakaocdn.net/dn/iyfB6/hyTy9CqTiK/3xoik4KtMHj2oBVpCnLaG1/img.png?width=501&amp;amp;height=72&amp;amp;face=0_0_501_72,https://scrap.kakaocdn.net/dn/blofl8/hyTzkxbTdU/6EVMUrsYwtl7Um8j9d6Fik/img.png?width=909&amp;amp;height=874&amp;amp;face=0_0_909_874');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[React] PWA&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;PWA : Progressive Web App 안드로이드 / iOS 모바일 앱처럼 사용할 수 있게 만드는 웹개발 기술 iOS, Android 앱으로 발행하는게 아니라 웹사이트 자체를 스마트폰 홈화면에 설치 1. PWA 장점 설치 마케팅 비&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seungstory.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 라이브러리 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1691393649007&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;vue add pwa&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 배포용 html 생성하기&lt;/h4&gt;
&lt;pre id=&quot;code_1691393714729&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* 주요 파일&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json - 앱 정보를 담은 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;service-worker.js - 웹페이지 구동에 필요한 html, css, js, img를 하드에 저장해두고 사용(오프라인에서도 사용가능하게)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. PWA 설정 변경하기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;vue.config.js 파일 생성&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691394288846&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// vue.config.js
module.exports = {
  pwa: {
    name: '앱이름',
    themeColor: '#4DBA87',
    msTileColor: '#000000',
    workboxOptions: {
      exclude: [/\.map$/, /manifest\.json$/, 'index.html'] // 캐싱 목록에서 제외할 폴더
    }
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* play store에 등록가능한 실제 apk 파일생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://v3.vuejs.org/guide/mobile.html#introduction&quot;&gt;https://v3.vuejs.org/guide/mobile.html#introduction&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1691394062912&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Vue.js - The Progressive JavaScript Framework | Vue.js&quot; data-og-description=&quot;Versatile A rich, incrementally adoptable ecosystem that scales between a library and a full-featured framework.&quot; data-og-host=&quot;vuejs.org&quot; data-og-source-url=&quot;https://v3.vuejs.org/guide/mobile.html#introduction&quot; data-og-url=&quot;https://vuejs.org/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cYIABq/hyTzhmUyXo/XfTKPKaxArhcZrLHkKkPa0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://v3.vuejs.org/guide/mobile.html#introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://v3.vuejs.org/guide/mobile.html#introduction&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cYIABq/hyTzhmUyXo/XfTKPKaxArhcZrLHkKkPa0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Vue.js - The Progressive JavaScript Framework | Vue.js&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Versatile A rich, incrementally adoptable ecosystem that scales between a library and a full-featured framework.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vuejs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/542</guid>
      <comments>https://seungstory.tistory.com/542#entry542comment</comments>
      <pubDate>Mon, 7 Aug 2023 19:56:18 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 19. Vuex</title>
      <link>https://seungstory.tistory.com/541</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Vuex&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;: 사용 이유&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;props, custom event로 데이터를 주고받으면 컴포넌트가 여러개일 때 관리하기가 힘듦&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;(컴포넌트, 데이터 개수가 적을 때는 props가 더 나을 수 있음)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1691341754819&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install vuex@next&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 세팅&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;src폴더 &amp;gt; store.js 파일 생성&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691342178765&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// store.js
import { createStore } from 'vuex';

const store = createStore({
    state() {
        return {
            name: 'kim', // 보관하고 싶은 state(:데이터)
        };
    },
});

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;main.js에 store파일 import&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691342310671&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.js
import { createApp } from 'vue';
import App from './App.vue';
let app = createApp(App);

import store from './store';

app.use(store).mount('#app'); // 모든 컴포넌트들이 이 store 안에 있는 state(:데이터)들을 공유&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 사용하기&lt;/h4&gt;
&lt;pre id=&quot;code_1691342429314&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{{ $store.state.state이름 }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;ex)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691342464076&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{{ $store.state.name }}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;i&gt;&lt;b&gt;❗ Vuex 컴포넌트 안에서 직접 수정 금지&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. state 변경하기1 - mutations(순차적으로 state변경)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;미리 store.js에 수정방법을 정의&lt;/li&gt;
&lt;li&gt;해당 방법을 컴포넌트에서 소환해서 수정&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1691384680760&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// store.js
import { createStore } from 'vuex';

const store = createStore({
    state() {
        return {
            name: 'kim',
            age: 20,
        };
    },
    mutations: { // 순차적으로 state 변경
        updateName(state) {
            state.name = 'park';
        },
        addAge(state, payload) {
            state.age += payload;
        },
    },
});

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691384724002&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div class=&quot;header&quot;&amp;gt;
        &amp;lt;h4&amp;gt;안녕 {{ $store.state.name }}&amp;lt;/h4&amp;gt;
        &amp;lt;button @click=&quot;$store.commit('updateName')&quot;&amp;gt;이름변경&amp;lt;/button&amp;gt;
        
        &amp;lt;span&amp;gt;{{ $store.state.age }}&amp;lt;/span&amp;gt;
        &amp;lt;button @click=&quot;$store.commit('addAge', 3)&quot;&amp;gt;나이추가&amp;lt;/button&amp;gt; &amp;lt;!-- age + 3 --&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. state 변경하기2 -&amp;nbsp; actions(ajax, 오래걸리는작업)&lt;/h4&gt;
&lt;pre id=&quot;code_1691387936870&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// store.js
import axios from 'axios';
import { createStore } from 'vuex';

const store = createStore({
    // 보관하고 싶은 state(:데이터)
    state() {
        return {
            name: 'kim',
            age: 20,
            likes: 0,
            clickLikes: false,
            more: {},
        };
    },
    // 순차적으로 state 변경
    mutations: {
        ...
        setMore(state, data) {
            state.more = data;
        },
    },
    // ajax, 오래걸리는 작업
    actions: {
        getData(context) {
            axios
                .get(`https://codingapple1.github.io/vue/more0.json`)
                .then((res) =&amp;gt; {
                    context.commit('setMore', res.data);
                })
                .catch((err) =&amp;gt; console.log(err));
        },
    },
});

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691387979328&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;p&amp;gt;{{ $store.state.more }}&amp;lt;/p&amp;gt;
    &amp;lt;!-- dispatch: actions요청 --&amp;gt;
    &amp;lt;button @click=&quot;$store.dispatch('getData')&quot;&amp;gt;더보기&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. computed 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;methods 함수: 사용할 때마다 실행&lt;/li&gt;
&lt;li&gt;computed 함수: 사용해도 실행되지 않음.처음 실행할 때 값을 간직함 - 데이터 결과 저장소...&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691390213076&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;p&amp;gt;{{ now() }}{{ counter }}&amp;lt;/p&amp;gt; &amp;lt;!-- methods --&amp;gt;
        &amp;lt;p&amp;gt;{{ now2 }}{{ counter }}&amp;lt;/p&amp;gt;  &amp;lt;!-- computed --&amp;gt;
        &amp;lt;button @click=&quot;counter++&quot;&amp;gt;버튼&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    name: 'App',
    data() {
        return {
            counter: 0,
        };
    },
    methods: {
        now() {
            return new Date();
        },
    },
    computed: {
        now2() {
            return new Date();
        },
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;7. mapState&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;store에 저장한 state 편하게 꺼내 쓰기&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691392956788&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// store.js
import axios from 'axios';
import { createStore } from 'vuex';

const store = createStore({
    state() {
        return {
            name: 'kim',
            age: 20,
            likes: 0,
            clickLikes: false,
            more: {},
        };
    },
    mutations: {
        updateName(state) {
            state.name = 'park';
        },
        addAge(state, payload) {
            state.age += payload;
        },
        likes(state) {
            if (!state.clickLikes) {
                state.likes++;
                state.clickLikes = true;
            } else {
                state.likes--;
                state.clickLikes = false;
            }
        },
        setMore(state, data) {
            state.more = data;
        },
    },
    actions: {
        getData(context) {
            axios
                .get(`https://codingapple1.github.io/vue/more0.json`)
                .then((res) =&amp;gt; {
                    console.log(res.data);
                    context.commit('setMore', res.data);
                })
                .catch((err) =&amp;gt; console.log(err));
        },
    },
});

export default store;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691392997996&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;div&amp;gt;
        &amp;lt;!-- mapState 사용 --&amp;gt;
        {{ name }} {{ age }} {{ likes }}
        {{ 내이름 }}
        
        &amp;lt;button @click=&quot;$store.commit('addAge', 3)&quot;&amp;gt;나이+&amp;lt;/button&amp;gt; &amp;lt;!-- mapState 사용x --&amp;gt;
        &amp;lt;button @click=&quot;addAge(3)&quot;&amp;gt;나이+3&amp;lt;/button&amp;gt; &amp;lt;!-- mapState 사용o --&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import { mapActions, mapMutations, mapState } from 'vuex';

export default {
    name: 'App',
    data() {
        return {
            postData: postData,
            moreCount: 0,
            step: 0,
            image: '',
            writePost: '',
            selectedFilter: '',
            counter: 0,
        };
    },
    methods: {
        ...mapMutations(['addAge', 'likes', 'setMore']),
        ...mapActions(['getData']),
       ...
    },
    computed: {
        ...
        ...mapState(['name', 'age', 'likes']),
        ...mapState({ 내이름: 'name' }),
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/541</guid>
      <comments>https://seungstory.tistory.com/541#entry541comment</comments>
      <pubDate>Mon, 7 Aug 2023 02:23:01 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 18. mitt</title>
      <link>https://seungstory.tistory.com/540</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 구조&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;App.vue &amp;gt; Container.vue &amp;gt; FilterBox.vue&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;mitt 라이브러리를 사용해서 FilerBox 컴포넌트에서 App 컴포넌트로 데이터 전송하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;설치&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691335908478&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install mitt&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;세팅&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691336114100&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// main.js
...
import mitt from 'mitt';
let emitter = mitt();
let app = createApp(App);
app.config.globalProperties.emitter = emitter;
// app.config.globalProperties: 글로벌한 변수보관함 - 보관함에 { emitter: emitter } 추가

app.mount('#app');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;mitt로 데이터 전송하는 방법&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;데이터 전송할 컴포넌트에서 this.emitter.emit()&lt;/li&gt;
&lt;li&gt;데이터 수신할 컴포넌트에서 this.emitter.on()&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;데이터 보내기&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691336327340&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 데이터 보낼 컴포넌트 --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;button @click=&quot;fire&quot;&amp;gt;버튼&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    name: 'Filter-box',
    methods: {
        fire() {
            // this.emitter.emit('작명', '데이터'); // 보낼 데이터 작성
            this.emitter.emit('selectedFilter', this.filter);
        },
    },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;데이터 받기&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691336482989&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 데이터 받는 컴포넌트 --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;!-- 필터선택페이지 --&amp;gt;
    &amp;lt;div v-if=&quot;step == 1&quot;&amp;gt;
        &amp;lt;div :class=&quot;`upload-image ${selectedFilter}`&quot; :style=&quot;{ backgroundImage: `url(${image})` }&quot;&amp;gt;&amp;lt;/div&amp;gt;
        ...
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
    name: 'App',
    data() {
        return {
            postData: postData,
            moreCount: 0,
            step: 0,
            image: '',
            writePost: '',
            selectedFilter: '', // &amp;lt;- 추가
        };
    },
    methods: {
        ...
        publish() {
            let myPost = {
                name: 'Kim Hyun',
                userImage: 'https://picsum.photos/100?random=3',
                postImage: this.image,
                likes: 36,
                date: 'May 15',
                liked: false,
                content: this.writePost,
                filter: this.selectedFilter, //&amp;lt;-emitt으로 받아온 데이터 갱신
            };
            this.postData.unshift(myPost);
            this.step = 0;
        },
    },
    mounted() {
        // this.emitter.on('작명', () =&amp;gt; {
        //     '실행할 코드';
        // });
        this.emitter.on('selectedFilter', (filter) =&amp;gt; {
            this.selectedFilter = filter;
        });
    },
    ...
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗ mitt는 많이 사용하면 관리가 힘들어짐 -&amp;gt; Vuex 사용하기&lt;/p&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/540</guid>
      <comments>https://seungstory.tistory.com/540#entry540comment</comments>
      <pubDate>Mon, 7 Aug 2023 01:57:32 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 17. slot</title>
      <link>https://seungstory.tistory.com/539</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;slot&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;: props보다 간단하게 자식 컴포넌트에서 부모 컴포넌트의 데이터를 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용방법&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;부모 컴포넌트에서 해당 &amp;lt;자식컴포넌트&amp;gt; 태그 사이에 보낼 데이터 작성하기&lt;/li&gt;
&lt;li&gt;자식 컴포넌트의 &amp;lt;template&amp;gt; 태그 사이에 데이터를 사용할 공간에 &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt; 태그 넣기&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1691335067688&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 부모 컴포넌트 --&amp;gt;
&amp;lt;!-- Container.vue --&amp;gt;
&amp;lt;FilterBox v-for=&quot;(filter, i) in filterData&quot; :key=&quot;i&quot; :image=&quot;image&quot; :filter=&quot;filter&quot;&amp;gt;
    {{ filter }} &amp;lt;!--FilterBox 컴포넌트에 보낼 데이터 --&amp;gt;
&amp;lt;/FilterBox&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1691335567608&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 자식 컴포넌트 --&amp;gt;
&amp;lt;!-- FilterBox.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;div :class=&quot;`filter-item ${filter}`&quot; :style=&quot;{ backgroundImage: `url(${image})` }&quot;&amp;gt;
        &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt; &amp;lt;!--여기에 부모에서 넘겨받은 데이터 들어감 --&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/539</guid>
      <comments>https://seungstory.tistory.com/539#entry539comment</comments>
      <pubDate>Mon, 7 Aug 2023 00:26:37 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 16. 서버없이 이미지 업로드</title>
      <link>https://seungstory.tistory.com/538</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;이미지 업로드 한 걸 HTML에 보여주는 방법 두가지&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;FileReader() - 파일을 글자로 변환&lt;/li&gt;
&lt;li&gt;URL.createObjectURL() - 이미지의 가상 URL을 생성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;* 이미지는 원래 0과 1로 이뤄진 binary 데이터임. binary 데이터를 다룰 때 BLOB라는 object에 담아서 다룸&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ex) 파일 업로드 후 다음페이지로 이동 - 이동한 페이지에 업로드한 이미지 띄우기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1691265567294&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- App.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;Container :postData=&quot;postData&quot; :step=&quot;step&quot; :image=&quot;image&quot; /&amp;gt;
    &amp;lt;div class=&quot;footer&quot;&amp;gt;
        &amp;lt;ul class=&quot;footer-button-plus&quot;&amp;gt;
            &amp;lt;!-- multiple: 다중선택 / accept=&quot;image/*&quot;: 이미지 선택을 기본으로 --&amp;gt;
            &amp;lt;input @change=&quot;upload&quot; accept=&quot;image/*&quot; type=&quot;file&quot; id=&quot;file&quot; class=&quot;inputfile&quot; /&amp;gt;
            &amp;lt;label for=&quot;file&quot; class=&quot;input-plus&quot;&amp;gt;+&amp;lt;/label&amp;gt;
        &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import Container from './components/Container.vue';
import postData from './data/postData';
export default {
    name: 'App',
    data() {
        return {
            ...
            step: 0,
            image: '',
        };
    },
    methods: {
        upload(e) {
            let file = e.target.files;
            console.log(file[0]);
            console.log(file[0].type); // 이미지 타입
            let url = URL.createObjectURL(file[0]); // 가상의 이미지 URL 생성
            console.log(url);
            this.image = url;
            this.step++; // 다음 페이지로 이동
        },
    },
    ...
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1691265884907&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- Container.vue --&amp;gt;
&amp;lt;template&amp;gt;
    &amp;lt;!-- 필터선택페이지 --&amp;gt;
    &amp;lt;div v-if=&quot;step == 1&quot;&amp;gt;
        &amp;lt;div class=&quot;upload-image&quot; :style=&quot;{ backgroundImage: `url(${image})` }&quot;&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import Post from './Post.vue';
export default {
    name: 'Container-component',
    props: {
        postData: Array,
        step: Number,
        image: String,
    },
    components: { Post },
};
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
.upload-image {
    width: 100%;
    height: 450px;
    background: cornflowerblue;
    background-size: cover;
}
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/538</guid>
      <comments>https://seungstory.tistory.com/538#entry538comment</comments>
      <pubDate>Sun, 6 Aug 2023 05:05:15 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 15. Ajax</title>
      <link>https://seungstory.tistory.com/537</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;ajax 요청 방법 두가지&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;axios 라이브러리 사용&lt;/li&gt;
&lt;li&gt;기본 fetch 함수 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;i&gt;&amp;gt; axios 라이브러리 사용&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라이브러리 설치하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691261982273&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install axios&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691262813474&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// post 요청
axios.post('URL', {name: 'kim'})
    .then((결과) =&amp;gt; {
        console.log(결과)
    })
    .catch((에러) =&amp;gt; {
        console.log(에러)
    });
    
// get 요청
axios.get('URL')
    .then((결과) =&amp;gt; {
        console.log(결과)
    })
    .catch((에러) =&amp;gt; {
        console.log(에러)
    });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ex) 더보기 클릭시 데이터 받아오기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1691262879350&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
    &amp;lt;button @click=&quot;more&quot;&amp;gt;더보기&amp;lt;/button&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
import postData from './data/postData';
import axios from 'axios';

export default {
    name: 'App',
    data() {
        return {
            postData: postData,
            moreCount: 0,
        };
    },
    methods: {
        more() {
            axios
                .get(`https://codingapple1.github.io/vue/more${this.moreCount}.json`)
                .then((res) =&amp;gt; {
                    console.log(res);
                    this.postData.push(res.data);
                    this.moreCount++;
                })
                .catch((err) =&amp;gt; {
                    console.log(err);
                });
        },
    },
    components: { Container },
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/537</guid>
      <comments>https://seungstory.tistory.com/537#entry537comment</comments>
      <pubDate>Sun, 6 Aug 2023 04:16:02 +0900</pubDate>
    </item>
    <item>
      <title>[Vue.js] 14-2. 라우터 hash mode, Navigation guards</title>
      <link>https://seungstory.tistory.com/535</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 라우터 hash mode&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 세팅했던 라우터 코드&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691249082288&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createRouter, createWebHistory } from 'vue-router'

const router = [];
const router = createRouter({
  history: createWebHistory(),
  routes,
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;history: createWebHistory() - HTML5 mode&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버에 해당 페이지 요청함.&lt;/li&gt;
&lt;li&gt;그래서 Vue가 라우팅 해주기 전에 서버가 해당 페이지를 보여주려고 함.&lt;/li&gt;
&lt;li&gt;서버에 기능 구현이 안되어있으면 404가 뜰 수도 있음 -&amp;gt; 미리 서버에 Vue에서 라우팅 처리하게 맡겨두라고 기능 개발 해둬야함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;history: createWebHashHistory() - Hash mode&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL에 #이 붙음 ex) tistory.com/#&lt;/li&gt;
&lt;li&gt;# 뒤에 있는 내용들은 서버로 전달되지 않음&lt;/li&gt;
&lt;li&gt;그래서 서버가 라우팅을 채가는 일을 방지할 수 있고 Vue에서 온전히 라우팅할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Navigation&amp;nbsp;guards&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특정 URL로 접속할 때 특정 코드를 실행&lt;/li&gt;
&lt;li&gt;네비게이션해주기 전에 실행되는 코드, 훅 같은 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) /home 페이지로 이동 전 로그인하지 않은 상태면 /login 페이지로 이동&lt;/p&gt;
&lt;pre id=&quot;code_1691249930289&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const routes = [
  {
    path: &quot;/home&quot;,
    component: HelloWorld,
    beforeEnter: ()=&amp;gt;{
      if (isLogin == false) { // 로그인하지않았으면
        return '/login' // 로그인 페이지로 이동
      }
    }
  }
];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+ 파라미터&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1691250150643&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const routes = [
  {
    path: &quot;/hello&quot;,
    component: HelloWorld,
    beforeEnter: (to, from)=&amp;gt;{ // 첫번째 파라미터: 도착 페이지 / 두번째 파라미터: 출발 페이지
      return to.fullPath // to.fullPath: 전체 경로 / to.params.id: id 파라미터
    } // return false: 라우팅 중단
  }
];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.1. Vue 컴포넌트 안에서도 navigatrion guard 사용 가능&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lifecycle hook 사용 위치에 사용&lt;/li&gt;
&lt;li&gt;특정 페이지로 접속했을 때 ajax 요청을 할 때 주로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1691250241729&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;beforeRouteEnter(){}
beforeRouteUpdate(){}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Library | Framework/Vue JS</category>
      <author>공부하는 승승</author>
      <guid isPermaLink="true">https://seungstory.tistory.com/535</guid>
      <comments>https://seungstory.tistory.com/535#entry535comment</comments>
      <pubDate>Sun, 6 Aug 2023 00:44:11 +0900</pubDate>
    </item>
  </channel>
</rss>