안녕하세요 상훈입니다.

Vue.js에서 반복문을 사용하고, 그 속에서 data binding이 된 객체 데이터를 출력하는 방법을 포스팅하겠습니다.

 

1. data

2. template

 

1. data

import products from './assets/listData.js'
export default {
  name: 'App',
  data () {
    return {
      products: products,
      }
    }
  }

 

외부의 객체 배열을 products라는 변수import 하여 vue 내에서 products로 사용하겠다고 선언한 내용입니다.

아래는 export한 객체 배열 내용 예시입니다.

export한 js객체 배열

 

2. template

자, 이제 반복문과 그에 해당하는 문법을 작성해야겠죠?

for의 기본 문법입니다.

<div v-for="item in items" :key="item"></div>
<div v-for="(item, index) in items" :key="item"></div>

JavaScript 혹은 React 같은 경우 많이 작성하는 방식입니다.

첫 번째는 1개의 인자만 사용할 경우이고, 두 번째는 index를 주고 싶을 경우입니다.

 

저는 이 중 첫 번째만 사용해보도록하겠습니다.

 <div v-for="product in products" :key="product">
    <img src="{{ product.image }}" alt="이미지">
    <h4>{{ product.title }}</h4>
    <p>{{ product.price }}원</p>
  </div>

작성 방법은 받아온 객체의 key값을 기준으로 작성하면 value가 출력되어져 나오는 방식입니다.

laravel의 blade 문법이 생각나는군요

결과 화면

결과입니다. css를 제대로 적용시켜주지 않고, 이미지 url이 올바르게 작성되어있지 않아 이미지가 깨졌지만, 나머지는 정상적으로 반복되어 출력되었습니다.

 

 

이상입니다.

 

반응형

안녕하세요 상훈입니다.

Vue.js에서 Javascript의 onclick addEventListener와 같이 onclick 이벤트를 주는 방법을 설명하겠습니다.

뷰는 매우 간단하더군요.

0. 기본문법

<button v-on:click=""></button>
<button @click=""></button>

v-on:click 이 기본, 

그리고 @click이 축약 버전입니다. 입맛에 맞게 사용하시면 됩니다.

1. 익히 알고 있는 함수 호출하기

2. 간단한 연산 결과값 도출

 

1. 함수 호출하기

<button @click="LetsGoVue"></button>

<script>
export default {
  name: 'App',
  data() {},
  methods: {
  	LetsGoVue() {
    	console.log('hello')
    }
  }

</script>

console.log에 출력

 

2. 연산 결과값 도출 [ v-if, v-on:click ] 

예시) 모달창 팝업

버튼 클릭 시, 모달창이 뜨고 사라지게 하는 내용을 구현하겠습니다.

<div class="black-bg" v-if="modalStatus">
    <div class="white-bg">
      <h4>상세페이지</h4>
      <p>상세페이지 내용</p>
      <button class="modal-close" @click="modalStatus = 0 ">닫기</button>
    </div>
</div>

모달레이아웃 div 부분입니다. 

modalStatus라는 변수가 1일 때만 해당 내용이 존재하게 하는 조건문[ v-if ] 으로 구현하였습니다.

button을 클릭시 modalStatus라는 변수에 0을 대입하는 것으로 구현하였습니다.

modalStatus의 기본값

script 내 data 내에 modalStatus 변수의 기본값을 0으로 설정하여 처음 렌더링 되었을 때, 보이지 않게 설정하였습니다.

 

 

 

반응형

안녕하세요 상훈입니다.

리눅스에서 폴더명 변경, 혹은 폴더 이동을 하고 싶을 때 하는 명령어를 포스팅하겠습니다.

$  mv  변경이전폴더명  변경할폴더명

입니다.

 

간단한 mv 명령어

 

 

반응형

안녕하세요 상훈입니다.

안드로이드 - 갤럭시 폰에서 개발자 모드 켜는 방법을 포스팅하겠습니다.

 

 

설정 - 휴대전화 정보 - 소프트웨어 정보 - 빌드번호 7번 연타 - 비밀번호 입력 - 개발자옵션

 

끝입니다. 

 

 

 

 

 

개발자모드에서는 다양한 것들을 설정이 가능합니다. 

저는 탭할때 포인터 뜨는 옵션을 항상 활성화 시켜놓습니다.

반응형

안녕하세요 상훈입니다.

Vuejs를 설치하여 사용 할 수 있도록 vue js 설치하는 방법을 간단하게 명령어로 설명하도록 하겠습니다.

$ npm install -g @vue/cli 

이렇게 작성하시면 자동으로 설치가 완료 됩니다.

 

그리고 vue 명령어를 사용하실 수 있게됩니다.

예시) vue 버전 확인하기

$ vue --version

기타 다른명령어가 무엇이 있는지 확인

$ vue 
Usage: vue <command> [options]

Options:
  -V, --version                              output the version number
  -h, --help                                 output usage information

Commands:
  create [options] <app-name>                create a new project powered by vue-cli-service
  add [options] <plugin> [pluginOptions]     install a plugin and invoke its generator in an already created project
  invoke [options] <plugin> [pluginOptions]  invoke the generator of a plugin in an already created project
  inspect [options] [paths...]               inspect the webpack config in a project with vue-cli-service
  serve [options] [entry]                    serve a .js or .vue file in development mode with zero config
  build [options] [entry]                    build a .js or .vue file in production mode with zero config
  ui [options]                               start and open the vue-cli ui
  init [options] <template> <app-name>       generate a project from a remote template (legacy API, requires @vue/cli-init)
  config [options] [value]                   inspect and modify the config
  outdated [options]                         (experimental) check for outdated vue cli service / plugins
  upgrade [options] [plugin-name]            (experimental) upgrade vue cli service / plugins
  migrate [options] [plugin-name]            (experimental) run migrator for an already-installed cli plugin
  info                                       print debugging information about your environment

  Run vue <command> --help for detailed usage of given command.

 

 

이상입니다.

리액트했다가 뷰했다가 환장파티~!

 

https://online.codingapple.com/wp-content/uploads/2021/03/1_oZqGznbYXJfBlvGp5gQlYQ-600x294.jpeg

 

반응형

안녕하세요 상훈입니다.

드림코딩 앨런님의 강의로 자바스크립트를 이용하여 짧고 간단한 쇼핑 웹앱을 구현하도록 해보겠습니다.

결과 화면

 

index.html

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <script src="src/main.js" defer></script>
  <title>Document</title>
</head>
<body>
  <!--Logo-->
  <img src="img/logo.png" alt="Logo" class="logo">

  <!--Buttons-->
  <div class="buttons">
    <button class="btn">
      <img src="img/blue_t.png" alt="blue tshirts" class="imgBtn" data-key="type" data-value="tshirt" />
    </button>
    <button class="btn">
      <img src="img/blue_p.png" alt="blue pants" class="imgBtn" data-key="type" data-value="pants" />
    </button>
    <button class="btn">
      <img src="img/blue_s.png" alt="blue skirt" class="imgBtn" data-key="type" data-value="skirt" />
    </button>
    <button class="btn" class="btn colorBtn blue"  data-key="color" data-value="blue">Blue</button>
    <button class="btn" class="btn colorBtn yellow" data-key="color" data-value="yellow">Yellow</button>
    <button class="btn" class="btn colorBtn pink" data-key="color" data-value="pink">Pink</button>
  </div>
  <!--Items-->
  <ul class="items"></ul>
</body>
</html>

 

 

main.js

// Fetch the items from the JSON file
function loadItems() {
    return fetch('data/data.json')
    .then(response => response.json())
    .then(json => json.items)
}

// update the list with the given items
function displayItems(items) {
    const container = document.querySelector('.items')
    container.innerHTML = items.map(item => createHTMLString(item)).join('')
}

// Create html list item from the given data item
function createHTMLString (item) {
    return `
        <li class="item">
            <img src="img/${item.image}" alt="${item.type}" class="item__thumbnail">
            <span class="item__description">${item.gender}, ${item.size}</span>
        </li>
    `
}

function onButtonClick (event, items) {
    const dataset = event.target.dataset
    const key = dataset.key
    const value = dataset.value

    if(key == null || value == null){
        return ;
    }

    // updateItems(items, key, value)

    const filtered = items.filter(item => item[key] === value)
    displayItems(filtered)
}

function updateItems(items, key, value) {
    items.forEach(item => {
        if(item.dataset[key] === value) {
            item.classList.remove('invisiable')
        }else{
            item.classList.add('invisable')
        }
    });
}


function setEventListeners (items) {
    const logo = document.querySelector('.logo')
    const buttons = document.querySelector('.buttons')
    logo.addEventListener("click", () => displayItems(items) )
    buttons.addEventListener("click", event => onButtonClick(event, items))
}


// main
loadItems() 
    .then(items => {
        displayItems(items)
        setEventListeners(items)
    })
    .catch(console.log)

 

 

style.css

:root {
  /* color */
  --color-black: #3f454d;
  --color-white: #ffffff;
  --color-blue: #3b88c3;
  --color-yellow: #fbbe28;
  --color-pink: #fd7f84;
  --color-light-grey: #dfdfdf;

  /* size */
  --base-space: 8px;
  --size-button: 60px;
  --size-border: 4px;
  --size-thumbnail: 50px;
  --font-size: 18px;

  /* animation */
  --animation-duration: 300ms;
}

body {
  height:100vh;
  background-color: var(--color-black);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.logo {
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
}

.btn {
  background-color: transparent;
  border: none;
  outline: none;
  cursor: pointer;
  transition: transform var(--animation-duration) ease;
  margin-right: var(--base-space);
}

.btn:hover,
.logo:hover {
  transform: scale(1.1);
}

.buttons {
  display: flex;
  align-items: center;
}

.imgBtn {
  width: var(--size-button);
  height:var(--size-button);
}

.colorBtn {
  font-size: var(--font-size);
  padding: calc(var(--base-space) * 2);
  border-radius: var(--size-border);
}

.blue {
  background-color: var(--color-blue);
}

.yellow {
  background-color: var(--color-yellow);
}

.pink {
  background-color: var(--color-pink);
}

.items {
  width: 60%;
  height: 60%;
  list-style: none;
  padding-left:0;
  overflow-y: scroll;
}

.item {
  background-color: var(--color-white);
  display: flex;
  align-items: center;
  padding: var(--base-space);
  margin-bottom: var(--base-space);
}

.item__thumbnail {
  width: var(--size-thumbnail);
  height: var(--size-thumbnail);
}

.item__description {
  margin-left: var(--base-space);
  font-size: var(--font-size);
}

 

디렉터리 구조

디렉터리 구조는 다음과 같습니다. 강의 영상에서 제공한 project 자체를 import 시켰습니다.

이미지, json 등의 파일은 모두 구비되었습니다.

 

강의 진행이 되면서 간단하다 간단하다 하셨는데, 전혀 간단하게 느껴지지 않았습니다. ㅠㅠ

자바스크립트의 filter, map 등등 몇가지 라이브러리를 사용하셨었는데, 

저같은 웹린이한테는 어렵다고 느껴졌어요...

눈물..

나는 감자다! I'm annoied talking potatoooooooo!!!!

 

반응형

안녕하세요 상훈입니다.

마인크래프트에서 같은 인터넷선으로 게임을 하려고 합니다.

멀티게임 - 로컬 서버 인데요,

방법 간단합니다.

1. 서버를 한쪽에서 생성합니다.

2. 생성 완료되면 번호를 줍니다. ex) 50068

3. 입장하는 쪽에서 멀티플레이 [ 직접연결 ] or [ 서버 추가 ] 를 해줍니다.

 

4. 서버 주인의 ip 주소를 확인합니다.

win + r 해서 실행창을 띄워줍니다.

 

 

ipconfig 를 쳐줍니다.

 

노란색으로 칠해진 부분이 내부 아이피 주소 입니다. (외부 아이피 안돼요)

 

5. 2번에서 생성한 번호와 함께 연결

주소를 포트번호와 입력해줍니다.

아이피주소:2번주소

아이피주소 : 2번번호

 

6. 접속 완료

 

 

 

즐겜하십셔

반응형

안녕하세요 상훈입니다.

리액트 - 차트를 이용해 코로나19의 현황을 간단하게 알아보는 예제를 출력하겠습니다.

결과화면

Contents.js

import React, {useState, useEffect} from 'react'
import { Bar, Doughnut, Line } from "react-chartjs-2"
import axios from 'axios'


const Contents = () => {

    const [confirmedData, setConfirmedData] = useState({})
    const [quarantinedData, setQuarantinedData] = useState({})
    const [comparedData, setComparedData] = useState({})




    useEffect(() => {
        const fetchEvents = async () => {
            const res = await axios.get("https://api.covid19api.com/total/dayone/country/kr")
            console.log(res)
            makeData(res.data)

        }
        const makeData = (items)=>{
            const arr = items.reduce((acc, cur) => {
                const currentDate = new Date(cur.Date)
                const year = currentDate.getFullYear()
                const month = currentDate.getMonth()
                const date = currentDate.getDate()
                const confirmed = cur.Confirmed
                const active = cur.Active
                const death = cur.Death
                const recovered = cur.Recovered

                const findItem = acc.find(a=> a.year === year && a.month === month)

                if(!findItem){
                    acc.push({ year, month, date, confirmed, active, death, recovered })
                }
                if(findItem && findItem.date < date){
                    findItem.active = active
                    findItem.death = death
                    findItem.date = date
                    findItem.year = year
                    findItem.month = month
                    findItem.recovered = recovered
                    findItem.confirmed = confirmed

                }
                return acc;

            }, [])


            const labels = arr.map(a => `${a.month+1}월`)
            setConfirmedData({
                labels,
                datasets: [
                    { 
                        label: "국내 누적 확진자", 
                        backgroundColor: "salmon",
                        fill: true,
                        data: arr.map(a => a.confirmed)
                    },
                ]
            })

            setQuarantinedData({
                labels,
                datasets: [
                    { 
                        label: "월별 격리자 현황", 
                        borderColor: "salmon",
                        fill: false,
                        data: arr.map(a => a.active)
                    },
                ]
            })

            const last = arr[arr.length -1 ]
            setComparedData({
                labels: ["확진자","격리해제","사망"],
                datasets: [
                    { 
                        label: "누적 확진, 해제, 사망 비율", 
                        backgroundColor: ["#ff3d67", "#059bff", "#ffc233"],
                        borderColor: ["#ff3d67", "#059bff", "#ffc233"],
                        fill: false,
                        data: [last.confirmed, last.recovered, last.death]
                    },
                ]
            })
        }
        fetchEvents()
    }, [])

    return (
        <section>
            <h2>국내 코로나 현황</h2>
            <div className="contents">
                <div>
                    <Bar data={confirmedData} options={
                        {title: { display : true, text: "누적 확진자 추이", fontSize: 16 } },
                        {legend: {display : true, position: "bottom"} }
                    } />
                </div>
                <div>
                    <Line data={quarantinedData} options={
                        {title: { display : true, text: "월별 격리자 현황", fontSize: 16 } },
                        {legend: {display : true, position: "bottom"} }
                    } />
                </div>
                <div>
                    <Doughnut data={comparedData} options={
                        {title: { display : true, text: `누적 확진, 해제, 사망 (${new Date().getMonth() + 1 })`, fontSize: 16 } },
                        {legend: {display : true, position: "bottom"} }
                    } />
                </div>
            </div>
        </section>
    )
}

export default Contents

 

 

App.css

.App {
  display: flex;
  flex-direction: column;
}

.header {
  background-color: #3b5998;
  display: flex;
  justify-content: space-between;
  padding: 1rem 2rem;
  align-items: center;
}

.header h1{
  color:azure;
}

.header select {
  height: 30px;
  width: 140px;
  border-radius: 5px;
  border: none;
}

section {
  padding: 1rem;
}

.contents {
  width: 60%;
  text-align:center;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap : 2rem;
}

 

원형차트는 아무래도 확진자 대비 나머지 비율이 너무 작아서 안보이는 건지,,,, 아니면 제가 api 적용을 잘못한건지 헷갈립니다... ㅠㅠ

나중에 확인 해야할 것 같아요. 그럼 이만ㅌㅌ

 

 

강의 참고

React.js로 웹앱 만들기

 

리액트와 가까워지기.
(어렵당)

 

반응형

+ Recent posts