Vue (3)

Hvvany·2022년 12월 15일
0

vue

목록 보기
9/10

데이터 바인딩

vue 네이밍 규칙 (참고)

원래 규칙이 없지만 vue3 부터는 컴포넌트의 vue파일과 구분하기 위해 views에 vue파일은 뒤에 View를 붙여준다.

  • template 입력하면 자동완성 html.vue 선택
  • template 내부는 하나의 덩어리로 존재해야 한다
  • script 입력하면 자동완성 javascript.vue 선택

style scoped

style scoped 를 하면 파일 내부에만 적용
scoped 를 지우면 모든 파일에서 클래스 적용 가능 but CSS파일을 따로 만들기 때문에 의도적으로 사용 하지는 않는다.

단방향 바인딩 & 양방향 바인딩

서버에서 가져온 데이터를 사용자가 변경하면 바로 변경되는 양방향 바인딩은 뷰가 가지는 매우 큰 장점

계속 반복되는 코드 구성의 기본 틀을 저장하여 쉽게 불러올 수 있다.
File > Preference > User Snippets > Vue.json (Vue) > 아래 코드 붙여넣기

"Generate Basic Vue Code": {
    "prefix": "vue-start",
    "body": [
      "<template>\n\t<div></div>\n</template>\n\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>\n\n<style scoped>\n</style>\n"
    ],
    "description": "Generate Basic Vue Code"
  }

view-start 가 자동완성 탭에 생성되었다.


views내부 StringView.vue 생성

데이터를 바인딩하여 활용할려면 script에 data 안에 return 내부에 정의를 해주어야 한다.


script에서 정의한 userName은 문자열이므로 이중 대괄호로 template에서 바인딩 하여 사용할 수 있다.

router 연결

새로운 vue를 만들었으면 라우터 설정을 반드시 해줘야한다.

App.vue 버튼 생성

string

<template>
  <div>
    <h1>hello {{ userName }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      userName: 'John Doe',
      message: '',
      arr: [],
      obj: {}
    }
  }
}
</script>

html

<template>
  <div>
    <div v-html="html"></div>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      html: '<h1> html 그대로 바인딩!</h1>'
    }
  },
  setup() {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {}
}
</script>

Input

<template>
  <div>
    <input type="text" v-model="userId" />
    <button @click="myFunction">클릭</button>
    <button @click="changeData">변경</button>
    <br />
    <input type="text" v-model="num1" /> +
    <input type="text" v-model="num2" /> =
    <span>{{ num1 + num2 }}</span>
    <br />
    <input type="text" v-model.number="num3" /> +
    <input type="text" v-model.number="num4" /> =
    <span>{{ num3 + num4 }}</span>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      html: '<h1> html 그대로 바인딩!</h1>',
      num1: 0,
      num2: 0,
      num3: 0,
      num4: 0
    }
  },
  setup() {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {
    myFunction() {
      console.log(this.userId)
    },
    changeData() {
      this.userId = 'jason'
    }
  }
}
</script>

<style scoped></style>

select

<template>
  <div>
    <select name="" id="" v-model="selectedCity">
      <option value=""></option>
      <option value="02">서울</option>
      <option value="051">부산</option>
      <option value="064">제주</option>
    </select>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      selectedCity: '051'
    }
  },
  setup() {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {}
}
</script>

<style scoped></style>

기본 값을 return 안에 적어놓으면 기본 선택 되어진다

checkbox

value하고 연결되어 바인딩 되는 것은 아니고 체크된 상태에 따라 배열에 value가 추가, 삭제 되는 형태이다.

<template>
  <div>
    <div>
      <input
        type="checkbox"
        name=""
        id="html"
        value="HTML"
        v-model="favoriteLang"
      />
      <label for="html">HTML</label>
    </div>
    <div>
      <input
        type="checkbox"
        name=""
        id="css"
        value="CSS"
        v-model="favoriteLang"
      />
      <label for="css">CSS</label>
    </div>
    <div>
      <input
        type="checkbox"
        name=""
        id="js"
        value="JavaScript"
        v-model="favoriteLang"
      />
      <label for="js">JavaScript</label>
    </div>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      favoriteLang: ['HTML']
    }
  },
  setup() {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {}
}
</script>

<style scoped></style>

radio

select와 거의 같지만 type과 데이터가 배열이 아니라 문자열 인것이 차이점이다

<div>
  <input
    type="radio"
    ...
  />
</div>
...
return {
  favoriteLang: 'HTML'
}

attribute

단방향 바인딩을 하고 싶을 때

v-model로 양방향 바인딩을 하고 readonly를 적용한다면 양방향 바인딩을 묶을 이유가 없어진다.

<template>
  <div>
    <input type="text" name="" id="" v-model="userId" readonly />
  </div>
</template>

input에 value로 값을 주면 인풋 상자에 자동으로 value값을 채워준다.
따라서 V-bind:value 를 통해 value에 직접 값을 단방향 바인딩하면 된다.
추가적으로 이때 v-bind는 생략가능하다.

<template>
  <div>
    <input type="text" name="" id="" v-bind:value="userId" readonly />
    <input type="text" name="" id="" :value="userId" readonly />
  </div>
</template>

이미지의 src attribute도 v-bind로 연결 가능하다. 심지어 조건문을 통해 활성화/ 비활성화 여부를 결정할 수도 있다...

<template>
  <div>
    <input type="text" name="" id="" v-bind:value="userId" readonly />
    <input type="text" name="" id="" :value="userId" readonly />
    <br />
    <img :src="imgSrc" alt="" style="width: 100px; height: auto" />
    <br />
    <input type="serch" name="" id="" v-model="txt1" />
    <button :disabled="txt1 === ''">조회</button>
  </div>
</template>
<!-- v-bind: -->
<script>
export default {
  components: {},
  data() {
    return {
      userId: '미리보기 값',
      imgSrc:
        'https://data1.pokemonkorea.co.kr/newdata/pokedex/full/000401.png',
      txt1: ''
    }
  },
  setup() {},
  created() {},
  mounted() {},
  unmounted() {},
  methods: {}
}
</script>

List

<template>
  <div>
    <div>
      <select name="" id="">
        <option value=""></option>
        <option :value="city.title" :key="city.code" v-for="city in cities">
          {{ city.title }}
        </option>
      </select>
    </div>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      cities: [
        { title: '서울', code: '02' },
        { title: '부산', code: '051' },
        { title: '제주', code: '064' }
      ]
    }
  },
}
</script>

table

<template>
  <div>
    <div>
      <select name="" id="">
        <option value=""></option>
        <option :value="city.title" :key="city.code" v-for="city in cities">
          {{ city.title }}
        </option>
      </select>
    </div>
    <div>
      <table>
        <thead>
          <tr>
            <th>제품번호</th>
            <th>제품명</th>
            <th>가격</th>
            <th>주문수량</th>
            <th>합계</th>
          </tr>
        </thead>
        <tbody>
          <tr :key="drink.drinkId" v-for="drink in drinkList">
            <td>{{ drink.drinkId }}</td>
            <td>{{ drink.drinkName }}</td>
            <td>{{ drink.price }}</td>
            <td><input type="number" name="" id="" v-model="drink.qty" /></td>
            <td>{{ drink.price * drink.qty }}</td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      cities: [
        { title: '서울', code: '02' },
        { title: '부산', code: '051' },
        { title: '제주', code: '064' }
      ],
      drinkList: [
        { drinkId: '1', drinkName: '코카콜라', price: 700, qty: 1 },
        { drinkId: '2', drinkName: '제로콜라', price: 800, qty: 2 },
        { drinkId: '3', drinkName: '라이트콜라', price: 900, qty: 3 },
        { drinkId: '4', drinkName: '라임콜라', price: 1000, qty: 4 },
        { drinkId: '5', drinkName: '나랑드', price: 1100, qty: 5 }
      ]
    }
  },
}
</script>

key 값을 정해주기 힘들때는 인덱스 번호를 키로 주면 된다.

<tbody>
  <tr :key="i" v-for="(drink, i) in drinkList">
    <td>{{ i }}</td>
    <td>{{ drink.drinkName }}</td>
    <td>{{ drink.price }}</td>
    <td><input type="number" name="" id="" v-model="drink.qty" /></td>
    <td>{{ drink.price * drink.qty }}</td>
  </tr>
</tbody>
profile
Just Do It

0개의 댓글