실행하는 환경

실행되는 환경

실행되는 공간

 

컨텍스트의 원칙

  • 먼저 전역 컨텍스트 하나 생성 후, 함수 호출 시마다 컨텍스트가 생깁니다.
  • 컨텍스트 생성 시 컨텍스트 안에 변수객체(arguments, variable), scope chain, this가 생성됩니다.
  • 컨텍스트 생성 후 함수가 실행되는데, 사용되는 변수들은 변수 객체 안에서 값을 찾고, 없다면 스코프 체인을 따라 올라가며 찾습니다.
  • 함수 실행이 마무리되면 해당 컨텍스트는 사라집니다.(클로저 제외) 페이지가 종료되면 전역 컨텍스트가 사라집니다.
'컨텍스트': {
  변수객체: {
    arguments: [{ word : 'hello' }],
    variable: null,
  },
  scopeChain: ['wow 변수객체', '전역 변수객체'],
  this: window,
}

 

스코프 : 범위, 함수를 선언할 때 만들어진다.

전역변수 / 지역변수

 

스코프체인 : 찾는 변수가 내부에 없으면 외부로 -> 전역으로 이어서 찾아가는 것

내부에선 외부로 참조 가능, 외부에서 내부는 참조 불가

var globalName = 'globalName'; // 전역변수

function outer() {
    console.log('외부에서 전역호출', globalName);// 외부에서 전역호출
    var outName = 'outName';

    function inner() {
        console.log('내부에서 전역호출', globalName); //내부에서 전역호출
        console.log('내부에서 외부호출', outName);
        var inName = 'inName';
    }
    inner();
}
outer();

console.log(outName); // outName is not defined
console.log(inName); // inName is not defined

 

 

렉시컬 스코프 (Lexical Scope) : (어휘적 범위) 함수는 선언될때 범위가 만들어진다.

var name = 'Mike';
function log() {
  console.log(name);
}

function wrapper() {
  var name = 'Sally';
  log();
}
wrapper();

호이스팅 관점에서의 차이

함수선언문은 함수 자체가 호이스팅 된다.

함수표현식은 함수 자체는 호이스팅 되지 않고, 변수가 호이스팅된다.

화살표함수는 함수표현식의 다른 표현(ES6에서 추가)으로 마찬가지로 함수는 호이스팅 되지 않고, 변수만 호이스팅된다.

선언하고, 사용하는게 정상적 로직이므로 함수표현식&화살표함수를 권장한다.

 

case1) 함수 선언문은, 런타임 이전에 엔진에서 먼저 실행되어서 함수 자체를 호이스팅 한다.

console.dir(plus) // output: ƒ plus(x, y)
console.log(plus(2, 5)) // output: 7

// 함수 선언문
function plus(x, y) {
	return x+y
}

 

case2) 함수 표현식은 런타임 이전에 변수에 undefined라고 초기화만 시켜두고, 런타임에서 객체가 된다.

console.dir(sub) // output: undefined
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function

// 함수 표현식 예시
var sub = function(x, y) {
    return x + y
}

 

case3) 화살표함수는 런타임 이전에 변수에 undefined라고 초기화만 시켜두고, 런타임에서 객체가 된다.

console.dir(sub) // output: undefined
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function

// 화살표 함수 예시
var sub = () => {
    return x + y
}

 

this 관점에서의 차이

 

- 화살표함수는

this 가 없다. 자기만의 this 가 없다. 이 this 를 찾을때 자기 스코프 안에서 없으면, 함수가 실행되는 위치에서 스코프를 뒤져본다. (스코프 체인 순서대로 뒤진다) 

bind, apply, call 사용불가

(참고) 이름도 없다. 익명함수 / arguments도 없다

 

- 함수선언문에서 

this의 값은 함수를 호출하는 방법에 의해 결정된다.

 

case1) 함수선언문에서 다른 호출방법에 의한 this

// 호출하는 방법에 따라 결정된다.
var someone = {
    name : 'Mike',
    who : function(){
        console.log(this)
    }
}

// 호출방법1 -> 누가호출했니? someone
someone.who();

var myWho = someone.who;
// 호출방법2 -> 누가호출했니? global(브라우저)
myWho();

 

case2) 함수선언문과 화살표함수에서의 this

-> 같은 결과를 냈지만, 함수선언문에서는 함수를 호출하는 방법에 의해 this 가 결정되기 때문에, global(브라우저) 가 불렀기 때문에 window 를 리턴한다.

화살표함수는 자체 this 가 없기 때문에, 스코프 체인 순서대로 this 를 찾는다. 가장 밖에 있는 global(브라우저)가 리턴된다.

// 함수선언문
function who() {
    console.log(this)
}

who()

// 화살표함수
const when = () =>{
    console.log(this)
}

when();

 

 

case3) 함수선언문은 누가 호출했는지 확인하여 someone을 this로 받아서 age를 잘 리턴하지만, 화살표함수는 자체 this 가 없기 때문에 스코프 체인에 의해 window로 올라가서 name을 찾으니 없어서 안나온다.

let someone = {
    age : 10,
    name : 'Mike',
    LogAge : function() {
        console.log(this.age);
    },
    LogName : ()=>{
        console.log(this.name)
    }
}

someone.LogAge();
someone.LogName();

 

 

case4) 함수선언문 안에!

함수선언문으로 버튼에 클릭 이벤트를 단 경우, -> 누가 호출했나? -> button 이 호출했다 -> this 는 button

함수선언문으로 버늩에 클릭 이벤트를 달고 + this 를 bind 한 경우 -> this 를 someone으로 묶어준다

화살표함수로 버튼에 클릭 이벤트를 단 경우, -> 화살표 함수는 this 가 없으니까, 스코프 체인에 의해 상위의 함수 선언문안에 있는 this 가 리턴되어, gender 값을 가져올 수 있다.

 

let someone = {
    age : 10,
    name : 'Mike',
    gender : 'Female',
    LogAge : function() {
        btn.addEventListener('click', function(){
        	console.log(this)
            console.log(this.age)
        })
    },
    LogName : function() {
        btn2.addEventListener('click', (function(){
            console.log(this.name)
        }).bind(this))
    },
    LogGender : function() {
        btn3.addEventListener('click', ()=> {
            console.log(this.gender)
        })
    },
    
}

 

generator 

yield는 제너레이터 함수 안에 존재

next는 함수 밖에서 호출되는 메서드, yield를 순서대로 부름

 

function* generateSequence() {
    yield 1;
    yield 2;
    return 3;
}

let generator = generateSequence();

console.log(generator.next()); // {value: 1, done: false}
console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

[실행결과]

 

어디서 많이 봤다.

어디서?

 

Symbol.iterator() 메소드가 반환하는 값 = interator

const array = [1, 2, 3];

// Symbol.iterator 메소드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// iterator는 next 메소드를 갖는다.
// next 메소드는 value, done 속성을 갖는 Result객체를 리턴한다
let iteratorResult = iterator.next();
console.log(iteratorResult); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

[실행결과]

 

그럼 이전에 이터러블이고, 이터레이터인 함수로 피보나치 수열을 만든 소스코드가 있다.

이 소스코드를 제너레이터로 변환 해보자

 

[이터러블&이터레이터 피보나치 함수]

function fibo(max) {
    let [pre, cur] = [0, 1]
    return {
        [Symbol.iterator]() {
            return this
        },
        next() {
            [pre, cur] = [cur, pre+cur]
            return {
                value : cur,
                done : cur <= max
            }
        }
    }
}

let fiboIter = fibo(10);
console.log(fiboIter.next())
console.log(fiboIter.next())

[실행결과]

 

[제너레이터로 구현한 피보나치 수열 함수]

function* fiboGen(max){
    let [pre, cur] = [0, 1]
    while(pre+cur <= max){
        [pre, cur] = [cur, pre+cur]
        yield cur
    }
}

let fiboGenIter = fiboGen(10)
console.log(fiboGenIter.next())
console.log(fiboGenIter.next())
console.log(fiboGenIter.next())
console.log(fiboGenIter.next())
console.log(fiboGenIter.next())
console.log(fiboGenIter.next())

[실행결과]

ES6에서 도입됨

이터러블은 데이터 공급자의 역할

다양한 이터러블이 각자의 순회방식을 갖는다면, 데이터 소비자는 모든 방식을 각각 지원해야한다.

효율성을 위해 프로토콜(규칙)을 정의

이터러블은 Lazy evaluation(지연평가)를 통해 값을 생성한다. 

100개의 값이 필요할때 처음부터 100개를 만드는 것이아니고, 하나씩 next -> next-> next로 하나씩 만든다.

할당이 이루어지기 전까지는 데이터를 생성하지 않는다.

 

iteration 프로토콜

데이터 컬렉션을 순회하기 위한 프로토콜(규칙)

이터레이션 프로토콜(규칙)을 준수한 객체는 for문으로 순회할 수 있고, spread문법으로 펼칠 수 있다.

이터레이션 프로토콜 (대분류) 안에 이터러블 프로토콜과 이터레이터 프로토콜이 있다.

 

 

iterable 프로토콜

- 순회 가능한 자료구조 (for 문)

- Spread 문법 적용가능 

- Symbol.iterator 메소드를 소유한다 -> iterator 를 리턴한다.

- iterable 프로토콜(규칙)을 준수한 객체를 iterable 이라 한다

 

interable 객체 예시 : Array

const array = [1, 2, 3];

// 배열은 Symbol.iterator 메소드를 소유한다.
// 따라서 배열은 이터러블 프로토콜을 준수한 이터러블이다.
console.log(Symbol.iterator in array); // true

// 이터러블 프로토콜을 준수한 배열은 for...of 문에서 순회 가능하다.
for (const item of array) {
  console.log(item);
}

[실행결과]

 

iterable 하지 않은 객체 예시 : Object

const obj = { a: 1, b: 2 };

// 일반 객체는 Symbol.iterator 메소드를 소유하지 않는다.
// 따라서 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
console.log(Symbol.iterator in obj); // false

// 이터러블이 아닌 일반 객체는 for...of 문에서 순회할 수 없다.
// TypeError: obj is not iterable
for (const p of obj) {
  console.log(p);
}

[실행결과]

t

 

iterator 프로토콜

- next 메소드 소유 -> (value, done) 프로퍼티를 갖는 iterator result 객체를 리턴한다.

- next 메소드는 이터러블의 각 요소를 순회하기 위한 포인터의 역할

- iterator 프로토콜(규칙)을 준수한 객체를 iterator 이라 한다

 

const array = [1, 2, 3];

// 배열은 Symbol.iterator 메소드를 소유한다.
// 따라서 배열은 이터러블 프로토콜을 준수한 이터러블이다.
console.log(Symbol.iterator in array); // true

// 이터러블 프로토콜을 준수한 배열은 for...of 문에서 순회 가능하다.
for (const item of array) {
  console.log(item);
}

// Symbol.iterator 메소드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// iterator는 next 메소드를 갖는다.
// next 메소드는 value, done 속성을 갖는 Result객체를 리턴한다
let iteratorResult = iterator.next();
console.log(iteratorResult); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

[실행결과]

 

Javascript ES6에서 제공하는 내장 이터러블

Array, String, Map, Set, TypedArray, DOM data structure, Arguments

Symbol 객체의 프로퍼티 중 length와 prototype을 제외한 프로퍼티들을 Well-Known Symbol 이라 부른다

이미지출처: 모던 자바스크립트 Deep Dive

이런 Well-Known Symbol 은 자바스크립트 엔진에 "상수"로 존재하며, 자바스크립트 엔진은 각각 이 상수들을 참조하여 일정한 처리를 한다.

예를 들어 어떤 객체가 Symbol.iterator 를 프로퍼티로 갖고 있으면(메소드로 가지고 있으면) 이 객체는 이터레이션 프로토콜을 따는 것으로 생각하고 이터레이터로 동작시킨다. -> 이터레이터를 커스텀하여 만들 수 있다!

Javascript 내장 이터러블들은 그럼, Symbol.iterator를 프로퍼티로 이미 갖고 있다는 뜻

 

* Symbol 은 ES6에서 추가된 원시 데이터 유형 (기존: Boolean, Null, Undefined, Number, String, +Symbol)

* Symbol("abc") 같은 문자열을 할당해도 다르게 인식된다, 고유한 존재

* Object에서 키값으로 Symbol을 사용하는 경우 : String과의 차별성, 객체에 같은 속성을 string으로 추가시, 에러가난다. Symbol로 추가시 충돌이 없다. 

 

for...of문

우리가 자주 사용하던 for문도 내부적으로 이터레이터의 next 메소드를 호출하여 이터러블을 순회하고, next 메소드가 반환하는 result 객체의 value 속성 값을 변수에 할당한다. 그리고 done 속성 값이 true가 될때까지 순회한다.

 

for문의 내부 동작 방식을 코드로 표현해보면 다음과 같다

// 이터러블
const iterable = [1, 2, 3];

// 이터레이터
const iterator = iterable[Symbol.iterator]();

for (;;) {
  // 이터레이터의 next 메소드를 호출하여 이터러블을 순회한다.
  const res = iterator.next();

  // next 메소드가 반환하는 이터레이터 리절트 객체의 done 프로퍼티가 true가 될 때까지 반복한다.
  if (res.done) break;

  console.log(res);
}

 

커스텀 이터러블

1) 이터러블 객체 만들기

const fibo = {
    [Symbol.iterator]() {
        let [pre, cur] = [0,1];
        const max = 10; // 10까지 피보나치

        // Symbol.iterator 메소드(지금 정의하는 메소드)는 iterator를 반환해야함
        // iterator는 next 메소드를 가져야함
        // next 메소드는 { value, done } 객체를 반환해야함
        return {
            next() {
                [pre, cur] = [cur, pre+cur];
                return {
                    value : cur,
                    done : cur >= max
                }
            }
        }
    }
}

for (const num of fibo) {
    console.log(num)
}

// spread 문법
console.log([...fibo])

// 디스트럭처링
const [first, second, ...rest] = fibo;
console.log(first, second, rest)

[실행 결과]

 

2) 이터러블을 생성하는 함수 만들기

function fiboIterableMaker(max) {
    let [pre, cur] = [0, 1];
    // Symbol.iterator 메소드(지금 정의하는 메소드)는 iterator를 반환해야함
    // iterator는 next 메소드를 가져야함
    // next 메소드는 { value, done } 객체를 반환해야함
    return {
        [Symbol.iterator]() {
            return {
                next() {
                    [pre, cur] = [cur, pre+cur];
                    return {
                        value : cur,
                        done : cur >= max
                    }
                }
            }
        }
    }
}

// 이터러블을 반환하는 함수에 이터러블의 최대값을 전달한다.
console.log(fiboIterableMaker(10))

for (const num of fiboIterableMaker(10)) {
    console.log(num); // 1 2 3 5 8
}

[실행결과]

 

3) 이터러블이면서 이터레이터 객체를 생성하는 함수 만들기

// 이터러블 & 이터레이터 객체를 반환
// 이터러블이려면 Symbol.iterator 메소드 가져야함
// 이터레이터는 next 메소드 가져야함
// next는 value, done 리절트 리턴해야함

function fiboIterableIterator(max){
    let [pre, cur] = [0,1]
    return {
        [Symbol.iterator](){
            return this; // 지금의 이터레이터를 리턴
        },
        next() {
            [pre, cur] = [cur, pre+cur];
            return {
                value : cur,
                done : cur >= max
            }
        }
    }
}

// iter는 이터러블
let iter = fiboIterableIterator(10);
console.log('iter', iter) //iter {next: ƒ, Symbol(Symbol.iterator): ƒ}

for (const num of iter) { 
    console.log(num) // 1,2,3,5,8
}

// iter는 이터레이터
console.log(iter.next()); //{value: 21, done: true}
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());

[실행결과]

 

특성 선택자란? 

주어진 특성의 존재 여부나 그 값에 따라 요소를 선택하는 것

<!-- html -->

<ul>
    <li><a title="hello" href="#">title link</a></li>
    <li><a className="hellologo" href="#internal">Internal link</a></li>
    <li><a href="https://example.com">https://example.com</a></li>
    <li><a href="#InSensitive">Insensitive internal link</a></li>
    <li><a href="http://example.org">http://example.org</a></li>
</ul>
/* css */

/* <a> elements with a title attribute */
a[title] {
  color: red;
}

/* <a> elements with an href matching "https://example.org" */
a[href="https://example.com"] {
  color: green;
}

/* <a> elements with an href containing "example" */
a[href*="example"] {
  font-size: 2em;
}

/* <a> elements with an href ending ".org" */
a[href$=".org"] {
  font-style: italic;
}

/* <a> elements whose class attribute contains the word "logo" */
a[class~="logo"] {
  padding: 2px;
}

 

[실행결과]

'programming > Web' 카테고리의 다른 글

[AWS] IAM 이란? (개념과 실습)  (0) 2022.04.05
API, SDK, Library, Framework  (0) 2022.03.10
REST Service에 대하여  (0) 2022.03.05
HTTP 헤더 총정리  (0) 2022.03.04
브라우저 저장소 비교 (localStorage, SessionStorage, Cookie)  (0) 2022.02.17

REST API란?

Representational State Transfer

웹을 좀 더 효율적으로 사용하기 위한 아키텍처

 

REST 구성

- 자원(URI)

- 행위(METHOD)

- 표현

 

REST 특징 ( 아직 모호한 개념 )

1) uniform interface : URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일

2) stateless (상태없음) : 작업을 위한 상태가 따로 없음. API는 들어오는 요청만 단순히 처리.

3) Cacheable(캐시가능): HTTP가 가진 캐싱 기능이 적용됨, HTTP프로토콜에서 사용하는 헤더(Last-modifed, E-tag)를 이용하여 캐싱 구현 가능

4) Self-descriptiveness(자체 표현 구조) : REST API 만 보고도 쉽게 이해할 수 있는 자체적으로 표현능력도 있음.

5) Client-Server 구조 : 서버는 API제공, 클라이언트는 사용자 인증, 컨텍스트(세션, 로그인정보) 등을 직접 관리하는 구조, 각각 역할이 확실히 구분된다.

6) 계층형 구조 : 다중 계층으로 구성될 수 있으며, 로드밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있음. 프록시나 게이트웨이 같은 네트워크 기반의 중간매체를 사용 가능

 

REST 설계 가이드

1) URI는 정보의 자원을 표현해야한다

2) 자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.

3) 마지막 문자 슬래시는 작성하지 않는다.

4) 너무 긴 리소스의 경우 하이픈(-)을 사용하여 의미상 구분하여 가독성을 올린다(언더바(_)는 사용 안함)

5) 소문자가 적합

6) 파일의 확장자는 URI에 포함시키지 않는다.

7) 컬렉션과 도큐먼트의 개념에 따라 단/복수를 지킨다.

8) 리소스명은 동사보다 명사를 사용

  • GET /members/delete/1/ ---(X)
  • DELETE /member/1 ---(O)
  • http:// restapi.example.com/sports/soccer/players/13 ---sports : 컬렉션, soccor : 도큐먼트, players : 컬렉션, 13 : 도큐먼트
  • GET : /users/{userid}/likes/devices (관계명이 애매하거나 구체적 표현이 필요할 때)

9) 물리적 URLs를 사용하지 마라.

10) 데이터가 너무 많으면 paging을 해라

11) 응답은 정제해서 보내라. 응답을 수정하지 마라

12) GET 요청은 서버/DB의 상태 변화를 일으키지 않는다.

13) POST/PUT/DELETE 요청만 서버/DB의 상태를 변화시킨다. 

14) 클라이언트가 추가적인 액션을 위해 URLs을 구성하도록 두지말고, 실제 URLs를 응답에 담아라. 

예를 들어, 제품 리스트를 요청했을 때, 디테일 정보를 위한 링크를 제공한다고 할때

제품별 ID값들을 리턴하여, 다음과 같은 URL을 제공하지 말고, http://www.acme.com/product/PRODUCT_ID ---(X)

응답에 각각의 item 별로 실제 actual URL 을 제공해야한다. http://www.acme.com/product/001263 --- (O)

 

 

참고 http://rest.elkstein.org/2008/02/rest-design-guidelines.html

 

9. REST Design Guidelines

Some soft guidelines for designing a REST architecture: Do not use "physical" URLs. A physical URL points at something physical -- e.g., an ...

rest.elkstein.org

 

[specific concept]

1. 조건에 따라 class 값 추가/제거

- isOpened라는 boolean 변수의 값에 따라 open 추가/없음 토글 됨

- @click 속성으로 toggleMenu 함수 실행됨

<div id="hamburger-icon" :class="{open: isOpened}" @click="toggleMenu">

 

[예제 코드]

1. /componets/NavBar.vue 만들기

<template>
<header>
  <div id="brand"><router-link to="/">HOME</router-link></div>
  <nav>
    <ul>
      <li><router-link to="/about">About</router-link></li>
      <li><router-link to="/user">Users</router-link></li>
    </ul>
  </nav>
  <div id="hamburger-icon" :class="{open: isOpened}" @click="toggleMenu">
    <div class="bar1"></div>
    <div class="bar2"></div>
    <div class="bar3"></div>
    <ul class="mobile-menu">
      <li><router-link to="/about">About</router-link></li>
      <li><router-link to="/user">Users</router-link></li>
    </ul>
  </div>
</header>
</template>

<script>
export default {
  data() {
    return {
      isOpened : false
    }
  },
  methods: {
    toggleMenu() {
      this.isOpened = !this.isOpened
    }
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
}
body {
  background-color: darkgray;
}
header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 50px;
  background-color: black;
  padding: 0 10px;
}
header a {
  text-decoration: none;
}
ul {
  display: flex;
  list-style: none;
  gap: 20px;
}
li a {
  color: white;
}
#hamburger-icon {
  display: none;
  cursor: pointer;
}
#hamburger-icon div {
  width: 35px;
  height: 3px;
  background-color: white;
  margin: 6px 0;
}
.open .bar1 {
  transform: rotate(-45deg) translate(-6px, 7px);
}
.open .bar2 {
  opacity: 0;
}
.open .bar3 {
  transform: rotate(45deg) translate(-6px, -7px);
}
#brand {
  font-size: 32px;
  font-weight: 700;
}
#brand a {
  color: coral;
}
.mobile-menu {
  display: none;
}
@media only screen and (max-width: 600px) {
  header nav {
    display: none;
  }

  #hamburger-icon {
    display: block;
  }
}
</style>

 

2. App.vue 템플릿 상단 NavBar 추가하기

<script setup>
import CardList from './components/CardList.vue'
import NavBar from './components/NavBar.vue'
</script>

<template>
  <!-- <CardList/> -->
  <!-- <div>
    <router-link to="/">HOME</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/user">Users</router-link>
  </div> -->
  <NavBar />
  <div>
    <router-view></router-view>
  </div>
</template>

<style>
* {
  padding : 0px;
  margin : 0px;
}
</style>

 

[실행결과]

1. main.js

props로 받겠다 true 설정

import { createApp } from 'vue'
import { createWebHistory, createRouter } from 'vue-router';
import App from './App.vue'
// router 쓰일 Component
import Home from './views/Home.vue';
import About from './views/About.vue';
import User from './views/User.vue';
import UserDetail from './views/UserDetail.vue';

//routes 정하기
const routes = [    
  { path : '/', component: Home, name:"home"},
  { path : '/about', component: About, name:'about2' },
  { path : '/user', component: User },
  { path : '/user/:id', component: UserDetail, props: true },
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

const app = createApp(App)
app.use(router)
app.mount('#app')

 

2. /view/UserDetail.vue

- params로 받거나

- props로 받기 가능

<template>
<h1>UserDetail</h1>
<h2>주소의 params로 받은 id : {{ $route.params.id }}</h2>
<div>props로 받은 id : {{ id }}</div>
</template>

<script>
export default {
  props : {
    id : String
  }
}
</script>

 

[실행결과]

1. view 폴더생성

2. 페이지 생성(About.vue, Home.vue, User.vue, UserDetail.vue)

// About.vue 내용 (Home, User, UserDetail 모두 동일)

<template>
About
</template>

 

3. main.js : routing 내용 설정

import { createApp } from 'vue';
import { createWebHistory, createRouter } from 'vue-router';
import App from './App.vue'
// router 쓰일 Component
import Home from './views/Home.vue';
import About from './views/About.vue';
import User from './views/User.vue';
import UserDetail from './views/UserDetail.vue';

//routes 정하기
const routes = [    
  { path : '/', component: Home },
  { path : '/about', component: About },
  { path : '/user', component: User },
  { path : '/user/:id', component: UserDetail },
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

const app = createApp(App)
app.use(router)
app.mount('#app')

 

 

4. App.vue 에 링크 생성

<script setup>
import CardList from './components/CardList.vue'
</script>

<template>
  <!-- <CardList/> -->
  <div>
    <router-link to="/">HOME</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/user">Users</router-link>
  </div>
  <div>
    <router-view></router-view>
  </div>
</template>

<style>
* {
  padding : 0px;
  margin : 0px;
}
</style>

 

[실행결과]

+ Recent posts