Vue.js 에서 Component (컴포넌트)를 3가지 방법으로 선언할 수 있다.

1. Global (전역 선언)
2. Local (지역 선언)
3. 파일 분리

 

1,2번의 방법은 사실 별로라고 생각한다. 그 이유인즉슨, 특정 컴포넌트 내에 또 다른 컴포넌트 작성하여 적용시키는 방법이라 생각하면 되는데, 가독성이 좋지 않다.

물론 컴포넌트를 한 개의 파일에서 관리할 수 있다는 매력이 있지만, 애초에 `template` 속성 내에 전부 때려 넣다보니 편리함보다는 오히려 보기가 너무 불편하다.

Syntax Highlight 지원도 받기 어렵다. (혹시 있나?)

 

■ Global [전역]

예시)

이렇게 ' component 명' 을 먼저 선언하고,
그 뒤에 template 속성을 선언하여  `  ` 속에 html 을 비롯한 모든 태그들을 작성하는 것이다.

 

■ Local [지역]

지역 선언은 전역과 약.간. 다르다.

예시)

차이점은 변수에 할당한다는 점... ( ES6로 넘어오면서 코드의 엄격성을 생각하여 var 사용은 자제하자.)
나머지는 동일하게 template 내에 작성한다.

 

■ 파일분리

가장 선호하는 방식이고, 주로 사용되는 방식이다.

[ Header.vue,  Content.vue ] 가 있다면, Header.vue 내에 Content.vueimport하여 사용하는 것이다.

 

경로는 같은 폴더 내를 기준으로 작성하였습니다.

 

이렇게 넣으면 컴포넌트 간따로 파일을 관리하여 유지보수 하기에 용이하다.

데이터 통신을 하기 위해서는 다른 수고를 넣어야하지만, 가독성이 좋아져서 선호한다.

 

 

 

참고 

 

Components | Cracking Vue.js

뷰 컴포넌트 컴포넌트는 화면의 영역을 구분하여 개발할 수 있는 뷰의 기능입니다. 컴포넌트 기반으로 화면을 개발하게 되면 코드의 재사용성이 올라가고 빠르게 화면을 제작할 수 있습니다.

joshua1988.github.io

 

반응형

Linux, Ubuntu, Vue-cli, axios를 사용하는데, proxy 에러가 출력되었다.

Proxy error: Could not proxy request 

 

 

 

■ 해결 방법

해당 에러는 root 경로vue.config.js 에서 proxy 관련 정보를 수정하면 된다.

/vue.config.js

module.exports = {
  devServer: {
    proxy: {
      "/api": {
        target: "https://localhost:8081/",
      },
    },
}

 

기본 경로(/root)가 될 port 번호정보를 작성하면 된다.

 

이제는 path 문제가 남았습니다.....

 

proxy 문제가 해결된것을 확인하실 수 있습니다.

이렇게 axios를 이용해서 데이터를 올바른 경로에서 뽑아오면 되겠습니다.

 

 

 

 

Form Handling | Cracking Vue.js

Form 다루기 폼(Form)은 웹 애플리케이션에서 가장 많이 사용되는 코드 형식입니다. 로그인이나 상품 결제 등 모든 곳에 사용자의 입력을 처리하는 폼이 필요합니다. Form 제작하기 그럼 뷰로 간단

joshua1988.github.io

 

vue proxy 사용하기

vue cli 3.x 버전 이상에서 웹팩 개발서버를 이용해서 프록시 요청을 보내봅시다.

velog.io

 

 

 

반응형

Vue.js - axios를 설치하고 바로 사용하려고 하는데 에러가 발생하였습니다.

 'Axios' is not defined no-undef

당황하였다.

■해결 방법

해당되는 컴포넌트(component)import 해주시면 됩니다.

 

<script>
import axios from 'axios'

export default {
...
}
</script>

이상입니다.

 

 

 

[오류해결] 'Axios' is not defined no-undef

 해결방법 '해당라이브러리' is not defined no-undef 오류가 났을 때는 import를 해주면 간단히 해결된다.

import Axios from 'axios';

iancoding.tistory.com

 

반응형

v-for에는 유용한 기능이 하나 더 있다.

v-for="(value, name, index) in MyObject"

이런식으로 적용이 가능한 점인데, value와 name은 각각 MyObject에서 valuekey를 나타낸다.

예시를 들어보자면,

MyObject = {
  title : 'the title',
  author : 'Sanghoon',
  description : 'Descriptions... This is Vue.js'
 }

MyObject가 이렇게 있을 때,

<div  v-for="(value, name, index) in MyObject">
    {{ index }}.   {{ name }}  :  {{ value }}
</div>

를 작성한다면,

0. title :  the title
1. author  :  Sanghoon
2. description : Descriptions... This is Vue.js

가 된다. 그러니까, 결국에는 json 형태의 keyvalue를 출력할 수 있다는 것이다.

 

vue.js  공식 문서. 클릭시 새창으로 이동

반응형

에러문구

VM8167:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

Vue.js 3 ,  App.vue 에서 json 파일fetch() 하려고 했는데 경로를 옳게 작성했는데 이런 에러가 발생하였음.

해당 파일의 경로같은 폴더 내(/src) 에 있었지만 발생하였고, Network에서 확인하니 404에러가 발생하였다.

 

해결방법

json 파일/src 가 아닌, /public에 넣어서 사용하도록 한다.

경로를 변경해주니 바로 됨...

경로를 변경해주니까 바로 200 success가 반환되었습니다.

 

내부에 js폴더를 추가시켜 사용하여도 똑같이 잘 읽습니다.

public/js/food.json

public/js/food.json
success.200

 

결론.

경로 설정을 잘 합시다.

반응형

안녕하세요 상훈입니다.

Vue.js 에서 라우팅을 정리해볼까합니다. 

 

Route, Routing...  Laravel 에서는 web.php가 그 역할을 가지고 있습니다. 


하지만 저는 Front Framework 부분에서 그 내용을 처리하는 것이 더 옳다고 생각하기 때문에 vue-route에도 신경을 써보았습니다.

처음에는 진짜 정말 ? ? ? 하는 순간에 파일이 휙휙 지나가고 내가 한 게 이게 무엇인가...나는 감자다 이랬는데 여러 번 반복하여 자료를 살펴보고 직접 세팅을 해보았으며 정리를 해보니 대략적인 감을 잡았습니다.

Vue.js 3 에서는 아직 적용해보지 않았고, 현재는 Vue.js 2 만 적용해본 상태입니다.

기본 구성은 이렇습니다.

기본 구성은 위와 같습니다. 

0. Vue project설치하고, vue-router를 설치합니다.

$ vue create '프로젝트명'
$ npm i -S vue-router
$ npm install 

1. router/index.js 생성
2. views/...  : vue 파일들 생성
3. main.js 수정
4. App.vue 수정

이렇게 진행하도록 하겠습니다.


1. router/index.js 생성

router 폴더와 그 안에 index.js를 생성하겠습니다. 그리고 아래와 같은 코드를 작성해줍니다.

import Vue from 'vue'
import VueRouter from 'vue-router'
import FirstPage from '@/views/first-page.vue'
import SecondPage from '@/views/second-page.vue'
import MainPage from '@/views/main-page.vue'

Vue.use(VueRouter)

const routes = [
        {
            path: '/', name: 'MainPage', component: MainPage
        },
        {
            path: '/FirstPage', name: 'FirstPage', component: FirstPage
        },
        {
            path: '/SecondPage', name: 'SecondPage', component: SecondPage
        },
    ]

const router = new VueRouter({
    mode: 'history',
    routes
})
export default router

vue route 관련한 내용을 import.

VueRouter를 사용한다고 선언.

routes의 경로를 직접 지정 저장. => Web.php가 하는 라우팅 역할

router를 출력(?) 내보내기(?) 느낌 실행


2. views/...  : vue 파일들 생성

views라는 폴더를 생성해주시고, 그 안에 해당되는 .vue파일들을 생성해줍니다.

3개의 .vue 파일을 router 이름과 동일하게 생성

 

여기서 잘 보시면 파일제목 <-> route 했던부분의 이름이 다른 것을 확인하실 수 있습니다.

바로 snake-casecamel-case를 지원하는 것인데요, 이에 대해서는 아시리라 생각하고 넘어가겠습니다.


3. main.js 수정

main.js

기존에 src/main.js 에 있던 파일을 살짝 수정하도록 하겠습니다.

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App),
}).$mount('#app')

변경된 부분은

1. import router from './router'
2. Vue 객체 내에 router 선언 
입니다.

이 곳에서 router를 호출하게 되고, app을 렌더링 시켜줍니다.


4. App.vue 수정

마지막으로 App.vue 수정입니다. 이곳에서는 쓸데없는 기존의 부분들을 모두 걷어내주고, 아래와 같이 작성합니다.

<template>
  <div id="app">
    <h1>Router Start</h1>
    <router-link to="/">Main Page</router-link> |
    <router-link to="/FirstPage">First Page</router-link> |
    <router-link to="/SecondPage">Second Page</router-link>
    <router-view />
  </div>
</template>

<script>

export default {
  name: 'App',
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

<router-link> </router-link>
<router-view />

두 가지만 잘 알고 있으면 됩니다. 나머지는 없애도 됩니다.

<router-link to="경로"> a 태그 라고 생각하세요 </router-link>

router link a 태그와 생김새가 동일합니다. 해당 태그를 클릭하면 (1)의 index.js에 의해 routing되어 해당되는 경로로 이동합니다. 

router-view 는 해당되는 view출력해줍니다. 대신 contents만 갈아끼워준다는 느낌이 강합니다.

 

 

[ F12 개발자모드 ] 를 켜서 확인해주시면 <div id="app"> 내의 태그들 reload 되기 때문입니다.

 

이제  $ npm run serve 를 통해 서버를 띄워주시면 아래의 결과가 나옵니다.

라우팅 어려운것,,,,

 

위의 내용 중에 오류잘못 서술한 부분이 있다면

코멘트 남겨주시면 감사하겠습니다.

 

뷰 초보자이지만 천천히 꾸준히 나아가려고 합니다. 감사합니다.

 

제가 정리한 전체적인 흐름입니다.

 

 

 

강의는 짐코더님의 Vuetify 강좌 중에서 반복적으로 연습해보았습니다.

 

 

동적 라우트 매칭 | Vue Router

동적 라우트 매칭 주어진 패턴을 가진 라우트를 동일한 컴포넌트에 매핑해야하는 경우가 자주 있습니다. 예를 들어 모든 사용자에 대해 동일한 레이아웃을 가지지만 하지만 다른 사용자 ID로 렌

router.vuejs.org

반응형

안녕하세요 상훈입니다.

Vue.js cli 를 이용하여 클론코딩을 하였습니다.

 

 

유튜버 분께서 타자가 엄청 빠르시니 적당히 멈추시면서 하세요!
(내용이 아주 좋습니다. 요점을 잘 잡고 간단하게 구현해주었습니다. )

 

 

$ vue create vue-weatherapp

으로 Vue 3 프로젝트를 생성해주었습니다.

그리고 바로 $ npm run serve 를 통하여 구동!

Component를 만들지 않고 오로지 App.vue에서 해당 내용을 작성하였습니다.

 

<template>

<template>
  <div id="App" :class="typeof weather.main != 'undefined' && weather.main.temp > 16 ? 'warm' : '' ">
    <main>
      <div class="search-box">
        <input 
          type="text" 
          class="search-bar" 
          placeholder="Search..."
          v-model="query" 
          @keypress="fetchWeather" 
        />
      </div>

      <div class="weather-wrap" v-if="typeof weather.main != 'undefined'">
        <div class="location-box">
          <div class="location">{{ weather.name }}, {{ weather.sys.country }}</div>
          <div class="date">{{ dateBuilder() }}</div>
        </div>

        <div class="weather-box">
          <div class="temp">{{ Math.round(weather.main.temp) }}</div>
          <div class="weather">{{ weather.weather[0].main }}</div>
        </div>

      </div>
    </main>
  </div>
</template>

 

<script>

<script>
export default {
  name: 'App',
  data() {
    return {
      api_key : 'd5297dac23efd490788f837861e52f62',
      url_base: 'https://api.openweathermap.org/data/2.5/',
      query: '',
      weather: {},
    }
  },
  methods: {
    fetchWeather (e) {
      if (e.key == "Enter") {
        fetch(`${this.url_base}weather?q=${this.query}&units=metric&APPID=${this.api_key}`)
          .then(res => {
            return res.json();
          }).then(this.setResults);
      }
    },
    setResults (results) {
      this.weather = results;
    },
    dateBuilder () {
      let d = new Date()
      let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
      let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

      let day = days[d.getDay()];
      let date = d.getDate();
      let month = months[d.getMonth()-1];
      let year = d.getFullYear();

      return `${day} ${date} ${month} ${year}`;
    }
  }
  
}
</script>

 

 

<style>

<style>
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body{
  font-family: 'montserrat', sans-serif;
}

#App{
  background-image: url('./assets/cold-bg.jpg');
  background-color: aquamarine;
  background-size: cover;
  background-position: bottom;
  transition: 0.4s;
}

#App.warm {
  background-image: url('./assets/warm-bg.jpg');
}

main{
  min-height: 100vh;
  padding: 25px;

  background-image: linear-gradient(to bottom, rgba(0,0,0,0.25), rgba(0,0,0,0.75));
}

.search-box{
  width: 100%;
  margin-bottom: 30px;
}

.search-box .search-bar {
  display:block;
  width: 100%;
  padding: 15px;

  color: #313131;
  font-size:20px;

  appearance: none;
  border: none;
  outline: none;
  background: none;

  box-shadow: 0px 0px 8px rgba(0,0,0,0.25);
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 0px 16px;
  transition: 0.4s;
}

.search-box .search-bar:focus{
  box-shadow: 0px 0px 16px rgba(0,0,0,0.25);
  background-color: rgba(255, 255, 255, 0.75);
  border-radius: 16px 0px;
}

.location-box .location {
  color: #FFF;
  font-size: 32px;
  font-weight: 500;
  text-align: center;
  text-shadow: 1px 3px rgba(0,0,0,0.25);
}

.location-box .date {
  color: #FFF;
  font-size: 20px;
  font-weight: 300;
  font-style: italic;
  text-align: center;
}

.weather-box {
  text-align: center;
}

.weather-box .temp{
  display: inline-block;
  padding: 10px 25px;
  color: #FFF;
  font-size: 102px;
  font-weight: 900;

  text-shadow: 3px 6px rgba(0,0,0,0.25);
  background-color: rgba(255, 255, 255, 0.25);
  border-radius: 16px;
  margin: 30px 0px;

  box-shadow: 3px 6px rgba(0,0,0,0.25);
}

.weather-box .weather {
  color: #FFF;
  font-size: 48px;
  font-weight: 700;
  font-style: italic;
  text-shadow: 3px 6px rgba(255, 255, 255, 0.25);
}
</style>

 

 

결과물입니다.

도시명을 작성하면 해당되는 api를 가져와 띄워줍니다.

 

아프리카는 28도네요 ㄷㄷ

 

이상입니다.

 

무료 기상 API 주소 입니다. 개발 공부에 참고하세요!!

 

Сurrent weather and forecast - OpenWeatherMap

Access current weather data for any location on Earth including over 200,000 cities! The data is frequently updated based on the global and local weather models, satellites, radars and a vast network of weather stations. how to obtain APIs (subscriptions w

openweathermap.org

클릭 시 새 창으로 이동 

 

반응형

안녕하세요 상훈입니다.

 

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

 

Vue.js , API, Fetch(), 비동기 통신 간에 에러가 발생하였습니다. 

 

이 에러가 처음에는 제가 오타를 내서 발생한 에러인줄 알았으나(근데 오타도 있었음), 

오타의 문제가 아니었습니다.

 

1. F12 -> Network 를 확인해주세요.

2. api를 가져올 때 주소를 잘못 작성한 것을 저는 확인하였습니다. 

HTTPS:// 를 붙여주지 않아 인터넷 접속을 하지 않고 발생한 에러

그리고 다시 url_base를 사용하니 원활히 출력되었습니다!

 

F12-Network 에서 `200 status`로 잘 얻어왔습니다.

주소 주의하세욤..

vue.js - weather clone-coding ing... 

 

 

이상입니다.

참고

 

React Js: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

I want to fetch my Json file in react js, for this I am using fetch. But it shows an error Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0 What could be the error,...

stackoverflow.com

 

반응형

+ Recent posts