[DAY 36] Vue (4)
1. Node.js 와 npm
1) Node.js
: JavaScript 엔진으로 빌드 된 JavaScript 런타임
2) npm
: Node Packaged Manager, 모듈을 웹에서 받아서 설치하고 관리해주는 프로그램
+ nvm : Node.js의 버전을 관리해주는 프로그램
+ npm n : 맥 버전 node.js 버전 관리
nvm use 14 // node js 버전을 14버전으로 바꿈
2. npm 프로젝트 빌드
npm init
npm init -y // 질문 생략
1) package.json 파일 구성
{
"name": "프로젝트 이름",
"version": "1.0.0",
"description": "설명",
"scripts": {
// 사용자 빌드 키워드
},
"author": "",
"license": "ISC",
"devDependencies": {
// 개발 환경에서의 의존성
},
"dependencies": {
// 실제 프로젝트 관련 모듈(일반 의존성)
}
}
* 현재 만드는 뷰 프로젝트는 외부에서 접근할 진입점이 필요 없어서 main 옵션을 생략해도 된다.
* 버전에 ^ 표시는 그 버전 이상이라는 의미(2, 3번째 숫자만)
2) npm으로 뷰 설치
npm install vue // 기본 버전 설치
npm info vue // 뷰 설치 정보 보기
npm i vue@3.2.9 // 3.2.9 버전 설치
npm un(install) vue // 뷰 삭제
3. npx
: x는 동작한다는 의미. serve라는 패키지를 동작시킨다.
- npm도 설치되면 자동으로 npx 도 설치됨
📌 설치 방법
npx serve
npm i serve --save-dev(-D)
4. parcel
1) 설치 모듈
npm init -y
npm i vue
npm i -D parcel (devdependency 로 들어감)
2) 과정
ⓐ 루트 프로젝트에 index.html, main.js, App.vue 생성
ⓑ index.html에 main.js 불러오기
<script defer src="./main.js"></script>
*defer 옵션 쿼리셀렉터 가 정상적으로 실행될수 있게함
ⓒ main.js에 App 컴포넌트 불러오기
import * as Vue from "vue"; // 뷰는 따로 이름을 정해줘야함
import App from "./App.vue";
Vue.createApp(App).mount("#app");
ⓓ App.vue 작성
// 기본 구조
<template>
</template>
<script>
export default {
data() {
return {
};
},
};
</script>
<style lang="scss">
// scss 작성하려면 npm i sass -D 로 설치
</style>
"scripts": {
"dev": "parcel ./src/index.html",
"build": "parcel build ./src/index.html"
},
* script 내용을 실행할 때는 사용자 키워드 앞에 npm run을 붙여야 한다.
* 빌드하면 dist 폴더가 생성되고, 난독화된 html js파일이 들어있다.
node_modules/
.vscode/
.idea/
.DS_Store/
5. webpack
1) 설치 모듈
npm init -y
npm i -D webpack webpack-cli
2) 루트 디렉토리에 webpack.config.js 생성
const path = require("path");
module.exports = {
entry: "./src/main.js", // 시작 지점
output: {
path: path.resolve(__dirname, "dist"), // 절대 경로여야한다.
// filename: (default) main
},
};
* __dirname : 실행 시 현재 파일 경로로 바뀐다.(루트 디렉토리가 됨)
* path.resolve : 두 path를 합침 => 현재디렉토리/dist 경로가 됨
3) script 작성 후 빌드
"scripts": {
"build": "webpack"
},
* npm run build
* 명령어 실행 후 dist 폴더에 난독화된 합쳐진 코드파일이 만들어져 있다.
6. webpack으로 Vue 프로젝트 빌드
1) 설치 모듈
npm init -y
npm i vue vue-loader @vue/compiler-sfc
npm i -D webpack webpackcli webpack-dev-server
npm i -D html-webpack-plugin
npm i -D css-loader vue-style-loader
npm i -D sass sass-loader
npm i -D copy-webpack-plugin
npm i -D eslint eslint-plugin-vue
- npm init -y : 기본 설정으로 프로젝트 초기화
- vue, vue-loader : 뷰 관련 모듈, 웹펙으로 뷰를 로드하기 위한 모듈
- @vue/compiler-sfc : 뷰 파일을 컴파일 하기 위한 모듈(뷰랑 버전 같아야함)
- webpack : 웹팩 관련 모듈
- webpack-cli : 터미널에서 명령어를 입력할 수 있게하는 도구
- webpack-dev-server : 개발 서버를 오픈하는 용도의 모듈
- html-webpack-plugin : 웹팩 실행 결과물에 html 파일을 자동으로 작성해주는 도구
* 위 모듈이 없으면 dist 내 index.html 파일을 작성해줘야한다.
- css-loader vue-style-loader : css 파일 불러오기 위한 모듈/ vue css 로드하기위한 모듈
- sass sass-loader : sass 이용하기 위한 모듈
- copy-webpack-plugin 디렉토리를 카피하여 dist에 들어갈 수 있도록 설정하는 플러그인
* 이미지나 파비콘 사용할 때 보통 쓰는 플러그인
- eslint : 코드 작성 규칙 지정하는 모듈 (루트 경로에 .eslintrc.json 파일 생성 해야함)
2) webpack.config파일 작성
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "dist"),
clean: true,
},
- entry : 시작 지점 파일 경로
- output : 최종 파일 경로
* clean : 최종 경로에 쓸데없는 파일은 삭제해주는 옵
ⓑ module 옵션
module: {
rules: [
{
test: /\.vue$/,
use: "vue-loader",
},
{
test: /\.scss$/, // s?css 로하면 scss, css 둘다 가능
use: ["vue-style-loader", "css-loader", "sass-loader"],
},
],
},
- module안에는 객체리터럴로, rules 옵션을 정의한다.
- rules는 객체 배열 형태로 test에 정의한 정규표현식과 일치한 파일들을 use에 있는 모듈을 사용하게 해준다.
* /\.vue$/ : .vue 로 끝나는 파일
- use 옵션은 순서가 있음! 제일 왼쪽부터가 제일 나중에 로드되야 하는 모듈이다.
ⓑ plugins 옵션
const { VueLoaderPlugin } = require("vue-loader");
const HTMLPlugin = require("html-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
plugins: [
new VueLoaderPlugin(),
new HTMLPlugin({
template: "src/index.html",
}),
new CopyPlugin({
patterns: [
{
from: "static",
// to: 'dist'
},
],
}),
],
- 이 옵션을 사용하지 않으면 package.json파일 내 script에 직접 배포용인지 개발용인지 기입해 줘야한다.
"scripts": {
"dev": "webpack-dev-server --mode development", // 개발서버 오픈
"build": "webpack --mode production"
},
ⓓ devServer 옵션
devServer: {
port: 1234,
},
node modules에 설치된 패키지 이름을 그대로 가져와서 ㅆ르수이승ㅁ
패키지 안, index.js에 의해 export 되는거임
ⓔ resolve 옵션
resolve: {
extensions: [".vue", ".js"],
alias: {
"~": path.resolve(__dirname, "src"),
},
},
- extentsion: 프로젝트 파일에서 import할 때 해당 확장자 생략 가능
= webpack.config.js 전체 내용 =
✅ gitignore 파일
node_modules/
.vscode/
.idea/
.DS_Store/
dist/
7. 컴포넌트 등록
1) 등록 방법
ⓐ 전역 등록
import { createApp } from 'vue'
const app = createApp({})
app.component(MyComponent)
app.component('my-component', MyComponent) // my-component 이름으로 컴포넌트 사용
ⓑ 지역 등록
- 해당 컴포넌트 내 components 옵션에 불러오면된다.
<template>
<Hello />
</template>
<script>
import Hello from "~/components/Hello";
export default {
components: {
Hello,
},
};
</script>
3) props
ⓐ 기본 사용 방법
export default {
props: ['foo'],
created() {
console.log(this.foo) // 콘솔에 출력 가능
}
}
- props의 타입 지정을 할 수 있다.
export default {
props: {
title: String,
likes: [Number, String] // 둘 다 허용
}
}
📌 프롭스 대소문자 : props에서 카멜케이스로 써도 html에서는 케밥케이스로 작성해야한다.
- props로 postTitle라고 썼으면 html 태그 에서는 post-title 이라고 써야함
ⓑ props의 데이터
- 하위컴포넌트에서 상위 컴포넌트의 data를 직접적으로 수정할수 없다.
export default {
props: ['foo'],
created() {
// ❌ warning, props are readonly!
this.foo = 'bar'
}
}
4) non-props 속성
: props로 지정되지않은 나머지 속성들로 이루어진 객체
- 하위 컴포넌트에서 $attrs 로 가져올 수 있다.
<template>
<h1 :class="$attrs.class">{{ id }} / {{ title }} / {{ email }}</h1>
<h1>{{ id }} / {{ title }} / {{ email }}</h1>
</template>
- $attrs는 하위 컴포넌트의 내부 요소가 한 개일때 자동으로 하위 컴포넌트에 적용이 되는 속성임
inheritAttrs: false; // 상속 안되게 하기
5) 커스텀 이벤트
- 상위 컴포넌트의 데이터를 하위 컴포넌트에서 변경하기
ⓐ 상위 컴포넌트
<Hello :message="msg" @update="msg = $event" />
- 하위 컴포넌트에서 지정한 'update' 이벤트가 실행되게 함
- $event는 하위컴포넌트에서 작성한 $event.target.value가 들어온다.
ⓑ 하위 컴포넌트
<template>
<label>
<input
:value="message"
type="text"
@input="$emit('update', $event.target.value)"
/>
</label>
</template>
<script>
ex) 양방향 데이터 바인딩 사용하기
<Hello
v-model:message="msg"
v-model:name="name" />
<template>
<label>
<input
:value="message"
type="text"
@input="$emit('update:message', $event.target.value)"
/>
</label>
<label>
<input
:value="name"
type="text"
@input="$emit('update:name', $event.target.value)"
/>
</label>
</template>
<script>