[Vue] Vue.js 3 문법 기초 정리

hwwwa·2023년 2월 15일
post-thumbnail

Vue.js 3 문법 기초 정리

개발환경

Intel Chip Macbook Pro (2019)
MacOS Monterey 12.6.2
Vue.js 3

설정

Formatter 설정

  • Visual Studio 설정에서 Default Formatter - Prettier 설정, Format On Save 체크 설정하기

    • 프로젝트 폴더 바로 하위에서 .prettierrc 파일을 생성하고 { "semi": false, "bracketSpacing": true, "singleQuote": true, "useTabs": false, "trailingComma": "none", "printWidth": 80 } 내용 추가
    • package.json 파일에서 eslintConfig 부분에 "rules": { "space-before-function-paren": "off" } 내용 추가
  • 특정 영역이 여러 군데에 재사용 가능하다면 components 폴더에 만들기

  • 화면 전체를 차지하는 컴포넌트는 views 폴더에 만들기

    • naming rule: views 폴더에 생성하는 파일은 이름 끝이 View가 포함되도록 생성 ex) HomeView.vue

Vue User Snippets 등록

visual studio 설정 > User Snippets 이동
검색창에 vue 입력 -> vue 선택

"Generate Basic Vue Code" : { "prefix": "vue-start", "body": [ "<template>\n\t<div></div>\n</template>\n<script>\nexport default {\n\tcomponents: {},\n\tdata () {\n\t\treturn {\n\t\t\tsampleData: ''\n\t\t}\n\t},\n\tsetup () {},\n\tcreated() {},\n\tmounted() {},\n\tunmounted() {},\n\tmethods: {}\n}\n</script>" ], "description": "Generate Basic Vue Code" }

index.js에서 View 컴포넌트 호출하기

import { createRouter, createWebHistory } from  'vue-router'
import  HomeView  from  '../views/HomeView.vue'

const routes = [
  { // component 호출 방법 1: app.js에 들어감
    path:  '/',
    name:  'home',
    component:  HomeView
  },
  { // component 호출 방법 2: lazy load 방식
    path:  '/about',
    name:  'about',
    component: () =>  import(/* webpackChunkName: "about" */  '../views/AboutView.vue')
  }
  { // component 호출 방법 3: Prefetch 방식
    path:  '/about2',
    name:  'about2',
    component: () =>  import(/* webpackChunkName: "about2", webpackPrefetch:ture */  '../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router
  • webpackChunkName 을 같은 이름으로 설정해주면 해당하는 메뉴중 하나가 처음 로딩 될 때 그룹핑된 다른 것들도 함께 로딩됨
  • webpackPrefetch 설정 시 초기화면 로딩 시에 설정해둔 페이지도 함께 캐싱됨

Databinding

문자열 바인딩 {{ }}

<template>
  <div>
    <h1>Hello {{  userName  }}</h1>
    <p>{{ message }}</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      userName:  'John Doe',
      message:  ''
    }
  }
}
</script>

HTML 바인딩 v-html

<template>
  <div v-html="htmlString"></div>
</template>
<script>
export default {
  data() {
    return {
      htmlString: '<p style="color:blue;">파란색</p>'
    }
  }
}
</script>

양방향 데이터 바인딩 v-model

  1. Input
<template>
  <div>
    <input type="text" v-model="userId" />
    <button @click="myFunction">click</button>
    <button @click="changeData">change</button>
    <br />
    <input type="text" v-model.number="num1" /> +
    <input type="text" v-model.number="num2" /> =
    <span>{{  num1 + num2  }}</span>
    </div>
</template>
<script>
export default {
  data() {
    return {
      userId: 'hwwwa',  // default value
      num1: 0,
      num2: 0
    }
  },
  methods: {
    myFunction() {
      console.log(this.userId)
    }
  }
}
</script>
  1. Select
<template>
  <div>
    <select v-model="selectedCity">
      <option value=""></option>
      <option value="02">Seoul</option>
      <option value="051">Busan</option>
      <option value="053">Daegu</option>
    </select>
  </div>
</template>
<script>
export default {
  data() {
    return {
      selectedCity: '02'
    }
  }
}
</script>
  1. Checkbox
<template>
  <div>
    <div>
        <input type="checkbox" id="html" value="HTML" v-model="favoriteLang" />
        <label for="html">HTML</label>
    </div>
    <div>
      <input type="checkbox" id="css" value="CSS" v-model="favoriteLang" />
      <label for="css">CSS</label>
    </div>
    <div>
      <input type="checkbox" id="js" value="JS" v-model="favoriteLang" />
      <label for="js">JS</label>
    </div>
      <div>Lang: {{  favoriteLang  }}</div>
    </div>
</template>
<script>
export default {
  data() {
    return {
      favoriteLang: ['JS']
    }
  }
}
</script>
  • radio 버튼 사용 시에는 input type="radio"로 변경해주고 하나만 선택 가능하므로 변수도 문자열로 선언 favoriteLang: 'JS'

Attribute 바인딩 v-bind:

  • readonly와 같이 사용자가 값을 입력해서는 안되는 상황에서는 v-model을 쓰지 않고 v-bind:로 속성 값에 데이터를 바인딩
  • v-bind를 생략하고 :만 사용 가능
<template>
  <div>
    <input type="text" v-bind:value="userId" readonly />
    <input type="text":value="userId" readonly />
    <br />
    <img :src="imgSrc" alt="" style="width: 100px; height: auto" />
    <br />
    <input type="search" v-model="txt1" />
    <button :disabled="txt1 === ''">search</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      userId: 'hwwwa',
      imgSrc: 'https://upload.wikimedia.org/wikipedia/commons/f/f1/Vue.png',
      txt1: ''
    }
  }
}
</script>

리스트 바인딩 v-for

<template>
  <div>
    <div>
      <select name="" id="">
        <option value=""></option>
        <option :value="city.code" :key="city.code" v-for="city in cities">
          {{  city.title  }}
        </option>
      </select>
    </div>
    <div>
      <table>
        <thead>
          <tr>
            <th>ProductNum</th>
            <th>ProductName</th>
            <th>Price</th>
            <th>Quantity</th>
            <th>Sum</th>
          </tr>
        </thead>
        <tbody>
          <tr :key="idx" v-for="(drink, idx)in drinkList">
            <td>{{  drink.drinkId  }}</td>
            <td>{{  drink.drinkName  }}</td>
            <td>{{  drink.price  }}</td>
            <td><input type="number" v-model="drink.qty" /></td>
            <td>{{  drink.price * drink.qty  }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      cities: [
        { title: 'Seoul', code: '02' },
        { title: 'Busan', code: '051' },
        { title: 'Daegu', code: '064' }
      ],
      drinkList: [
        {
          drinkId: '1',
          drinkName: 'coke',
          price: 700,
          qty: 1
        },
        {
          drinkId: '2',
          drinkName: 'orange juice',
          price: 1200,
          qty: 1
        },
        {
          drinkId: '3',
          drinkName: 'coffee',
          price: 500,
          qty: 2
        }
      ]
    }
  }
}
</script>

Class 바인딩

<template>
  <div>
    <div :class="{ 'text-blue': hasError, active: isActive }">
      Class Binding1
    </div>
    <div :class="class2">Class Binding2</div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      isActive:  false,
      hasError:  true,
      class2: ['text-blue', 'hasError']
    }
    }
}
</script>
<style scoped>
.active {
  background-color: greenyellow;
  font-weight: bold;
}
.text-blue {
  color: blue;
}
</style>

Style 바인딩

<template>
  <div>
    <div :style="style1">Style Binding: text blue, font 30px</div>
    <button @click="style1.color = 'green'">color change</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      style1: {
        color:  'blue',
        fontSize:  '30px'
      }
    }
  }
}
</script>

Event

Click Event

<template>
  <div>
    <button @click="increaseCounter">Add 1</button>
    <p>{{  counter  }}</p>
  </div>
</template>
<script>
export default {
  data () {
    return {
      counter: 0
    }
  },
  methods: {
    increaseCounter() {
      this.counter += 1
    }
  }
}
</script>

Change Event

<template>
  <div>
    <!--v-on:change를 @change로 바꿔서 사용 가능-->
    <select name="" id="" @change="changeCity($event)" v-model="selectedCity">
      <option value="">==select city==</option>
      <option :value="city.cityCode" :key="city.cityCode" v-for="city in cityList">
        {{  city.title  }}
      </option>
    </select>
    <select name="" id="">
      <option :value="dong.dongCode" :key="dong.dongCode" v-for="dong in selectedDongList">
        {{  dong.dongTitle  }}
      </option>
    </select>
  </div>
</template>
<script>
export default {
  data () {
    return {
      selectedCity:  '',
      cityList: [
        { cityCode: '02', title: 'Seoul' },
        { cityCode: '051', title: 'Busan' },
        { cityCode: '053', title: 'Daegu' }
      ],
      dongList: [
        { cityCode: '02', dongCode: '1', dongTitle: 'Seoul 1dong' },
        { cityCode: '02', dongCode: '2', dongTitle: 'Seoul 2dong' },
        { cityCode: '051', dongCode: '1', dongTitle: 'Busan 1dong' },
        { cityCode: '051', dongCode: '2', dongTitle: 'Busan 2dong' },
        { cityCode: '053', dongCode: '1', dongTitle: 'Daegu 1dong' },
        { cityCode: '053', dongCode: '2', dongTitle: 'Daegu 2dong' }
      ],
      selectedDongList: []
    }
  },
  methods: {
    changeCity(event) {
      console.log(event.target.tagName)
      this.selectedDongList = this.dongList.filter((dong) => dong.cityCode === this.selectedCity)
    }
  }
}
</script>

Key Event

<template>
  <div>
    <!--방법1-->
    <input type="search" @keyup="checkEnter($event)" v-model="searchText" />
    <button @click="doSearch">Search</button>
    <br />
    <!--방법2. keyup의 다양한 기능 사용하기-->
    <input type="search" @keyup.enter="doSearch" v-model="searchText" />
    <button @click="doSearch">Search</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      searchText:  ''
    }
  },
  methods: {
    doSearch() {
      console.log(this.searchText)
    },
    checkEnter(event) {
      if (event.keyCode === 13) {
        this.doSearch()
      }
    }
  }
}
</script>

0개의 댓글