TSLint 추가
show / ask / jobs를 사용하여 제작
hacker news
api 깃허브
vue create vue-news
cd vue-news
npm run serve
npm i vue-router@3.5.3 --save
export를 하면 다른 곳에서 import 할 수 있다
import Vue from 'vue'
import VueRouter from 'vue-router';
import NewsView from '../views/NewsView.vue';
import AskView from '../views/AskView.vue';
import JobsView from '../views/JobsView.vue';
Vue.use(VueRouter);
export const router = new VueRouter({
routes: [
{
// path: url 주소
path: '/news',
// component: url 주소로 갔을 때 표시될 컴포넌트
component: NewsView,
},
{
path: '/ask',
component: AskView,
},
{
path: '/jobs',
component: JobsView,
}
]
});
각각의 형태가 같지만 이름은 다른 View 세개 생성
<template>
<div>
News
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
router를 import
import Vue from 'vue'
import App from './App.vue'
import { router } from './router/index.js';
Vue.config.productionTip = false
new Vue({
render: h => h(App),
router,
}).$mount('#app')
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</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>
첫번째 페이지를 news 페이지로 띄우기
import Vue from 'vue'
import VueRouter from 'vue-router';
import NewsView from '../views/NewsView.vue';
import AskView from '../views/AskView.vue';
import JobsView from '../views/JobsView.vue';
Vue.use(VueRouter);
export const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/news',
},
{
// path: url 주소
path: '/news',
// component: url 주소로 갔을 때 표시될 컴포넌트
component: NewsView,
},
{
path: '/ask',
component: AskView,
},
{
path: '/jobs',
component: JobsView,
}
]
});
페이지 네비게이션
<template>
<div id="app">
<tool-bar></tool-bar>
<router-view></router-view>
</div>
</template>
<script>
import ToolBar from './components/ToolBar.vue';
export default {
components: {
ToolBar,
},
}
</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>
<template>
<div>
<router-link to="/news">News</router-link>
<router-link to="/ask">Ask</router-link>
<router-link to="/jobs">Jobs</router-link>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
scoped 해당 컴포넌트에만 적용됨
<template>
<div class="header">
<router-link to="/news">News</router-link> |
<router-link to="/ask">Ask</router-link> |
<router-link to="/jobs">Jobs</router-link>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
.header {
color: white;
background-color: #42b883;
display: flex;
padding: 8px;
}
.header .router-link-exact-active {
color: #35495e;
}
.header a {
color: white;
}
</style>
<style>
#app {
padding: 0;
margin: 0;
}
</style>
ItemView.vue / UserView.vue를 만든 후 router 연결
import Vue from 'vue'
import VueRouter from 'vue-router';
import NewsView from '../views/NewsView.vue';
import AskView from '../views/AskView.vue';
import JobsView from '../views/JobsView.vue';
import ItemView from '../views/ItemView.vue';
import UserView from '../views/UserView.vue';
Vue.use(VueRouter);
export const router = new VueRouter({
routes: [
{
path: '/',
redirect: '/news',
},
{
// path: url 주소
path: '/news',
// component: url 주소로 갔을 때 표시될 컴포넌트
component: NewsView,
},
{
path: '/ask',
component: AskView,
},
{
path: '/jobs',
component: JobsView,
},
{
path: '/user',
component: UserView,
},
{
path: '/item',
component: ItemView,
}
]
});
mode: 'history'
import Vue from 'vue'
import VueRouter from 'vue-router';
import NewsView from '../views/NewsView.vue';
import AskView from '../views/AskView.vue';
import JobsView from '../views/JobsView.vue';
import ItemView from '../views/ItemView.vue';
import UserView from '../views/UserView.vue';
Vue.use(VueRouter);
export const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
redirect: '/news',
},
{
// path: url 주소
path: '/news',
// component: url 주소로 갔을 때 표시될 컴포넌트
component: NewsView,
},
{
path: '/ask',
component: AskView,
},
{
path: '/jobs',
component: JobsView,
},
{
path: '/user',
component: UserView,
},
{
path: '/item',
component: ItemView,
}
]
});
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
users: []
}
},
created() {
var vm = this;
axios.get('https://api.hnpwa.com/v0/news/1.json')
.then(function(response){
console.log(response);
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
},
}
</script>
<style>
</style>
📂src -> 📂api -> index.js
import axios from 'axios';
const config = {
baseUrl: 'https://api.hnpwa.com/v0/'
}
function fetchNewsList() {
// return axios.get(config.baseUrl + 'news/1.json');
return axios.get(`${config.baseUrl}news/1.json`);
}
export {
fetchNewsList
}
👉두가지 방법 다 사용 가능
- return axios.get(config.baseUrl + 'news/1.json');
- return axios.get(
${config.baseUrl}news/1.json
); (백틱)
중복되는 url을 따로 관리
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchNewsList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
var vm = this;
fetchNewsList()
.then(function(response){
console.log(response);
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
},
}
</script>
<style>
</style>
AskView, JobsView 똑같이 구현해보기
import axios from 'axios';
const config = {
baseUrl: 'https://api.hnpwa.com/v0/'
}
function fetchNewsList() {
// return axios.get(config.baseUrl + 'news/1.json');
return axios.get(`${config.baseUrl}news/1.json`);
}
function fetchAskList() {
return axios.get(`${config.baseUrl}ask/1.json`);
}
function fetchJobsList() {
return axios.get(`${config.baseUrl}jobs/1.json`);
}
export {
fetchNewsList,
fetchAskList,
fetchJobsList,
}
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchAskList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
var vm = this;
fetchAskList()
.then(function(response){
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
}
}
</script>
<style>
</style>
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchJobsList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
var vm = this;
fetchJobsList()
.then(function(response){
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
}
}
</script>
<style>
</style>
created: function () -> created() 생략가능
reactivity in depth
화살표로 한줄 표기 가능
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchJobsList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
fetchJobsList()
.then(response => this.users = response.data)
.catch(error => console.log(error));
}
}
</script>
<style>
</style>
자바스크립트에서는 this는 전역 함수
this
this(함수)
this(비동기처리)
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchNewsList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
console.log('호출 전->',this);
var vm = this;
fetchNewsList()
.then(function(response){
console.log('호출 후->',this);
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
},
}
</script>
<style>
</style>
데이터를 요청하고 받아올 때까지 기다려주지 않고 다음 코드인 return response를 실행했기 때문에 초기값을 설정해주지 않은 response 값은 undefined로 출력한다.
이렇게 특정 로직의 실행이 끝날 때까지 기다려주지 않고 나머지 코드를 먼저 실행하는 것이 비동기 처리이다. 동기, 비동기 참고 자료
컴포넌트를 가리키는 this을 바로 호출 가능하다
<template>
<div>
<div v-for="(user, index) in users" :key="index">{{ user.title }}</div>
</div>
</template>
<script>
import { fetchNewsList } from '../api/index.js';
export default {
data() {
return {
users: []
}
},
created() {
console.log('호출 전->',this);
var vm = this;
fetchNewsList()
.then(response => {
console.log('호출 후->',this);
vm.users = response.data;
})
.catch(function(error){
console.log(error);
});
},
}
</script>
<style>
</style>
<!DOCTYPE html>
<html lang="en">
<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">
<title>Callback</title>
</head>
<body>
<div>jquery ajax</div>
<script src="https://code.jquery.com/jquery-3.6.3.js" integrity="sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM="
crossorigin="anonymous"></script>
<script>
function fetchData() {
// 1
var result = [];
// 2
$.ajax({
url: 'https://api.hnpwa.com/v0/news/1.json',
success: function(data) {
console.log('데이터 호출 결과', data);
result = data;
console.log('ajax 함수 결과', result);
}
});
// 3
console.log('함수 결과', result);
}
fetchData();
</script>
</body>
</html>
mdn promise
Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타냅니다.
<!DOCTYPE html>
<html lang="en">
<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">
<title>Promise</title>
</head>
<body>
<div>jquery ajax</div>
<script src="https://code.jquery.com/jquery-3.6.3.js" integrity="sha256-nQLuAZGRRcILA+6dMBOvcRh5Pe310sBpanc6+QBmyVM="
crossorigin="anonymous"></script>
<script>
function callAjax() {
return new Promise(function(resolve, reject) {
$.ajax({
url: 'https://api.hnpwa.com/v0/news/1.json',
success: function(data) {
// console.log(data);
resolve(data);
}
});
});
}
function fetchData() {
// 1
var result = [];
callAjax()
.then(function(data) {
console.log('데이터 호출 결과', data);
result = data;
console.log('ajax 함수 결과', result);
});
}
fetchData();
</script>
</body>
</html>